From aeb385739167b3dc2a676399982a9ac3cf1f7cc2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Dec 2012 12:01:03 -0800 Subject: [PATCH 01/57] fixing unit tests Signed-off-by: Nikolaj Bjorner --- src/muz_qe/rel_context.h | 3 +-- src/smt/params/smt_params.cpp | 1 + src/smt/smt_model_checker.cpp | 1 + src/test/dl_context.cpp | 2 +- src/test/dl_product_relation.cpp | 9 +++++---- src/test/dl_query.cpp | 10 +++++----- src/test/dl_relation.cpp | 4 ++-- src/test/dl_table.cpp | 4 ++-- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/muz_qe/rel_context.h b/src/muz_qe/rel_context.h index 5fa2486b4..b05532d14 100644 --- a/src/muz_qe/rel_context.h +++ b/src/muz_qe/rel_context.h @@ -41,8 +41,6 @@ namespace datalog { fact_vector m_table_facts; void reset_negated_tables(); - - lbool saturate(); relation_plugin & get_ordinary_relation_plugin(symbol relation_name); @@ -109,6 +107,7 @@ namespace datalog { void display_output_facts(std::ostream & out) const; void display_facts(std::ostream & out) const; + lbool saturate(); }; }; diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 70f0ad811..691ec009d 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -29,6 +29,7 @@ void smt_params::updt_local_params(params_ref const & _p) { m_case_split_strategy = static_cast(p.case_split()); m_delay_units = p.delay_units(); m_delay_units_threshold = p.delay_units_threshold(); + m_proof_mode = _p.get_bool("produce_proofs", false)? PGM_FINE : PGM_DISABLED; } void smt_params::updt_params(params_ref const & p) { diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index 704c272ee..350ec333f 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -283,6 +283,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_proof_mode = m_manager.proof_mode(); } if (!m_aux_context) { symbol logic; diff --git a/src/test/dl_context.cpp b/src/test/dl_context.cpp index c004c531f..cdc9c52d9 100644 --- a/src/test/dl_context.cpp +++ b/src/test/dl_context.cpp @@ -60,7 +60,7 @@ void dl_context_saturate_file(params_ref & params, const char * f) { } dealloc(parser); std::cerr << "Saturating...\n"; - ctx.dl_saturate(); + ctx.get_rel_context().saturate(); std::cerr << "Done\n"; } diff --git a/src/test/dl_product_relation.cpp b/src/test/dl_product_relation.cpp index 4b67b32af..3fd81bc81 100644 --- a/src/test/dl_product_relation.cpp +++ b/src/test/dl_product_relation.cpp @@ -22,11 +22,12 @@ namespace datalog { void test_functional_columns(smt_params fparams, params_ref& params) { ast_manager m; context ctx(m, fparams); + rel_context& rctx = ctx.get_rel_context(); ctx.updt_params(params); - relation_manager & rmgr(ctx.get_rmanager()); + relation_manager & rmgr(rctx.get_rmanager()); sparse_table_plugin & plugin = - static_cast(*ctx.get_rmanager().get_table_plugin(symbol("sparse"))); + static_cast(*rctx.get_rmanager().get_table_plugin(symbol("sparse"))); SASSERT(&plugin); table_signature sig2; sig2.push_back(2); @@ -126,9 +127,9 @@ namespace datalog { context ctx(m, fparams); ctx.updt_params(params); dl_decl_util dl_util(m); - relation_manager & rmgr = ctx.get_rmanager(); + relation_manager & rmgr = ctx.get_rel_context().get_rmanager(); - relation_plugin & rel_plugin = *ctx.get_rmanager().get_relation_plugin(params.get_sym("default_relation", symbol("sparse"))); + relation_plugin & rel_plugin = *rmgr.get_relation_plugin(params.get_sym("default_relation", symbol("sparse"))); SASSERT(&rel_plugin); finite_product_relation_plugin plg(rel_plugin, rmgr); diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index 712ae386a..5e61c1836 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -49,7 +49,7 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, dl_decl_util decl_util(m); - context ctx_q(m, fparams); + context ctx_q(m, fparams); params.set_bool(":magic-sets-for-queries", use_magic_sets); ctx_q.updt_params(params); { @@ -57,7 +57,7 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, TRUSTME( p->parse_file(problem_file) ); dealloc(p); } - relation_manager & rel_mgr_q = ctx_b.get_rmanager(); + relation_manager & rel_mgr_q = ctx_b.get_rel_context().get_rmanager(); decl_set out_preds = ctx_b.get_output_predicates(); decl_set::iterator it = out_preds.begin(); @@ -68,10 +68,10 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, func_decl * pred_q = ctx_q.try_get_predicate_decl(symbol(pred_b->get_name().bare_str())); SASSERT(pred_q); - relation_base & rel_b = ctx_b.get_relation(pred_b); + relation_base & rel_b = ctx_b.get_rel_context().get_relation(pred_b); relation_signature sig_b = rel_b.get_signature(); - relation_signature sig_q = ctx_q.get_relation(pred_q).get_signature(); + relation_signature sig_q = ctx_q.get_rel_context().get_relation(pred_q).get_signature(); SASSERT(sig_b.size()==sig_q.size()); std::cerr << "Queries on random facts...\n"; @@ -209,7 +209,7 @@ void tst_dl_query() { TRUSTME( p->parse_file(problem_file) ); dealloc(p); } - ctx_base.dl_saturate(); + ctx_base.get_rel_context().saturate(); for(unsigned use_restarts=0; use_restarts<=1; use_restarts++) { params.set_uint(":initial-restart-timeout", use_restarts ? 100 : 0); diff --git a/src/test/dl_relation.cpp b/src/test/dl_relation.cpp index fe8ba1730..5daf3dc9b 100644 --- a/src/test/dl_relation.cpp +++ b/src/test/dl_relation.cpp @@ -12,7 +12,7 @@ namespace datalog { ast_manager ast_m; context ctx(ast_m, params); arith_util autil(ast_m); - relation_manager & m = ctx.get_rmanager(); + relation_manager & m = ctx.get_rel_context().get_rmanager(); m.register_plugin(alloc(interval_relation_plugin, m)); interval_relation_plugin& ip = dynamic_cast(*m.get_relation_plugin(symbol("interval_relation"))); SASSERT(&ip); @@ -115,7 +115,7 @@ namespace datalog { ast_manager ast_m; context ctx(ast_m, params); arith_util autil(ast_m); - relation_manager & m = ctx.get_rmanager(); + relation_manager & m = ctx.get_rel_context().get_rmanager(); m.register_plugin(alloc(bound_relation_plugin, m)); bound_relation_plugin& br = dynamic_cast(*m.get_relation_plugin(symbol("bound_relation"))); SASSERT(&br); diff --git a/src/test/dl_table.cpp b/src/test/dl_table.cpp index 6383dc1ab..0c8afcdc2 100644 --- a/src/test/dl_table.cpp +++ b/src/test/dl_table.cpp @@ -27,9 +27,9 @@ static void test_table(mk_table_fn mk_table) { smt_params params; ast_manager ast_m; datalog::context ctx(ast_m, params); - datalog::relation_manager & m = ctx.get_rmanager(); + datalog::relation_manager & m = ctx.get_rel_context().get_rmanager(); - ctx.get_rmanager().register_plugin(alloc(datalog::bitvector_table_plugin, ctx.get_rmanager())); + m.register_plugin(alloc(datalog::bitvector_table_plugin, m)); datalog::table_base* _tbl = mk_table(m, sig); datalog::table_base& table = *_tbl; From 3b51597dbecd2624410f46bef502e8b68e419ed1 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Dec 2012 12:05:07 -0800 Subject: [PATCH 02/57] fixing unit tests Signed-off-by: Nikolaj Bjorner --- src/smt/smt_model_checker.cpp | 1 - src/test/dl_query.cpp | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index cefdacef5..53f3af961 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -283,7 +283,6 @@ 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_proof_mode = m_manager.proof_mode(); } if (!m_aux_context) { symbol logic; diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index a642be9d6..4dc770056 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -49,13 +49,8 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, dl_decl_util decl_util(m); -<<<<<<< HEAD - context ctx_q(m, fparams); - params.set_bool(":magic-sets-for-queries", use_magic_sets); -======= context ctx_q(m, fparams); params.set_bool("magic_sets_for_queries", use_magic_sets); ->>>>>>> 3736c5ea3b97521dad85cdc6262151fae2875ec5 ctx_q.updt_params(params); { parser* p = parser::create(ctx_q,m); From 53cb389398f9492137fd00f198eba1e004872d5b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Dec 2012 13:05:14 -0800 Subject: [PATCH 03/57] fixing unit tests Signed-off-by: Nikolaj Bjorner --- src/smt/params/smt_params.cpp | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/smt/params/smt_params.cpp diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp new file mode 100644 index 000000000..70f0ad811 --- /dev/null +++ b/src/smt/params/smt_params.cpp @@ -0,0 +1,49 @@ +/*++ +Copyright (c) 2006 Microsoft Corporation + +Module Name: + + smt_params.cpp + +Abstract: + + + +Author: + + Leonardo de Moura (leonardo) 2008-02-20. + +Revision History: + +--*/ +#include"smt_params.h" +#include"smt_params_helper.hpp" + +void smt_params::updt_local_params(params_ref const & _p) { + smt_params_helper p(_p); + m_auto_config = p.auto_config(); + m_ematching = p.ematching(); + m_phase_selection = static_cast(p.phase_selection()); + m_restart_strategy = static_cast(p.restart_strategy()); + m_restart_factor = p.restart_factor(); + m_case_split_strategy = static_cast(p.case_split()); + m_delay_units = p.delay_units(); + m_delay_units_threshold = p.delay_units_threshold(); +} + +void smt_params::updt_params(params_ref const & p) { + preprocessor_params::updt_params(p); + qi_params::updt_params(p); + theory_arith_params::updt_params(p); + theory_bv_params::updt_params(p); + updt_local_params(p); +} + +void smt_params::updt_params(context_params const & p) { + m_auto_config = p.m_auto_config; + m_soft_timeout = p.m_timeout; + m_model = p.m_model; + m_model_validate = p.m_validate_model; + m_proof_mode = p.m_proof ? PGM_FINE : PGM_DISABLED; +} + From 188aea3fb109c0cff5196c57e0e016ba0e014e4f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Dec 2012 13:48:27 -0800 Subject: [PATCH 04/57] fix test Signed-off-by: Nikolaj Bjorner --- src/smt/params/smt_params.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 70f0ad811..f74798499 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -22,6 +22,8 @@ Revision History: void smt_params::updt_local_params(params_ref const & _p) { smt_params_helper p(_p); m_auto_config = p.auto_config(); + m_random_seed = p.random_seed(); + m_relevancy_lvl = p.relevancy(); m_ematching = p.ematching(); m_phase_selection = static_cast(p.phase_selection()); m_restart_strategy = static_cast(p.restart_strategy()); @@ -29,6 +31,11 @@ void smt_params::updt_local_params(params_ref const & _p) { m_case_split_strategy = static_cast(p.case_split()); m_delay_units = p.delay_units(); m_delay_units_threshold = p.delay_units_threshold(); + m_preprocess = _p.get_bool("preprocess", true); // hidden parameter + if (_p.get_bool("arith.greatest_error_pivot", false)) + m_arith_pivot_strategy = ARITH_PIVOT_GREATEST_ERROR; + else if (_p.get_bool("arith.least_error_pivot", false)) + m_arith_pivot_strategy = ARITH_PIVOT_LEAST_ERROR; } void smt_params::updt_params(params_ref const & p) { @@ -43,7 +50,5 @@ void smt_params::updt_params(context_params const & p) { m_auto_config = p.m_auto_config; m_soft_timeout = p.m_timeout; m_model = p.m_model; - m_model_validate = p.m_validate_model; - m_proof_mode = p.m_proof ? PGM_FINE : PGM_DISABLED; + m_model_validate = p.m_model_validate; } - From 8cc695eb7fa4cd013e625ee00fa0ff1e3f8004e4 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Mon, 3 Dec 2012 03:50:28 +0000 Subject: [PATCH 05/57] Change treatment of unsigned to avoid depending on unspecified behavior of recursive macros --- src/api/ml/build.sed | 6 +++--- src/api/ml/z3.idl | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/api/ml/build.sed b/src/api/ml/build.sed index e4434a5a1..d53a13713 100644 --- a/src/api/ml/build.sed +++ b/src/api/ml/build.sed @@ -1,7 +1,7 @@ # attempt to clean up the mess with 'unsigned' -s/__in unsigned __/__in __/g -s/__out unsigned __/__out __/g -s/__out_opt unsigned __/__out_opt __/g +s/ unsigned/ unsigned int/g +s/unsigned int long/unsigned long/g +s/unsigned int __/unsigned __/g # '@name ' -> 'Section: ' diff --git a/src/api/ml/z3.idl b/src/api/ml/z3.idl index 2450e387d..555835c88 100644 --- a/src/api/ml/z3.idl +++ b/src/api/ml/z3.idl @@ -91,11 +91,6 @@ quote(c,"#define xstr(s) str(s)"); quote(c,"#define str(s) #s"); -// CamlIDL (1.05) has a bug where it does not accept [unsigned] as a type, -// only as a specifier, so unsigned is defined to be unsigned int. -#define unsigned unsigned int - - // Suppress "warning C4090: 'function' : different 'const' qualifiers" as // CamlIDL does not seem to get this right. quote(c,"#pragma warning(disable:4090)"); From 192f51e9862ecb08d8f35271647a4f67b85d0c04 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Mon, 3 Dec 2012 03:51:04 +0000 Subject: [PATCH 06/57] Change to avoid relying on sed supporting disjunction or escaped control characters --- src/api/ml/add_error_checking.V3.sed | 2 +- src/api/ml/add_error_checking.sed | 81 ++++++++++++++++++---------- src/api/ml/build.sed | 2 +- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/api/ml/add_error_checking.V3.sed b/src/api/ml/add_error_checking.V3.sed index 170ca2d6b..7ec725b77 100644 --- a/src/api/ml/add_error_checking.V3.sed +++ b/src/api/ml/add_error_checking.V3.sed @@ -1,2 +1,2 @@ # Customize error handling for contexts created in ML: -s/Z3_API Z3_mk_context\(_rc\|\)(\(.*\))/Z3_API Z3_mk_context\1(\2) quote(dealloc,\"Z3_set_error_handler(_res, caml_z3_error_handler);\")/g +s/Z3_API Z3_mk_context(\(.*\))/Z3_API Z3_mk_context(\1) quote(dealloc,\"Z3_set_error_handler(_res, caml_z3_error_handler);\")/g diff --git a/src/api/ml/add_error_checking.sed b/src/api/ml/add_error_checking.sed index ede3275e1..71c06b9e4 100644 --- a/src/api/ml/add_error_checking.sed +++ b/src/api/ml/add_error_checking.sed @@ -3,14 +3,19 @@ # Add error checking epilogue for all Z3_API functions that accept two Z3_contexts :begincc -# add epilogue for two Z3_context parameters -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);\")\7/g - -# if a match was found, done with all Z3_contexts and Z3_theorys +# 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 +/Z3_API .*(.*)[ ]*$/b endcc # if incomplete prototype /Z3_API .*(.*/{ @@ -18,10 +23,14 @@ t endt # read another line N - # add epilogue for two Z3_context parameters - 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);\")\7/g - - # if a match was found, done with all Z3_contexts and Z3_theorys + # 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 @@ -31,14 +40,19 @@ t endt # Add error checking epilogue for all Z3_API functions that accept one Z3_context :beginc -# add epilogue for one Z3_context parameter -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")\5/g - -# if a match was found, done with all Z3_contexts and Z3_theorys +# 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 +/Z3_API .*(.*)[ ]*$/b endc # if incomplete prototype /Z3_API .*(.*/{ @@ -46,10 +60,14 @@ t endt # read another line N - # add epilogue for one Z3_context parameter - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")\5/g - - # if a match was found, done with all Z3_contexts and Z3_theorys + # 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 @@ -60,24 +78,33 @@ t endt # Add error checking epilogue for all Z3_API functions that accept a Z3_theory :begint -# add epilogue for one Z3_theory parameter -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));\")\5/g - -# if a match was found, done with all Z3_contexts and Z3_theorys +# 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 .*(.*)[ ]*$/b endt /Z3_API .*(.*/{ # read another line N - # add epilogue for one Z3_theory parameter - 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));\")\5/g - - # if a match was found, done with all Z3_theorys + # 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 diff --git a/src/api/ml/build.sed b/src/api/ml/build.sed index d53a13713..c7d1fc804 100644 --- a/src/api/ml/build.sed +++ b/src/api/ml/build.sed @@ -43,7 +43,7 @@ s/\\ / /g s/\\c \([^ .,:]*\)/[\1]/g # '#Z3_' -> 'Z3.' -s/#Z3_\([^ \n\.\t,)]*\)/{!Z3.\1}/g +s/#Z3_\([^ \.,) ]*\)/{!Z3.\1}/g # '/*@}*/' -> '' s/\/\*@{\*\///g From c9865606e683cf1421f92c3dd15c570e12ad46af Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Tue, 4 Dec 2012 03:23:10 +0000 Subject: [PATCH 07/57] Fixes for error handling in ml api --- src/api/ml/add_error_checking.V3.sed | 2 +- src/api/ml/error_handling.idl | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/api/ml/add_error_checking.V3.sed b/src/api/ml/add_error_checking.V3.sed index 7ec725b77..7df291520 100644 --- a/src/api/ml/add_error_checking.V3.sed +++ b/src/api/ml/add_error_checking.V3.sed @@ -1,2 +1,2 @@ # 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, caml_z3_error_handler);\")/g +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/error_handling.idl b/src/api/ml/error_handling.idl index cc49a91e4..5a2ec9915 100644 --- a/src/api/ml/error_handling.idl +++ b/src/api/ml/error_handling.idl @@ -53,6 +53,12 @@ Author: #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," @@ -64,7 +70,7 @@ quote(mlmli," exception Error of context * error_code "); quote(ml," -/* Register dynamically-generated exception tag for use from C */ +(* Register dynamically-generated exception tag for use from C *) let _ = Callback.register_exception \"Z3.Error\" (Error (Obj.magic None, OK)) "); @@ -108,7 +114,7 @@ quote(mlmli," exception Error of context * error_code "); quote(ml," -/* Register dynamically-generated exception tag for use from C */ +(* Register dynamically-generated exception tag for use from C *) let _ = Callback.register_exception \"Z3.Error\" (Error (Obj.magic None, OK)) "); @@ -116,9 +122,6 @@ quote(c," /* Error checking routine that does nothing */ void check_error_code(Z3_context c) {} -/* All contexts share the same handler */ -static value caml_error_handler = 0; - static void error_handler_static (Z3_context c, Z3_error_code e) { static struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; @@ -126,8 +129,8 @@ static void error_handler_static (Z3_context c, Z3_error_code e) value ctx_err[2]; ctx_err[0] = c2ml_Z3_context(&c); ctx_err[1] = camlidl_c2ml_z3_Z3_error_code(&e, &_ctxs); - if (caml_error_handler) { - caml_callback2(caml_error_handler, ctx_err[0], ctx_err[1]); + 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\"); @@ -141,7 +144,7 @@ static void error_handler_static (Z3_context c, Z3_error_code e) void ml2c_Z3_error_handler (value ml_handler, void* c_handler) { - caml_error_handler = ml_handler; + caml_z3_error_handler = ml_handler; c_handler = (void*)error_handler_static; } From 79be6ee6c217e45b421799b2e0bab2d139e3116e Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Tue, 4 Dec 2012 03:31:08 +0000 Subject: [PATCH 08/57] Update build system for ml api --- src/api/ml/Makefile | 14 +++++ src/api/ml/Makefile.build | 69 ++++++++++++++++++++++++ src/api/ml/generate_mlapi.sh | 53 ++++++++++++++++++ src/api/ml/postprocess.sed | 8 +++ src/api/ml/{build.sed => preprocess.sed} | 0 src/api/ml/reverse.sed | 3 ++ src/api/ml/{z3.idl => z3.0.idl} | 5 -- 7 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 src/api/ml/Makefile create mode 100644 src/api/ml/Makefile.build create mode 100755 src/api/ml/generate_mlapi.sh create mode 100644 src/api/ml/postprocess.sed rename src/api/ml/{build.sed => preprocess.sed} (100%) create mode 100644 src/api/ml/reverse.sed rename src/api/ml/{z3.idl => z3.0.idl} (98%) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile new file mode 100644 index 000000000..55f89fe1c --- /dev/null +++ b/src/api/ml/Makefile @@ -0,0 +1,14 @@ +# 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/Makefile.build b/src/api/ml/Makefile.build new file mode 100644 index 000000000..27c798bbf --- /dev/null +++ b/src/api/ml/Makefile.build @@ -0,0 +1,69 @@ +# 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 ../../z3.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/generate_mlapi.sh b/src/api/ml/generate_mlapi.sh new file mode 100755 index 000000000..dd8692833 --- /dev/null +++ b/src/api/ml/generate_mlapi.sh @@ -0,0 +1,53 @@ +#!/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/postprocess.sed b/src/api/ml/postprocess.sed new file mode 100644 index 000000000..f25f70cb7 --- /dev/null +++ b/src/api/ml/postprocess.sed @@ -0,0 +1,8 @@ +# 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/build.sed b/src/api/ml/preprocess.sed similarity index 100% rename from src/api/ml/build.sed rename to src/api/ml/preprocess.sed diff --git a/src/api/ml/reverse.sed b/src/api/ml/reverse.sed new file mode 100644 index 000000000..31ac563d2 --- /dev/null +++ b/src/api/ml/reverse.sed @@ -0,0 +1,3 @@ +# output lines of input in reverse order + +1!G;h;$!d diff --git a/src/api/ml/z3.idl b/src/api/ml/z3.0.idl similarity index 98% rename from src/api/ml/z3.idl rename to src/api/ml/z3.0.idl index 555835c88..3773a28e3 100644 --- a/src/api/ml/z3.idl +++ b/src/api/ml/z3.0.idl @@ -91,11 +91,6 @@ quote(c,"#define xstr(s) str(s)"); quote(c,"#define str(s) #s"); -// Suppress "warning C4090: 'function' : different 'const' qualifiers" as -// CamlIDL does not seem to get this right. -quote(c,"#pragma warning(disable:4090)"); - - #ifndef MLAPIV3 #define DEFINE_TYPE(T) typedef [abstract] void* T From 6a5de3384ce75c46c17493636e2deac236737f01 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Thu, 6 Dec 2012 00:42:30 +0000 Subject: [PATCH 09/57] Regenerate ml api --- src/api/ml/z3.ml | 404 ++--- src/api/ml/z3.mli | 3498 ++++++++++------------------------------- src/api/ml/z3_stubs.c | 401 +++-- 3 files changed, 1196 insertions(+), 3107 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 76536ef43..4d391c06f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -293,13 +293,12 @@ 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" @@ -349,7 +348,6 @@ external param_descrs_to_string : context -> param_descrs -> string (** Refined view of a {!symbol}. - - {b See also}: {!mk_symbol} - {b See also}: {!symbol_refine} *) @@ -368,33 +366,28 @@ external mk_string_symbol : context -> 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 *) + 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 *) + 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} *) @@ -751,9 +744,9 @@ external mk_set_subset : context -> ast -> ast -> ast 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_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 @@ -930,21 +923,18 @@ external get_app_arg : context -> app -> int -> ast (** 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_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 + | Term_var of int * sort external is_eq_ast : context -> ast -> ast -> bool = "camlidl_z3_Z3_is_eq_ast" @@ -1220,12 +1210,6 @@ external get_smtlib_sort : context -> int -> sort external get_smtlib_error : context -> string = "camlidl_z3_Z3_get_smtlib_error" -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_string" - -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_file" - external set_error : context -> error_code -> unit = "camlidl_z3_Z3_set_error" @@ -1235,6 +1219,12 @@ external get_error_msg_ex : context -> error_code -> string 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" @@ -1280,8 +1270,11 @@ external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> un external fixedpoint_set_predicate_representation : context -> fixedpoint -> func_decl -> symbol array -> unit = "camlidl_z3_Z3_fixedpoint_set_predicate_representation" -external fixedpoint_simplify_rules : context -> fixedpoint -> ast array -> func_decl array -> ast_vector - = "camlidl_z3_Z3_fixedpoint_simplify_rules" +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" @@ -1295,6 +1288,12 @@ external fixedpoint_get_param_descrs : context -> fixedpoint -> 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" @@ -1544,6 +1543,9 @@ external solver_get_num_scopes : context -> solver -> int 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" @@ -1597,18 +1599,15 @@ external stats_get_double_value : context -> stats -> int -> float = "camlidl_z3_Z3_stats_get_double_value" - (* 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 @@ -1622,24 +1621,17 @@ let find equal x a = 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 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 = @@ -1648,7 +1640,6 @@ let get_datatype_sort c s = ) 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) @@ -1665,7 +1656,6 @@ let sort_refine 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 @@ -1677,10 +1667,7 @@ let mk_sort c = function | 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 @@ -1749,19 +1736,16 @@ let mk_datatypes ctx generator = ) 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 + if is_int then Numeral_int (i, sort) else let is_int64, i = get_numeral_int64 c t in - if is_int64 then + if is_int64 then Numeral_int64 (i, sort) else if get_sort_kind c sort <> REAL_SORT then @@ -1770,14 +1754,11 @@ let rec numeral_refine c t = 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 @@ -1790,21 +1771,14 @@ let rec embed_numeral c = function 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 = +let get_pattern_terms c p = Array.init (get_pattern_num_terms c p) (get_pattern c p) - - -let term_refine c t = +let term_refine c t = match get_ast_kind c t with | NUMERAL_AST -> Term_numeral (numeral_refine c t) @@ -1815,35 +1789,29 @@ let term_refine c t = 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 -> + | 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 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 -> + | 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) -> *) - - - +(* | 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 @@ -1903,49 +1871,33 @@ let model_refine c m = () done; {sorts; consts; arrays; funcs} - - (* Extended parser API *) - -let get_smtlib_formulas c = +let get_smtlib_formulas c = Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c) - -let get_smtlib_assumptions 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 = +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 = +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 = +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 = +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 @@ -1970,7 +1922,7 @@ let _ = module V3 = struct -(* File generated from z3.idl *) +(* File generated from z3V3.idl *) type symbol and literals @@ -2205,6 +2157,15 @@ and ast_print_mode = | 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" @@ -2263,7 +2224,7 @@ external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_dec = "camlidl_z3V3_Z3_mk_list_sort" external mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor - = "camlidl_z3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" + = "camlidl_z3V3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" external del_constructor : context -> constructor -> unit = "camlidl_z3V3_Z3_del_constructor" @@ -2587,16 +2548,16 @@ 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_z3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" + = "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_z3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" + = "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_z3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" + = "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_z3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" + = "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" @@ -2605,10 +2566,10 @@ external mk_exists_const : context -> int -> app array -> pattern array -> ast - = "camlidl_z3V3_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_z3V3_Z3_mk_quantifier_const" + = "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_z3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" + = "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" @@ -2890,19 +2851,19 @@ 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_z3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_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_z3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" + = "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_z3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" + = "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_z3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" + = "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_z3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" + = "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" @@ -2931,15 +2892,15 @@ external get_smtlib_sort : context -> int -> sort external get_smtlib_error : context -> string = "camlidl_z3V3_Z3_get_smtlib_error" -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_string" - -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_file" - 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" @@ -3121,114 +3082,85 @@ 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 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 = +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 +type datatype_constructor_refined = { + constructor : func_decl; + recognizer : func_decl; + accessors : func_decl array } - -let get_datatype_sort c ty = +let get_datatype_sort c ty = Array.init (get_datatype_sort_num_constructors c ty) - (fun idx_c -> + (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 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 = +let get_smtlib_formulas c = Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c);; - -let get_smtlib_assumptions 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 = +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 = +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 = +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 = +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 @@ -3240,7 +3172,6 @@ type sort_refined = | 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) @@ -3250,56 +3181,50 @@ let sort_refine c ty = | 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 + | 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 = +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 +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 = + | 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 -> + | 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) + 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 -> + 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 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 -> + | 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 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 -> + | VAR_AST -> Term_var(get_index_value c t, get_sort c t) | _ -> assert false - -type theory_callbacks = +type theory_callbacks = { mutable delete_theory : unit -> unit; mutable reduce_eq : ast -> ast -> ast option; @@ -3318,8 +3243,7 @@ type theory_callbacks = mutable new_assignment: ast -> bool -> unit; mutable new_relevant : ast -> unit; } - -let mk_theory_callbacks() = +let mk_theory_callbacks() = { delete_theory = (fun () -> ()); reduce_eq = (fun _ _ -> None); @@ -3338,8 +3262,6 @@ let mk_theory_callbacks() = 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" @@ -3358,146 +3280,116 @@ external set_new_eq_callback_register : theory -> unit = "set_new_eq_callback_re 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 = +let is_some opt = match opt with | Some v -> true - | None -> false - -let get_some opt = + | None -> false +let get_some opt = match opt with | Some v -> v - | None -> failwith "None unexpected" - - - - + | None -> failwith "None unexpected" let apply_delete (th:theory_callbacks) = th.delete_theory () -let set_delete_callback th cb = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 = +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 diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index b0935f03c..4dd3d5b14 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -268,24 +268,17 @@ and goal_prec = (** - - *) (** {2 {L Types}} - - - Most of the types in the API are abstract. - - + 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. + - [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. @@ -301,23 +294,21 @@ and goal_prec = - [stats]: statistical data for a solver. *) (** - {!lbool} + {!lbool} Lifted Boolean type: [false], [undefined], [true]. *) (** - {!symbol_kind} + {!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} + {!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. @@ -327,229 +318,131 @@ and goal_prec = - PARAMETER_FUNC_DECL is used for function declaration parameters. *) (** - {!sort_kind} + {!sort_kind} The different kinds of Z3 types (See {!get_sort_kind}). *) (** - {!ast_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 + - 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} + {!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. - + 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_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. + - 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 @@ -557,19 +450,16 @@ and goal_prec = [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 + 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 @@ -577,10 +467,8 @@ and goal_prec = 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. - + It combines several symmetry and transitivity proofs. Example: {e T1: (R a b) @@ -589,13 +477,11 @@ and goal_prec = [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, + 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) @@ -605,58 +491,42 @@ and goal_prec = } 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. + - 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 + 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), + 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. @@ -666,44 +536,31 @@ and goal_prec = - 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 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: + - 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])) - + (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: - + - OP_PR_LEMMA: {e T1: false [lemma T1]: (or (not l_1) ... (not l_n)) @@ -711,22 +568,19 @@ and goal_prec = 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: + - OP_PR_UNIT_RESOLUTION: {e - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) ... - T(n+1): (not l_n) + T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') } - - - OP_PR_IFF_TRUE: + - OP_PR_IFF_TRUE: {e T1: p [iff-true T1]: (iff p true) } - - OP_PR_IFF_FALSE: {e T1: (not p) @@ -736,14 +590,14 @@ and goal_prec = - 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) @@ -772,7 +626,7 @@ and goal_prec = 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: @@ -788,17 +642,17 @@ and goal_prec = [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) Otherwise: - [def-intro]: (= n e) + [def-intro]: (= n e) - - OP_PR_APPLY_DEF: + - 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 @@ -813,7 +667,7 @@ and goal_prec = The quantifier is retained (unless the bound variables are eliminated). Example {e - T1: q ~ q_new + 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 @@ -822,7 +676,7 @@ and goal_prec = 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 @@ -843,24 +697,24 @@ and goal_prec = (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 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. + 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: - - 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 @@ -873,9 +727,9 @@ and goal_prec = 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. + 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. @@ -906,7 +760,7 @@ and goal_prec = {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 + 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 @@ -929,16 +783,16 @@ and goal_prec = - 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 + 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_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. + - OP_RA_UNION: Create the union or convex hull of two relations. The function takes two arguments. - OP_RA_WIDEN: Widen two relations. @@ -948,7 +802,7 @@ and goal_prec = The function takes one argument. - OP_RA_FILTER: Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. + 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. @@ -963,23 +817,23 @@ and goal_prec = 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. + + - 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. + - 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] + 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. @@ -999,10 +853,10 @@ and goal_prec = - OP_UNINTERPRETED: kind used for uninterpreted symbols. *) (** - {!param_kind} + {!param_kind} The different kinds of parameters that can be associated with parameter sets. - (see {!mk_params}). + (see {!mk_params}). - PK_UINT integer parameters. - PK_BOOL boolean parameters. @@ -1013,140 +867,113 @@ and goal_prec = - PK_INVALID invalid parameter. *) (** - {!search_failure} + {!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 + - 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} + {!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_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}. + {!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. + - 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. + - 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}. + - 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('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') + 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') *) (** 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 (** - {!goal_prec} + {!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_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. - + 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" (** - Summary: Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - {v - z3.exe -ini? - v} - - Only a few configuration parameters are mutable once the context is created. - The error handler is invoked when trying to modify an immutable parameter. - - - - {b See also}: {!mk_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_z3_Z3_update_param_value" (** - Summary: Get a configuration parameter. - - Returns [None] - if the parameter value does not exist. - - - - - {b See also}: {!mk_context } - + 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 @@ -1155,7 +982,6 @@ external get_param_value : context -> string -> string option (** 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 @@ -1168,10 +994,6 @@ external interrupt : context -> unit 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 @@ -1179,7 +1001,6 @@ external mk_params : context -> params (** 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 @@ -1187,7 +1008,6 @@ external params_set_bool : context -> params -> symbol -> bool -> unit (** 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 @@ -1195,7 +1015,6 @@ external params_set_uint : context -> params -> symbol -> int -> unit (** 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 @@ -1203,7 +1022,6 @@ external params_set_double : context -> params -> symbol -> float -> unit (** 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 @@ -1212,7 +1030,6 @@ external params_set_symbol : context -> params -> symbol -> symbol -> unit (** 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 @@ -1220,9 +1037,7 @@ external params_to_string : context -> params -> string (** 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 @@ -1233,7 +1048,6 @@ external params_validate : context -> params -> param_descrs -> unit *) (** 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 @@ -1241,7 +1055,6 @@ external param_descrs_get_kind : context -> param_descrs -> symbol -> param_kind (** 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 @@ -1249,9 +1062,7 @@ external param_descrs_size : context -> param_descrs -> int (** 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 @@ -1260,7 +1071,6 @@ external param_descrs_get_name : context -> param_descrs -> int -> symbol (** 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 @@ -1272,7 +1082,6 @@ external param_descrs_to_string : context -> param_descrs -> string (** Refined view of a {!symbol}. - - {b See also}: {!mk_symbol} - {b See also}: {!symbol_refine} *) @@ -1283,24 +1092,19 @@ type symbol_refined = (** 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}} + {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 @@ -1308,11 +1112,8 @@ external mk_int_symbol : context -> 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 @@ -1326,33 +1127,28 @@ external mk_string_symbol : context -> 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 *) + 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 *) + 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} *) @@ -1371,40 +1167,33 @@ type sort_refined = (** 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 (** - {4 {L Redundant low-level API}} + {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" (** - Summary: Create the Boolean type. - + 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 @@ -1412,24 +1201,19 @@ external mk_bool_sort : context -> 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_z3_Z3_mk_int_sort" (** - Summary: Create the real type. - + 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 @@ -1437,11 +1221,8 @@ external mk_real_sort : context -> 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 @@ -1449,27 +1230,21 @@ external mk_bv_sort : context -> int -> sort (** Summary: Create a named finite domain sort. - - To create constants that belong to the finite domain, + 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.} - + - {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" (** - Summary: Create an array type. - + 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 @@ -1477,14 +1252,8 @@ external mk_array_sort : context -> sort -> sort -> 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. @@ -1492,7 +1261,6 @@ external mk_array_sort : context -> sort -> sort -> sort @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 @@ -1500,28 +1268,20 @@ external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort (** Summary: Create a enumeration sort. - - [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], + [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 + 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 @@ -1529,13 +1289,7 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ (** 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. @@ -1545,7 +1299,6 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ @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 @@ -1554,19 +1307,17 @@ external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_dec (* (** 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] + @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. - + 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 @@ -1574,24 +1325,20 @@ external mk_constructor : context -> symbol -> symbol -> symbol array -> sort op (** 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" (** - Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. + 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 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 @@ -1599,11 +1346,9 @@ external mk_datatype : context -> symbol -> constructor array -> sort * construc (** 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 @@ -1611,12 +1356,9 @@ external mk_constructor_list : context -> constructor array -> 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 @@ -1624,28 +1366,24 @@ external del_constructor_list : context -> constructor_list -> unit (** 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 datattype 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" (** - Summary: Query constructor for declared functions. - + 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 @@ -1657,22 +1395,17 @@ external query_constructor : context -> constructor -> int -> func_decl * func_d *) (** 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]. - + 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 @@ -1680,9 +1413,7 @@ external mk_func_decl : context -> symbol -> sort array -> 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 @@ -1690,18 +1421,9 @@ external mk_app : context -> func_decl -> ast array -> ast (** Summary: Declare and create a constant. - - - - - - - - [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - + [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 @@ -1709,14 +1431,8 @@ external mk_const : context -> symbol -> sort -> ast (** 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 @@ -1724,17 +1440,9 @@ external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_de (** 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) [||]]. - - - + [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 @@ -1745,7 +1453,6 @@ external mk_fresh_const : context -> string -> sort -> ast *) (** Summary: Create an AST node representing [true]. - def_API('mk_true', AST, (_in(CONTEXT), )) *) external mk_true : context -> ast @@ -1753,7 +1460,6 @@ external mk_true : context -> ast (** Summary: Create an AST node representing [false]. - def_API('mk_false', AST, (_in(CONTEXT), )) *) external mk_false : context -> ast @@ -1762,51 +1468,40 @@ external mk_false : context -> ast (** Summary: \[ [ mk_eq c l r ] \] Create an AST node representing {e l = r }. - - The nodes [l] and [r] must have the same type. - + 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" (** - 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 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" (** - Summary: \[ [ mk_not c a ] \] + 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" (** - Summary: \[ [ mk_ite c t1 t2 t2 ] \] + 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 @@ -1815,9 +1510,7 @@ external mk_ite : context -> ast -> ast -> ast -> ast (** 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 @@ -1826,9 +1519,7 @@ external mk_iff : context -> ast -> ast -> ast (** 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 @@ -1837,37 +1528,25 @@ external mk_implies : context -> ast -> ast -> ast (** 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" (** - - Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. - - + 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" (** - - Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. - - + 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 @@ -1877,110 +1556,78 @@ external mk_or : context -> ast array -> ast {2 {L Arithmetic: Integers and Reals}} *) (** - - Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. - - + 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" (** - - Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. - - + 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" (** - - Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. - - + 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" (** - - Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. - + 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" (** - - Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. - + 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" (** - - Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. - + 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" (** - - Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. - + 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 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" (** - Summary: \[ [ mk_lt c t1 t2 ] \] + 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 @@ -1989,9 +1636,7 @@ external mk_lt : context -> ast -> ast -> ast (** 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 @@ -2000,9 +1645,7 @@ external mk_le : context -> ast -> ast -> ast (** 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 @@ -2011,9 +1654,7 @@ external mk_gt : context -> ast -> ast -> ast (** 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 @@ -2022,19 +1663,14 @@ external mk_ge : context -> ast -> ast -> ast (** 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 + 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 }. - + 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 @@ -2043,13 +1679,10 @@ external mk_int2real : context -> ast -> ast (** 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 @@ -2058,10 +1691,8 @@ external mk_real2int : context -> ast -> ast (** 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 @@ -2073,9 +1704,7 @@ external mk_is_int : context -> ast -> ast (** 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 @@ -2084,9 +1713,7 @@ external mk_bvnot : context -> ast -> ast (** 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 @@ -2095,9 +1722,7 @@ external mk_bvredand : context -> ast -> ast (** 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 @@ -2106,9 +1731,7 @@ external mk_bvredor : context -> ast -> ast (** 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 @@ -2117,9 +1740,7 @@ external mk_bvand : context -> ast -> 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 @@ -2128,9 +1749,7 @@ external mk_bvor : context -> ast -> ast -> ast (** 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 @@ -2138,10 +1757,8 @@ external mk_bvxor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnand c t1 t2 ] \] - Bitwise nand. - + 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 @@ -2149,10 +1766,8 @@ external mk_bvnand : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnor c t1 t2 ] \] - Bitwise nor. - + 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 @@ -2160,10 +1775,8 @@ external mk_bvnor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvxnor c t1 t2 ] \] - Bitwise xnor. - + 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 @@ -2172,9 +1785,7 @@ external mk_bvxnor : context -> ast -> ast -> ast (** 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 @@ -2183,9 +1794,7 @@ external mk_bvneg : context -> ast -> ast (** 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 @@ -2194,9 +1803,7 @@ external mk_bvadd : context -> ast -> ast -> ast (** 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 @@ -2205,9 +1812,7 @@ external mk_bvsub : context -> ast -> ast -> ast (** 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 @@ -2215,14 +1820,11 @@ external mk_bvmul : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvudiv c t1 t2 ] \] - Unsigned division. - + 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 @@ -2231,17 +1833,11 @@ external mk_bvudiv : context -> ast -> ast -> ast (** 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 @@ -2250,13 +1846,9 @@ external mk_bvsdiv : context -> ast -> ast -> ast (** 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 @@ -2265,16 +1857,11 @@ external mk_bvurem : context -> ast -> ast -> ast (** 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 @@ -2283,13 +1870,9 @@ external mk_bvsrem : context -> ast -> ast -> ast (** 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 @@ -2298,9 +1881,7 @@ external mk_bvsmod : context -> ast -> ast -> ast (** 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 @@ -2309,17 +1890,14 @@ external mk_bvult : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvslt c t1 t2 ] \] Two's complement signed less than. - It abbreviates: - {v + {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 @@ -2328,9 +1906,7 @@ external mk_bvslt : context -> ast -> ast -> ast (** 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 @@ -2339,9 +1915,7 @@ external mk_bvule : context -> ast -> ast -> ast (** 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 @@ -2350,9 +1924,7 @@ external mk_bvsle : context -> ast -> ast -> ast (** 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 @@ -2361,9 +1933,7 @@ external mk_bvuge : context -> ast -> ast -> ast (** 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 @@ -2372,9 +1942,7 @@ external mk_bvsge : context -> ast -> ast -> ast (** 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 @@ -2383,9 +1951,7 @@ external mk_bvugt : context -> ast -> ast -> ast (** 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 @@ -2394,12 +1960,9 @@ external mk_bvsgt : context -> ast -> ast -> ast (** 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 @@ -2410,9 +1973,7 @@ external mk_concat : context -> ast -> ast -> ast 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 @@ -2423,9 +1984,7 @@ external mk_extract : context -> int -> int -> ast -> ast 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 @@ -2433,12 +1992,10 @@ external mk_sign_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_zero_ext c i t1 ] \] - Extend the given bit-vector with zeros to the (unsigned int) equivalent + 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. - + 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 @@ -2447,9 +2004,7 @@ external mk_zero_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_repeat c i t1 ] \] Repeat the given bit-vector up length {e i }. - - The node [t1] must have a bit-vector sort. - + 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 @@ -2458,16 +2013,12 @@ external mk_repeat : context -> int -> ast -> ast (** 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 + 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 @@ -2476,16 +2027,12 @@ external mk_bvshl : context -> ast -> ast -> ast (** 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 + 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 @@ -2494,17 +2041,13 @@ external mk_bvlshr : context -> ast -> ast -> ast (** 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 + 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 @@ -2513,9 +2056,7 @@ external mk_bvashr : context -> ast -> ast -> ast (** 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. - + 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 @@ -2524,9 +2065,7 @@ external mk_rotate_left : context -> int -> ast -> ast (** 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. - + 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 @@ -2535,9 +2074,7 @@ external mk_rotate_right : context -> int -> ast -> ast (** 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 @@ -2546,9 +2083,7 @@ external mk_ext_rotate_left : context -> ast -> ast -> ast (** 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 @@ -2557,13 +2092,10 @@ external mk_ext_rotate_right : context -> ast -> ast -> ast (** 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. + 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. - + 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 @@ -2572,17 +2104,14 @@ external mk_int2bv : context -> int -> ast -> ast (** 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. + 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. + 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. - + 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 @@ -2592,9 +2121,7 @@ external mk_bv2int : context -> ast -> bool -> ast 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 @@ -2604,9 +2131,7 @@ external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast 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 @@ -2616,9 +2141,7 @@ external mk_bvadd_no_underflow : context -> ast -> ast -> ast 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 @@ -2628,9 +2151,7 @@ external mk_bvsub_no_overflow : context -> ast -> ast -> ast 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 @@ -2638,11 +2159,9 @@ external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast (** Summary: \[ [ mk_bvsdiv_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed division + 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 @@ -2650,11 +2169,9 @@ external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvneg_no_overflow c t1 ] \] - Check that bit-wise negation does not overflow when + 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 @@ -2664,9 +2181,7 @@ external mk_bvneg_no_overflow : context -> ast -> ast 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 @@ -2676,9 +2191,7 @@ external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast 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 @@ -2690,15 +2203,12 @@ external mk_bvmul_no_underflow : context -> ast -> ast -> ast (** 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] }, + 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 @@ -2707,18 +2217,15 @@ external mk_select : context -> ast -> ast -> ast (** 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: + 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 + 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 @@ -2726,14 +2233,11 @@ external mk_store : context -> ast -> ast -> ast -> ast (** Summary: Create the constant array. - - The resulting term is an array, such that a [select] on an arbitrary index + 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 @@ -2742,15 +2246,12 @@ external mk_const_array : context -> sort -> ast -> ast (** 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 }. + 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 @@ -2758,12 +2259,10 @@ external mk_map : context -> func_decl -> int -> ast -> ast (** Summary: Access the array default value. - Produces the default range value, for arrays that can be represented as + 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 @@ -2774,7 +2273,6 @@ external mk_array_default : context -> ast -> ast *) (** Summary: Create Set type. - def_API('mk_set_sort', SORT, (_in(CONTEXT), _in(SORT))) *) external mk_set_sort : context -> sort -> sort @@ -2782,7 +2280,6 @@ external mk_set_sort : context -> sort -> sort (** Summary: Create the empty set. - def_API('mk_empty_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_empty_set : context -> sort -> ast @@ -2790,7 +2287,6 @@ external mk_empty_set : context -> sort -> ast (** Summary: Create the full set. - def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_full_set : context -> sort -> ast @@ -2798,9 +2294,7 @@ external mk_full_set : context -> sort -> ast (** 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 @@ -2808,9 +2302,7 @@ external mk_set_add : context -> ast -> ast -> ast (** 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 @@ -2818,7 +2310,6 @@ external mk_set_del : context -> ast -> ast -> ast (** 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 @@ -2826,7 +2317,6 @@ external mk_set_union : context -> ast array -> ast (** 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 @@ -2834,7 +2324,6 @@ external mk_set_intersect : context -> ast array -> ast (** 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 @@ -2842,7 +2331,6 @@ external mk_set_difference : context -> ast -> ast -> ast (** Summary: Take the complement of a set. - def_API('mk_set_complement', AST, (_in(CONTEXT), _in(AST))) *) external mk_set_complement : context -> ast -> ast @@ -2850,9 +2338,7 @@ external mk_set_complement : context -> ast -> ast (** 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 @@ -2860,7 +2346,6 @@ external mk_set_member : context -> ast -> ast -> ast (** 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 @@ -2874,32 +2359,27 @@ external mk_set_subset : context -> ast -> ast -> ast 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_int of int * sort + | Numeral_int64 of int64 * sort + | Numeral_large of string * sort | Numeral_rational of numeral_refined * numeral_refined (** Summary: \[ [ embed_numeral c nr ] \] constructs the numeral described by [nr]. - - {b See also}: {!numeral_refine} *) val embed_numeral: context -> numeral_refined -> ast (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** - Summary: Create a numeral of a given sort. - + 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. - + @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 @@ -2907,43 +2387,32 @@ external mk_numeral : context -> string -> sort -> ast (** 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" (** - Summary: Create a numeral of an int, bit-vector, or finite-domain sort. - + 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" (** - Summary: Create a numeral of a int, bit-vector, or finite-domain sort. - + 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 @@ -2954,22 +2423,17 @@ external mk_int64 : context -> int64 -> sort -> ast *) (** 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 + 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 @@ -2977,12 +2441,10 @@ external mk_pattern : context -> ast array -> 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 + {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 @@ -2990,18 +2452,14 @@ external mk_pattern : context -> ast array -> pattern 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 @@ -3010,21 +2468,17 @@ external mk_bound : context -> int -> sort -> ast (** 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 + 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. - - + 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. @@ -3033,11 +2487,9 @@ external mk_bound : context -> int -> sort -> ast @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 @@ -3045,21 +2497,18 @@ external mk_forall : context -> int -> pattern array -> sort array -> symbol arr (** 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" (** - Summary: Create a quantifier - universal or existential, with pattern hints. + 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. @@ -3069,12 +2518,10 @@ external mk_exists : context -> int -> pattern array -> sort array -> symbol arr @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 @@ -3082,7 +2529,6 @@ external mk_quantifier : context -> bool -> int -> pattern array -> sort array - (** 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 @@ -3096,12 +2542,10 @@ external mk_quantifier : context -> bool -> int -> pattern array -> sort array - @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 @@ -3110,19 +2554,16 @@ external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> patter (** 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 + @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 @@ -3130,42 +2571,36 @@ external mk_forall_const : context -> int -> app array -> pattern array -> ast - (** 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 + @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 + 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 + 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 @@ -3175,7 +2610,7 @@ external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> {2 {L Accessors}} *) (** - {3 {L Symbols}} + {3 {L Symbols}} *) (** @@ -3184,13 +2619,12 @@ external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> val symbol_refine: context -> symbol -> symbol_refined (** - {4 {L Redundant low-level API}} + {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 @@ -3198,12 +2632,9 @@ external get_symbol_kind : context -> symbol -> symbol_kind (** Summary: \[ [ get_symbol_int c s ] \] - Return the symbol int value. - + 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 @@ -3211,23 +2642,16 @@ external get_symbol_int : context -> symbol -> int (** Summary: \[ [ get_symbol_string c s ] \] - Return the symbol name. - + 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}} + {3 {L Sorts}} *) (** @@ -3236,8 +2660,7 @@ external get_symbol_string : context -> symbol -> string val sort_refine: context -> sort -> sort_refined (** - Summary: Return the sort name as a symbol. - + 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 @@ -3245,20 +2668,18 @@ external get_sort_name : context -> sort -> symbol (** Summary: Return a unique identifier for [s]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {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}} + {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)]. - + 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 @@ -3266,8 +2687,7 @@ external sort_to_ast : context -> sort -> ast (** Summary: compare sorts. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {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 @@ -3275,9 +2695,7 @@ external is_eq_sort : context -> sort -> sort -> 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 @@ -3285,23 +2703,18 @@ external get_sort_kind : context -> sort -> sort_kind (** Summary: \[ [ get_bv_sort_size c t ] \] - Return the size of the given bit-vector sort. - + 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. + 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 @@ -3310,26 +2723,20 @@ external get_finite_domain_sort_size : context -> sort -> int64 option (** 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. - + 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 @@ -3338,13 +2745,10 @@ external get_array_sort_range : context -> sort -> sort (** Summary: \[ [ get_tuple_sort_mk_decl c t ] \] Return the constructor declaration of the given tuple - sort. - + 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 @@ -3352,13 +2756,10 @@ external get_tuple_sort_mk_decl : context -> sort -> func_decl (** Summary: \[ [ get_tuple_sort_num_fields c t ] \] - Return the number of fields of the given tuple sort. - + 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 @@ -3367,14 +2768,11 @@ external get_tuple_sort_num_fields : context -> sort -> int (** 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. - + 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 @@ -3382,13 +2780,10 @@ external get_tuple_sort_field_decl : context -> sort -> int -> func_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 @@ -3396,14 +2791,11 @@ external get_datatype_sort_num_constructors : context -> sort -> int (** 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 @@ -3411,14 +2803,11 @@ external get_datatype_sort_constructor : context -> sort -> int -> func_decl (** 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 @@ -3426,15 +2815,12 @@ external get_datatype_sort_recognizer : context -> sort -> int -> func_decl (** 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 @@ -3442,11 +2828,8 @@ external get_datatype_sort_constructor_accessor : context -> sort -> int -> int (** 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 @@ -3454,24 +2837,20 @@ external get_relation_arity : context -> sort -> int (** 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}} + {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)]. - + 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 @@ -3479,8 +2858,7 @@ external func_decl_to_ast : context -> func_decl -> ast (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {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 @@ -3488,16 +2866,14 @@ external is_eq_func_decl : context -> func_decl -> func_decl -> bool (** Summary: Return a unique identifier for [f]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {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. - + 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 @@ -3505,7 +2881,6 @@ external get_decl_name : context -> func_decl -> symbol (** 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 @@ -3513,9 +2888,7 @@ external get_decl_kind : context -> func_decl -> 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 @@ -3523,9 +2896,7 @@ external get_domain_size : context -> func_decl -> int (** 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 @@ -3534,11 +2905,8 @@ external get_arity : context -> func_decl -> int (** 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 @@ -3547,7 +2915,6 @@ external get_domain : context -> func_decl -> int -> sort (** Summary: \[ [ get_domains c d ] \] is the array of parameters of [d]. - - {b See also}: {!get_domain_size} - {b See also}: {!get_domain} *) @@ -3555,11 +2922,9 @@ val get_domains: context -> func_decl -> sort array (** Summary: \[ [ get_range c d ] \] - Return the range of the given declaration. - + 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 @@ -3567,7 +2932,6 @@ external get_range : context -> func_decl -> sort (** 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 @@ -3575,11 +2939,9 @@ external get_decl_num_parameters : context -> func_decl -> int (** 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 @@ -3587,9 +2949,7 @@ external get_decl_parameter_kind : context -> func_decl -> int -> 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 @@ -3597,9 +2957,7 @@ external get_decl_int_parameter : context -> func_decl -> int -> int (** 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 @@ -3607,9 +2965,7 @@ external get_decl_double_parameter : context -> func_decl -> int -> float (** 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 @@ -3617,9 +2973,7 @@ external get_decl_symbol_parameter : context -> func_decl -> int -> symbol (** 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 @@ -3627,9 +2981,7 @@ external get_decl_sort_parameter : context -> func_decl -> int -> sort (** 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 @@ -3637,9 +2989,7 @@ external get_decl_ast_parameter : context -> func_decl -> int -> ast (** 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 @@ -3647,21 +2997,18 @@ external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl (** 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}} + {3 {L Applications}} *) (** - Summary: Convert a [app] into [ast]. - - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. - + 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 @@ -3669,7 +3016,6 @@ external app_to_ast : context -> app -> 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 @@ -3679,7 +3025,6 @@ external get_app_decl : context -> app -> func_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 @@ -3688,9 +3033,7 @@ external get_app_num_args : context -> app -> int (** 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 @@ -3699,44 +3042,37 @@ external get_app_arg : context -> app -> int -> ast (** 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}} + {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_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 + | 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]. *) @@ -3744,8 +3080,7 @@ val term_refine : context -> ast -> term_refined (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {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 @@ -3753,8 +3088,7 @@ external is_eq_ast : context -> ast -> ast -> bool (** 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]. - + - {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 @@ -3762,8 +3096,7 @@ external get_ast_id : context -> ast -> int (** 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]. - + - {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 @@ -3771,9 +3104,7 @@ external get_ast_hash : context -> ast -> int (** 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 @@ -3781,7 +3112,6 @@ external get_sort : context -> ast -> 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 @@ -3789,7 +3119,6 @@ external is_well_sorted : context -> ast -> 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 @@ -3797,14 +3126,13 @@ external get_bool_value : context -> ast -> lbool (** 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))) + def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) *) external is_app : context -> ast -> bool = "camlidl_z3_Z3_is_app" @@ -3817,17 +3145,14 @@ external is_numeral_ast : context -> ast -> 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_z3_Z3_is_algebraic_number" (** - Summary: Convert an [ast] into an [APP_AST]. - - - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} - + 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 @@ -3835,33 +3160,28 @@ external to_app : context -> ast -> 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} - + - {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}} + {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}} + {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 @@ -3870,19 +3190,15 @@ external get_numeral_string : context -> ast -> 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))) + 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 @@ -3890,9 +3206,7 @@ external get_numerator : context -> ast -> ast (** 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 @@ -3900,16 +3214,12 @@ external get_denominator : context -> ast -> ast (** 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 @@ -3919,11 +3229,8 @@ external get_numeral_small : context -> ast -> bool * int64 * int64 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 @@ -3933,11 +3240,8 @@ external get_numeral_int : context -> ast -> bool * 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 @@ -3947,47 +3251,39 @@ external get_numeral_int64 : context -> ast -> bool * 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. + 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. + 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}} + {4 {L Patterns}} *) (** - Summary: Convert a pattern into ast. - - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. - + 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 @@ -3996,7 +3292,6 @@ external pattern_to_ast : context -> pattern -> 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} *) @@ -4004,7 +3299,6 @@ 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 @@ -4012,20 +3306,17 @@ external get_pattern_num_terms : context -> pattern -> int (** 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}} + {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 @@ -4033,29 +3324,23 @@ external get_index_value : context -> ast -> int (** Summary: Determine if quantifier is universal. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - - def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(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))) + 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 @@ -4063,9 +3348,7 @@ external get_quantifier_num_patterns : context -> ast -> int (** 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 @@ -4073,9 +3356,7 @@ external get_quantifier_pattern_ast : context -> ast -> int -> pattern (** 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 @@ -4083,9 +3364,7 @@ external get_quantifier_num_no_patterns : context -> ast -> int (** 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 @@ -4093,9 +3372,7 @@ external get_quantifier_no_pattern_ast : context -> ast -> int -> 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 @@ -4103,9 +3380,7 @@ external get_quantifier_num_bound : context -> ast -> int (** 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 @@ -4113,9 +3388,7 @@ external get_quantifier_bound_name : context -> ast -> int -> symbol (** 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 @@ -4123,22 +3396,18 @@ external get_quantifier_bound_sort : context -> ast -> int -> 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}} + {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 @@ -4146,11 +3415,9 @@ external simplify : context -> ast -> ast (** 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 + 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 @@ -4158,7 +3425,6 @@ external simplify_ex : context -> ast -> params -> ast (** Summary: Return a string describing all available parameters. - def_API('simplify_get_help', STRING, (_in(CONTEXT),)) *) external simplify_get_help : context -> string @@ -4166,7 +3432,6 @@ external simplify_get_help : context -> string (** 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 @@ -4177,10 +3442,9 @@ external simplify_get_param_descrs : context -> param_descrs *) (** Summary: Update the arguments of term [a] using the arguments [args]. - The number of arguments [num_args] should coincide + 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 @@ -4190,7 +3454,6 @@ external update_term : context -> ast -> ast array -> ast 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 @@ -4199,7 +3462,6 @@ external substitute : context -> ast -> ast array -> ast array -> ast (** 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 @@ -4209,7 +3471,6 @@ external substitute_vars : context -> ast -> ast array -> ast 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 @@ -4232,45 +3493,36 @@ type model_refined = { } -(** +(** 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. - + 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}} + {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]. + 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 @@ -4278,15 +3530,10 @@ external model_get_const_interp : context -> model -> func_decl -> ast option (** Summary: Return the interpretation of the function [f] in the model [m]. - Return [None], - if the model does not assign an interpretation for [f]. + 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 @@ -4294,9 +3541,7 @@ external model_get_func_interp : context -> model -> func_decl -> func_interp op (** 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 @@ -4304,12 +3549,9 @@ external model_get_num_consts : context -> model -> int (** Summary: \[ [ model_get_const_decl c m i ] \] - Return the i-th constant in the given model. - + 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 @@ -4317,10 +3559,8 @@ external model_get_const_decl : context -> model -> int -> func_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 @@ -4329,11 +3569,8 @@ external model_get_num_funcs : context -> model -> int (** 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 @@ -4341,14 +3578,11 @@ external model_get_func_decl : context -> model -> int -> 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 @@ -4356,12 +3590,9 @@ external model_get_num_sorts : context -> model -> int (** 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 @@ -4369,10 +3600,8 @@ external model_get_sort : context -> model -> int -> 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 @@ -4382,11 +3611,8 @@ external model_get_sort_universe : context -> model -> sort -> ast_vector 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. - + 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 @@ -4394,9 +3620,7 @@ external is_as_array : context -> ast -> bool (** 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 @@ -4404,11 +3628,9 @@ external get_as_array_func_decl : context -> ast -> 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 @@ -4417,11 +3639,8 @@ external func_interp_get_num_entries : context -> func_interp -> int (** 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 @@ -4429,10 +3648,8 @@ external func_interp_get_entry : context -> func_interp -> int -> func_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 @@ -4440,20 +3657,16 @@ external func_interp_get_else : context -> func_interp -> ast (** 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. - + 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 @@ -4461,9 +3674,7 @@ external func_entry_get_value : context -> func_entry -> ast (** 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 @@ -4471,11 +3682,8 @@ external func_entry_get_num_args : context -> func_entry -> int (** 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 @@ -4486,7 +3694,6 @@ external func_entry_get_arg : context -> func_entry -> int -> ast *) (** Summary: Log interaction to a file. - extra_API('open_log', INT, (_in(STRING),)) *) external open_log : string -> bool @@ -4494,11 +3701,9 @@ external open_log : string -> bool (** 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 @@ -4506,7 +3711,6 @@ external append_log : string -> unit (** Summary: Close interaction log. - extra_API('close_log', VOID, ()) *) external close_log : unit -> unit @@ -4514,10 +3718,8 @@ external close_log : unit -> unit (** 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]. - + suppressed after calling this method with [false]. def_API('toggle_warning_messages', VOID, (_in(BOOL),)) *) external toggle_warning_messages : bool -> unit @@ -4528,19 +3730,16 @@ external toggle_warning_messages : bool -> unit *) (** 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 + 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, + 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 @@ -4548,13 +3747,8 @@ external set_ast_print_mode : context -> ast_print_mode -> unit (** 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 @@ -4580,11 +3774,6 @@ external func_decl_to_string : context -> func_decl -> 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 @@ -4592,20 +3781,14 @@ external model_to_string : context -> model -> 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 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 @@ -4616,11 +3799,9 @@ external benchmark_to_smtlib_string : context -> string -> string -> string -> s *) (** Summary: \[ [ parse_smtlib2_string c str ] \] - Parse the given string using the SMT-LIB2 parser. - + 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 @@ -4628,7 +3809,6 @@ external parse_smtlib2_string : context -> string -> symbol array -> sort array (** 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 @@ -4637,57 +3817,45 @@ external parse_smtlib2_file : context -> string -> symbol array -> sort array -> (** 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. + 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}} + {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. + 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_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 @@ -4695,7 +3863,6 @@ external parse_smtlib_string : context -> string -> symbol array -> sort array - (** 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 @@ -4703,7 +3870,6 @@ external parse_smtlib_file : context -> string -> symbol array -> sort array -> (** 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 @@ -4712,9 +3878,7 @@ external get_smtlib_num_formulas : context -> int (** 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 @@ -4722,7 +3886,6 @@ external get_smtlib_formula : context -> int -> ast (** 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 @@ -4731,9 +3894,7 @@ external get_smtlib_num_assumptions : context -> int (** 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 @@ -4741,7 +3902,6 @@ external get_smtlib_assumption : context -> int -> ast (** 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 @@ -4750,9 +3910,7 @@ external get_smtlib_num_decls : context -> int (** 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 @@ -4760,7 +3918,6 @@ external get_smtlib_decl : context -> int -> func_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 @@ -4769,9 +3926,7 @@ external get_smtlib_num_sorts : context -> int (** 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 @@ -4781,38 +3936,17 @@ external get_smtlib_sort : context -> int -> 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" *) -(** - Summary: \[ [ parse_z3_string c str ] \] - Parse the given string using the Z3 native parser. - - Return the conjunction of asserts made in the input. - - def_API('parse_z3_string', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_string" - -(** - Summary: Similar to {!parse_z3_string}, but reads the benchmark from a file. - - def_API('parse_z3_file', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_file" - (** {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 @@ -4821,7 +3955,6 @@ external set_error : context -> error_code -> unit (* (** 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 @@ -4831,7 +3964,7 @@ external get_error_msg_ex : context -> error_code -> string (** Summary: Return a string describing the given error code. -*) +*) val get_error_msg: context -> error_code -> string (** @@ -4839,21 +3972,32 @@ val get_error_msg: context -> error_code -> string *) (** 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. - - - - + Summary: Create a new fixedpoint context. def_API('mk_fixedpoint', FIXEDPOINT, (_in(CONTEXT), )) *) external mk_fixedpoint : context -> fixedpoint @@ -4862,33 +4006,27 @@ external mk_fixedpoint : context -> fixedpoint (** Summary: Add a universal Horn clause as a named rule. The [horn_rule] should be of the form: - - {v + {v horn_rule ::= (forall (bound-vars) horn_rule) - | (=> atoms horn_rule) - | atom + | (=> 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. - + 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 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 + 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 is applied to the arguments. - + 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 @@ -4896,10 +4034,8 @@ external fixedpoint_add_fact : context -> fixedpoint -> func_decl -> int array - (** 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 @@ -4907,17 +4043,14 @@ external fixedpoint_assert : context -> fixedpoint -> ast -> unit (** Summary: Pose a query against the asserted rules. - - {v + {v query ::= (exists (bound-vars) query) - | literals + | literals v} - - query returns + 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 @@ -4925,14 +4058,11 @@ external fixedpoint_query : context -> fixedpoint -> ast -> lbool (** Summary: Pose multiple queries against the asserted rules. - The queries are encoded as relations (function declarations). - - query returns + 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 @@ -4940,14 +4070,10 @@ external fixedpoint_query_relations : context -> fixedpoint -> func_decl array - (** 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 @@ -4955,18 +4081,15 @@ external fixedpoint_get_answer : context -> fixedpoint -> ast (** 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. + 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 @@ -4974,11 +4097,9 @@ external fixedpoint_update_rule : context -> fixedpoint -> ast -> symbol -> unit (** Summary: Query the PDR engine for the maximal levels properties are known about predicate. - - This call retrieves the maximal number of relevant unfoldings + 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 @@ -4989,9 +4110,7 @@ external fixedpoint_get_num_levels : context -> fixedpoint -> func_decl -> int 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 @@ -4999,14 +4118,11 @@ external fixedpoint_get_cover_delta : context -> fixedpoint -> int -> func_decl (** Summary: Add property about the predicate [pred]. - Add a property of predicate [pred] at [level]. + 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 @@ -5014,7 +4130,6 @@ external fixedpoint_add_cover : context -> fixedpoint -> int -> func_decl -> ast (** 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 @@ -5025,7 +4140,6 @@ external fixedpoint_get_statistics : context -> fixedpoint -> stats 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 @@ -5033,29 +4147,30 @@ external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> un (** 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: Simplify rules into a set of new rules that are returned. - The simplification routines apply inlining, quantifier elimination, and other - algebraic simplifications. - - def_API('fixedpoint_simplify_rules', AST_VECTOR, (_in(CONTEXT), _in(FIXEDPOINT), _in(UINT), _in_array(2,AST), _in(UINT), _in_array(4,FUNC_DECL))) + Summary: Retrieve set of rules from fixedpoint context. + def_API('fixedpoint_get_rules', AST_VECTOR, (_in(CONTEXT),_in(FIXEDPOINT))) *) -external fixedpoint_simplify_rules : context -> fixedpoint -> ast array -> func_decl array -> ast_vector - = "camlidl_z3_Z3_fixedpoint_simplify_rules" +external fixedpoint_get_rules : context -> fixedpoint -> ast_vector + = "camlidl_z3_Z3_fixedpoint_get_rules" (** - Summary: Set parameters on fixedpoint context. + 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 @@ -5063,7 +4178,6 @@ external fixedpoint_set_params : context -> fixedpoint -> params -> unit (** 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 @@ -5071,7 +4185,6 @@ external fixedpoint_get_help : context -> fixedpoint -> string (** 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 @@ -5083,20 +4196,40 @@ external fixedpoint_get_param_descrs : context -> fixedpoint -> param_descrs @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 @@ -5104,11 +4237,8 @@ external fixedpoint_push : context -> fixedpoint -> unit (** 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 @@ -5119,10 +4249,6 @@ external fixedpoint_pop : context -> fixedpoint -> unit *) (** Summary: Return an empty AST vector. - - - - def_API('mk_ast_vector', AST_VECTOR, (_in(CONTEXT),)) *) external mk_ast_vector : context -> ast_vector @@ -5130,7 +4256,6 @@ external mk_ast_vector : context -> 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 @@ -5138,27 +4263,22 @@ external ast_vector_size : context -> ast_vector -> int (** 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]. - + 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]. - + 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 @@ -5166,7 +4286,6 @@ external ast_vector_resize : context -> ast_vector -> int -> unit (** 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 @@ -5174,7 +4293,6 @@ external ast_vector_push : context -> ast_vector -> ast -> unit (** 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 @@ -5182,7 +4300,6 @@ external ast_vector_translate : context -> ast_vector -> context -> ast_vector (** 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 @@ -5193,10 +4310,6 @@ external ast_vector_to_string : context -> ast_vector -> string *) (** 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 @@ -5204,7 +4317,6 @@ external mk_ast_map : context -> 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 @@ -5212,9 +4324,7 @@ external ast_map_contains : context -> ast_map -> ast -> bool (** 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 @@ -5222,7 +4332,6 @@ external ast_map_find : context -> ast_map -> ast -> ast (** 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 @@ -5230,7 +4339,6 @@ external ast_map_insert : context -> ast_map -> ast -> ast -> unit (** 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 @@ -5238,7 +4346,6 @@ external ast_map_erase : context -> ast_map -> ast -> unit (** 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 @@ -5246,7 +4353,6 @@ external ast_map_reset : context -> ast_map -> unit (** 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 @@ -5254,7 +4360,6 @@ external ast_map_size : context -> ast_map -> int (** 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 @@ -5262,7 +4367,6 @@ external ast_map_keys : context -> ast_map -> ast_vector (** 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 @@ -5275,17 +4379,10 @@ external ast_map_to_string : context -> ast_map -> string 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 + 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 @@ -5295,15 +4392,13 @@ external mk_goal : context -> bool -> bool -> bool -> 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. - + 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 @@ -5311,7 +4406,6 @@ external goal_assert : context -> goal -> ast -> unit (** 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 @@ -5319,7 +4413,6 @@ external goal_inconsistent : context -> goal -> bool (** 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 @@ -5327,7 +4420,6 @@ external goal_depth : context -> goal -> int (** Summary: Erase all formulas from the given goal. - def_API('goal_reset', VOID, (_in(CONTEXT), _in(GOAL))) *) external goal_reset : context -> goal -> unit @@ -5335,7 +4427,6 @@ external goal_reset : context -> goal -> unit (** 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 @@ -5343,9 +4434,7 @@ external goal_size : context -> goal -> int (** 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 @@ -5353,7 +4442,6 @@ external goal_formula : context -> goal -> int -> ast (** 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 @@ -5361,7 +4449,6 @@ external goal_num_exprs : context -> goal -> int (** 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 @@ -5369,7 +4456,6 @@ external goal_is_decided_sat : context -> goal -> bool (** 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 @@ -5377,7 +4463,6 @@ external goal_is_decided_unsat : context -> goal -> bool (** 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 @@ -5385,7 +4470,6 @@ external goal_translate : context -> goal -> context -> goal (** Summary: Convert a goal into a string. - def_API('goal_to_string', STRING, (_in(CONTEXT), _in(GOAL))) *) external goal_to_string : context -> goal -> string @@ -5398,9 +4482,7 @@ external goal_to_string : context -> goal -> string 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 @@ -5410,10 +4492,8 @@ external mk_tactic : context -> string -> 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 @@ -5422,7 +4502,6 @@ external mk_probe : context -> string -> 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 @@ -5431,7 +4510,6 @@ external tactic_and_then : context -> tactic -> tactic -> tactic (** 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 @@ -5439,7 +4517,6 @@ external tactic_or_else : context -> tactic -> tactic -> tactic (** 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 @@ -5448,7 +4525,6 @@ external tactic_par_or : context -> tactic array -> tactic (** 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 @@ -5457,7 +4533,6 @@ external tactic_par_and_then : context -> tactic -> tactic -> tactic (** 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 @@ -5466,7 +4541,6 @@ external tactic_try_for : context -> tactic -> int -> tactic (** 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 @@ -5475,7 +4549,6 @@ external tactic_when : context -> probe -> tactic -> tactic (** 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 @@ -5484,7 +4557,6 @@ external tactic_cond : context -> probe -> tactic -> tactic -> tactic (** 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 @@ -5492,7 +4564,6 @@ external tactic_repeat : context -> tactic -> int -> tactic (** Summary: Return a tactic that just return the given goal. - def_API('tactic_skip', TACTIC, (_in(CONTEXT),)) *) external tactic_skip : context -> tactic @@ -5500,7 +4571,6 @@ external tactic_skip : context -> tactic (** Summary: Return a tactic that always fails. - def_API('tactic_fail', TACTIC, (_in(CONTEXT),)) *) external tactic_fail : context -> tactic @@ -5508,7 +4578,6 @@ external tactic_fail : context -> tactic (** 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 @@ -5517,7 +4586,6 @@ external tactic_fail_if : context -> probe -> tactic (** 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 @@ -5525,7 +4593,6 @@ external tactic_fail_if_not_decided : context -> tactic (** 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 @@ -5533,7 +4600,6 @@ external tactic_using_params : context -> tactic -> params -> tactic (** Summary: Return a probe that always evaluates to val. - def_API('probe_const', PROBE, (_in(CONTEXT), _in(DOUBLE))) *) external probe_const : context -> float -> probe @@ -5541,9 +4607,7 @@ external probe_const : context -> float -> probe (** 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 @@ -5551,9 +4615,7 @@ external probe_lt : context -> probe -> probe -> probe (** 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 @@ -5561,9 +4623,7 @@ external probe_gt : context -> probe -> probe -> probe (** 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 @@ -5571,19 +4631,15 @@ external probe_le : context -> probe -> probe -> probe (** 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))) + 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 @@ -5591,9 +4647,7 @@ external probe_eq : context -> probe -> probe -> probe (** 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 @@ -5601,9 +4655,7 @@ external probe_and : context -> probe -> probe -> probe (** 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 @@ -5611,9 +4663,7 @@ external probe_or : context -> probe -> probe -> probe (** 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 @@ -5621,7 +4671,6 @@ external probe_not : context -> probe -> probe (** Summary: Return the number of builtin tactics available in Z3. - def_API('get_num_tactics', UINT, (_in(CONTEXT),)) *) external get_num_tactics : context -> int @@ -5629,9 +4678,7 @@ external get_num_tactics : context -> int (** 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 @@ -5639,7 +4686,6 @@ external get_tactic_name : context -> int -> string (** Summary: Return the number of builtin probes available in Z3. - def_API('get_num_probes', UINT, (_in(CONTEXT),)) *) external get_num_probes : context -> int @@ -5647,9 +4693,7 @@ external get_num_probes : context -> int (** 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 @@ -5657,7 +4701,6 @@ external get_probe_name : context -> int -> string (** 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 @@ -5665,7 +4708,6 @@ external tactic_get_help : context -> tactic -> string (** 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 @@ -5673,7 +4715,6 @@ external tactic_get_param_descrs : context -> tactic -> 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 @@ -5681,7 +4722,6 @@ external tactic_get_descr : context -> string -> string (** 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 @@ -5690,7 +4730,6 @@ external probe_get_descr : context -> string -> string (** 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 @@ -5698,7 +4737,6 @@ external probe_apply : context -> probe -> goal -> float (** 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 @@ -5706,7 +4744,6 @@ external tactic_apply : context -> tactic -> goal -> apply_result (** 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 @@ -5714,7 +4751,6 @@ external tactic_apply_ex : context -> tactic -> goal -> params -> apply_result (** 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 @@ -5722,7 +4758,6 @@ external apply_result_to_string : context -> apply_result -> 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 @@ -5730,9 +4765,7 @@ external apply_result_get_num_subgoals : context -> apply_result -> int (** 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 @@ -5741,7 +4774,6 @@ external apply_result_get_subgoal : context -> apply_result -> int -> goal (** 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 @@ -5753,11 +4785,7 @@ external apply_result_convert_model : context -> apply_result -> int -> model -> (** 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. - - - - + 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 @@ -5765,7 +4793,6 @@ external mk_solver : context -> solver (** Summary: Create a new (incremental) solver. - def_API('mk_simple_solver', SOLVER, (_in(CONTEXT),)) *) external mk_simple_solver : context -> solver @@ -5774,10 +4801,6 @@ external mk_simple_solver : context -> 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 @@ -5787,7 +4810,6 @@ external mk_solver_for_logic : context -> symbol -> solver 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 @@ -5795,7 +4817,6 @@ external mk_solver_from_tactic : context -> tactic -> solver (** 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 @@ -5803,7 +4824,6 @@ external solver_get_help : context -> solver -> string (** 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 @@ -5811,7 +4831,6 @@ external solver_get_param_descrs : context -> solver -> 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 @@ -5819,11 +4838,8 @@ external solver_set_params : context -> solver -> params -> unit (** Summary: Create a backtracking point. - - The solver contains a stack of assertions. - + 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 @@ -5831,11 +4847,8 @@ external solver_push : context -> solver -> unit (** 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 @@ -5843,7 +4856,6 @@ external solver_pop : context -> solver -> int -> unit (** Summary: Remove all assertions from the solver. - def_API('solver_reset', VOID, (_in(CONTEXT), _in(SOLVER))) *) external solver_reset : context -> solver -> unit @@ -5851,10 +4863,8 @@ external solver_reset : context -> solver -> unit (** 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 @@ -5862,34 +4872,42 @@ external solver_get_num_scopes : context -> solver -> int (** 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))) + 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 + 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 @@ -5898,12 +4916,9 @@ external solver_check : context -> solver -> lbool (** 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 + 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 @@ -5911,10 +4926,8 @@ external solver_check_assumptions : context -> solver -> ast array -> lbool (** 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 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 @@ -5922,11 +4935,9 @@ external solver_get_model : context -> solver -> 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 @@ -5935,7 +4946,6 @@ external solver_get_proof : context -> solver -> ast (** 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 @@ -5944,7 +4954,6 @@ external solver_get_unsat_core : context -> solver -> ast_vector (** 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 @@ -5952,9 +4961,6 @@ external solver_get_reason_unknown : context -> solver -> string (** Summary: Return statistics for the given solver. - - - def_API('solver_get_statistics', STATS, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_statistics : context -> solver -> stats @@ -5962,7 +4968,6 @@ external solver_get_statistics : context -> solver -> stats (** Summary: Convert a solver into a string. - def_API('solver_to_string', STRING, (_in(CONTEXT), _in(SOLVER))) *) external solver_to_string : context -> solver -> string @@ -5976,25 +4981,23 @@ 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}} + {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 @@ -6002,9 +5005,7 @@ external stats_size : context -> stats -> int (** 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 @@ -6012,9 +5013,7 @@ external stats_get_key : context -> stats -> int -> string (** 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 @@ -6022,9 +5021,7 @@ external stats_is_uint : context -> stats -> int -> bool (** 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 @@ -6032,9 +5029,7 @@ external stats_is_double : context -> stats -> int -> bool (** 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 @@ -6042,25 +5037,22 @@ external stats_get_uint_value : context -> stats -> int -> int (** 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 Legacy V3 API}} -*) - +(** + {2 {L Legacy V3 API}} +*) module V3 : sig -(** - {2 {L Legacy V3 API}} -*) +(** + {2 {L Legacy V3 API}} +*) -(* File generated from z3.idl *) +(* File generated from z3V3.idl *) type symbol and literals @@ -6296,24 +5288,17 @@ and ast_print_mode = (** - - *) (** {2 {L Types}} - - - Most of the types in the API are abstract. - - + 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. + - [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. @@ -6329,23 +5314,21 @@ and ast_print_mode = - [stats]: statistical data for a solver. *) (** - {!lbool} + {!lbool} Lifted Boolean type: [false], [undefined], [true]. *) (** - {!symbol_kind} + {!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} + {!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. @@ -6355,23 +5338,23 @@ and ast_print_mode = - PARAMETER_FUNC_DECL is used for function declaration parameters. *) (** - {!sort_kind} + {!sort_kind} The different kinds of Z3 types (See {!get_sort_kind}). *) (** - {!ast_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 + - 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} + {!decl_kind} The different kinds of interpreted function kinds. - OP_TRUE The constant true. @@ -6436,9 +5419,9 @@ and ast_print_mode = - 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. + Array store takes at least 3 arguments. - - OP_SELECT Array select. + - 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. @@ -6473,7 +5456,7 @@ and ast_print_mode = - OP_BSUB Binary subtraction. - OP_BMUL Binary multiplication. - + - OP_BSDIV Binary signed division. - OP_BUDIV Binary unsigned int division. @@ -6493,16 +5476,16 @@ and ast_print_mode = - 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_SLEQ Signed bit-vector <= - Binary relation. - - OP_UGEQ Unsigned bit-vector >= - Binary relation. + - OP_UGEQ Unsigned bit-vector >= - Binary relation. - - OP_SGEQ Signed bit-vector >= - Binary relation. + - OP_SGEQ Signed bit-vector >= - Binary relation. - - OP_ULT Unsigned bit-vector < - Binary relation. + - OP_ULT Unsigned bit-vector < - Binary relation. - OP_SLT Signed bit-vector < - Binary relation. @@ -6562,7 +5545,7 @@ and ast_print_mode = 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. + - 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))) @@ -6575,7 +5558,7 @@ and ast_print_mode = - 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. @@ -6587,7 +5570,7 @@ and ast_print_mode = 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 + The only reflexive relations that are used are equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. @@ -6607,7 +5590,7 @@ and ast_print_mode = } - 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. + It combines several symmetry and transitivity proofs. Example: {e @@ -6620,7 +5603,7 @@ and ast_print_mode = 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, + 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. @@ -6638,8 +5621,8 @@ and ast_print_mode = T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - - - OP_PR_DISTRIBUTIVITY: Distributivity proof object. + + - OP_PR_DISTRIBUTIVITY: Distributivity proof object. Given that f (= or) distributes over g (= and), produces a proof for (= (f a (g c d)) @@ -6653,11 +5636,11 @@ and ast_print_mode = 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 + 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 @@ -6673,10 +5656,10 @@ and ast_print_mode = 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), + 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 @@ -6698,22 +5681,22 @@ and ast_print_mode = - 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 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: + - 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])) + (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. @@ -6723,14 +5706,14 @@ and ast_print_mode = 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: + - OP_PR_LEMMA: {e T1: false @@ -6740,16 +5723,16 @@ and ast_print_mode = 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: + - OP_PR_UNIT_RESOLUTION: {e - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) ... - T(n+1): (not l_n) + T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') } - - OP_PR_IFF_TRUE: + - OP_PR_IFF_TRUE: {e T1: p [iff-true T1]: (iff p true) @@ -6764,14 +5747,14 @@ and ast_print_mode = - 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) @@ -6800,7 +5783,7 @@ and ast_print_mode = 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: @@ -6816,17 +5799,17 @@ and ast_print_mode = [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) Otherwise: - [def-intro]: (= n e) + [def-intro]: (= n e) - - OP_PR_APPLY_DEF: + - 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 @@ -6841,7 +5824,7 @@ and ast_print_mode = The quantifier is retained (unless the bound variables are eliminated). Example {e - T1: q ~ q_new + 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 @@ -6850,7 +5833,7 @@ and ast_print_mode = 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 @@ -6871,24 +5854,24 @@ and ast_print_mode = (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 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. + 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: - - 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 @@ -6901,9 +5884,9 @@ and ast_print_mode = 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. + 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. @@ -6934,7 +5917,7 @@ and ast_print_mode = {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 + 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 @@ -6957,16 +5940,16 @@ and ast_print_mode = - 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 + 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_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. + - OP_RA_UNION: Create the union or convex hull of two relations. The function takes two arguments. - OP_RA_WIDEN: Widen two relations. @@ -6976,7 +5959,7 @@ and ast_print_mode = The function takes one argument. - OP_RA_FILTER: Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. + 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. @@ -6991,23 +5974,23 @@ and ast_print_mode = 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. + + - 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. + - 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] + 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. @@ -7027,10 +6010,10 @@ and ast_print_mode = - OP_UNINTERPRETED: kind used for uninterpreted symbols. *) (** - {!param_kind} + {!param_kind} The different kinds of parameters that can be associated with parameter sets. - (see {!mk_params}). + (see {!mk_params}). - PK_UINT integer parameters. - PK_BOOL boolean parameters. @@ -7041,77 +6024,128 @@ and ast_print_mode = - PK_INVALID invalid parameter. *) (** - {!search_failure} + {!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 + - 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} + {!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_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('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') + 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. - - Configurations are created in order to assign parameters prior to creating - contexts for Z3 interaction. For example, if the users wishes to use model + 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 "MODEL" "true"] - + [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. - + 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 @@ -7119,9 +6153,7 @@ external mk_config : unit -> config (** Summary: Delete the given configuration object. - - {b See also}: {!mk_config} - def_API('del_config', VOID, (_in(CONFIG),)) *) external del_config : config -> unit @@ -7129,15 +6161,8 @@ external del_config : config -> unit (** Summary: Set a configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - {v - z3.exe -ini? - v} - + 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 @@ -7147,16 +6172,10 @@ external set_param_value : config -> string -> string -> unit {2 {L Create context}} *) (** - Summary: Create a context using the given configuration. - + 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 @@ -7164,44 +6183,23 @@ external mk_context : config -> 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: Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - {v - z3.exe -ini? - v} - - Only a few configuration parameters are mutable once the context is created. - The error handler is invoked when trying to modify an immutable parameter. - - - - {b See also}: {!mk_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: Get a configuration parameter. - - Returns [None] - if the parameter value does not exist. - - - - - {b See also}: {!mk_context } - + 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 @@ -7211,18 +6209,14 @@ external get_param_value : context -> string -> string option {2 {L Symbols}} *) (** - {4 {L Redundant low-level API}} + {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 @@ -7230,11 +6224,8 @@ external mk_int_symbol : context -> 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 @@ -7244,23 +6235,19 @@ external mk_string_symbol : context -> string -> symbol {2 {L Sorts}} *) (** - {4 {L Redundant low-level API}} + {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. - + 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 @@ -7268,24 +6255,19 @@ external mk_bool_sort : context -> 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. - + 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 @@ -7293,11 +6275,8 @@ external mk_real_sort : context -> 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 @@ -7305,27 +6284,21 @@ external mk_bv_sort : context -> int -> sort (** Summary: Create a named finite domain sort. - - To create constants that belong to the finite domain, + 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.} - + - {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. - + 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 @@ -7333,14 +6306,8 @@ external mk_array_sort : context -> sort -> sort -> 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. @@ -7348,7 +6315,6 @@ external mk_array_sort : context -> sort -> sort -> sort @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 @@ -7356,28 +6322,20 @@ external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort (** Summary: Create a enumeration sort. - - [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], + [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 + 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 @@ -7385,13 +6343,7 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ (** 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. @@ -7401,7 +6353,6 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ @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 @@ -7409,44 +6360,38 @@ external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_dec (** 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] + @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. - + 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_z3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_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. + 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 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 @@ -7454,11 +6399,9 @@ external mk_datatype : context -> symbol -> constructor array -> sort * construc (** 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 @@ -7466,12 +6409,9 @@ external mk_constructor_list : context -> constructor array -> 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 @@ -7479,28 +6419,24 @@ external del_constructor_list : context -> constructor_list -> unit (** 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 datattype 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. - + 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 @@ -7511,22 +6447,17 @@ external query_constructor : context -> constructor -> int -> func_decl * func_d *) (** 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]. - + 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 @@ -7534,9 +6465,7 @@ external mk_func_decl : context -> symbol -> sort array -> 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 @@ -7544,18 +6473,9 @@ external mk_app : context -> func_decl -> ast array -> ast (** Summary: Declare and create a constant. - - - - - - - - [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - + [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 @@ -7563,14 +6483,8 @@ external mk_const : context -> symbol -> sort -> ast (** 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 @@ -7578,17 +6492,9 @@ external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_de (** 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) [||]]. - - - + [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 @@ -7599,7 +6505,6 @@ external mk_fresh_const : context -> string -> sort -> ast *) (** Summary: Create an AST node representing [true]. - def_API('mk_true', AST, (_in(CONTEXT), )) *) external mk_true : context -> ast @@ -7607,7 +6512,6 @@ external mk_true : context -> ast (** Summary: Create an AST node representing [false]. - def_API('mk_false', AST, (_in(CONTEXT), )) *) external mk_false : context -> ast @@ -7616,51 +6520,40 @@ external mk_false : context -> ast (** Summary: \[ [ mk_eq c l r ] \] Create an AST node representing {e l = r }. - - The nodes [l] and [r] must have the same type. - + 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 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 ] \] + 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 ] \] + 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 @@ -7669,9 +6562,7 @@ external mk_ite : context -> ast -> ast -> ast -> ast (** 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 @@ -7680,9 +6571,7 @@ external mk_iff : context -> ast -> ast -> ast (** 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 @@ -7691,37 +6580,25 @@ external mk_implies : context -> ast -> ast -> ast (** 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}. - - + 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}. - - + 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 @@ -7731,110 +6608,78 @@ external mk_or : context -> ast array -> ast {2 {L Arithmetic: Integers and Reals}} *) (** - - Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. - - + 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}. - - + 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}. - - + 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}. - + 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}. - + 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}. - + 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}. - + 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 ] \] + 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 @@ -7843,9 +6688,7 @@ external mk_lt : context -> ast -> ast -> ast (** 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 @@ -7854,9 +6697,7 @@ external mk_le : context -> ast -> ast -> ast (** 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 @@ -7865,9 +6706,7 @@ external mk_gt : context -> ast -> ast -> ast (** 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 @@ -7876,19 +6715,14 @@ external mk_ge : context -> ast -> ast -> ast (** 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 + 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 }. - + 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 @@ -7897,13 +6731,10 @@ external mk_int2real : context -> ast -> ast (** 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 @@ -7912,10 +6743,8 @@ external mk_real2int : context -> ast -> ast (** 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 @@ -7927,9 +6756,7 @@ external mk_is_int : context -> ast -> ast (** 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 @@ -7938,9 +6765,7 @@ external mk_bvnot : context -> ast -> ast (** 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 @@ -7949,9 +6774,7 @@ external mk_bvredand : context -> ast -> ast (** 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 @@ -7960,9 +6783,7 @@ external mk_bvredor : context -> ast -> ast (** 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 @@ -7971,9 +6792,7 @@ external mk_bvand : context -> ast -> 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 @@ -7982,9 +6801,7 @@ external mk_bvor : context -> ast -> ast -> ast (** 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 @@ -7992,10 +6809,8 @@ external mk_bvxor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnand c t1 t2 ] \] - Bitwise nand. - + 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 @@ -8003,10 +6818,8 @@ external mk_bvnand : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnor c t1 t2 ] \] - Bitwise nor. - + 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 @@ -8014,10 +6827,8 @@ external mk_bvnor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvxnor c t1 t2 ] \] - Bitwise xnor. - + 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 @@ -8026,9 +6837,7 @@ external mk_bvxnor : context -> ast -> ast -> ast (** 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 @@ -8037,9 +6846,7 @@ external mk_bvneg : context -> ast -> ast (** 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 @@ -8048,9 +6855,7 @@ external mk_bvadd : context -> ast -> ast -> ast (** 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 @@ -8059,9 +6864,7 @@ external mk_bvsub : context -> ast -> ast -> ast (** 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 @@ -8069,14 +6872,11 @@ external mk_bvmul : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvudiv c t1 t2 ] \] - Unsigned division. - + 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 @@ -8085,17 +6885,11 @@ external mk_bvudiv : context -> ast -> ast -> ast (** 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 @@ -8104,13 +6898,9 @@ external mk_bvsdiv : context -> ast -> ast -> ast (** 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 @@ -8119,16 +6909,11 @@ external mk_bvurem : context -> ast -> ast -> ast (** 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 @@ -8137,13 +6922,9 @@ external mk_bvsrem : context -> ast -> ast -> ast (** 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 @@ -8152,9 +6933,7 @@ external mk_bvsmod : context -> ast -> ast -> ast (** 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 @@ -8163,17 +6942,14 @@ external mk_bvult : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvslt c t1 t2 ] \] Two's complement signed less than. - It abbreviates: - {v + {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 @@ -8182,9 +6958,7 @@ external mk_bvslt : context -> ast -> ast -> ast (** 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 @@ -8193,9 +6967,7 @@ external mk_bvule : context -> ast -> ast -> ast (** 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 @@ -8204,9 +6976,7 @@ external mk_bvsle : context -> ast -> ast -> ast (** 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 @@ -8215,9 +6985,7 @@ external mk_bvuge : context -> ast -> ast -> ast (** 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 @@ -8226,9 +6994,7 @@ external mk_bvsge : context -> ast -> ast -> ast (** 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 @@ -8237,9 +7003,7 @@ external mk_bvugt : context -> ast -> ast -> ast (** 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 @@ -8248,12 +7012,9 @@ external mk_bvsgt : context -> ast -> ast -> ast (** 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 @@ -8264,9 +7025,7 @@ external mk_concat : context -> ast -> ast -> ast 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 @@ -8277,9 +7036,7 @@ external mk_extract : context -> int -> int -> ast -> ast 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 @@ -8287,12 +7044,10 @@ external mk_sign_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_zero_ext c i t1 ] \] - Extend the given bit-vector with zeros to the (unsigned int) equivalent + 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. - + 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 @@ -8301,9 +7056,7 @@ external mk_zero_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_repeat c i t1 ] \] Repeat the given bit-vector up length {e i }. - - The node [t1] must have a bit-vector sort. - + 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 @@ -8312,16 +7065,12 @@ external mk_repeat : context -> int -> ast -> ast (** 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 + 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 @@ -8330,16 +7079,12 @@ external mk_bvshl : context -> ast -> ast -> ast (** 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 + 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 @@ -8348,17 +7093,13 @@ external mk_bvlshr : context -> ast -> ast -> ast (** 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 + 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 @@ -8367,9 +7108,7 @@ external mk_bvashr : context -> ast -> ast -> ast (** 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. - + 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 @@ -8378,9 +7117,7 @@ external mk_rotate_left : context -> int -> ast -> ast (** 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. - + 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 @@ -8389,9 +7126,7 @@ external mk_rotate_right : context -> int -> ast -> ast (** 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 @@ -8400,9 +7135,7 @@ external mk_ext_rotate_left : context -> ast -> ast -> ast (** 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 @@ -8411,13 +7144,10 @@ external mk_ext_rotate_right : context -> ast -> ast -> ast (** 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. + 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. - + 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 @@ -8426,17 +7156,14 @@ external mk_int2bv : context -> int -> ast -> ast (** 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. + 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. + 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. - + 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 @@ -8446,9 +7173,7 @@ external mk_bv2int : context -> ast -> bool -> ast 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 @@ -8458,9 +7183,7 @@ external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast 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 @@ -8470,9 +7193,7 @@ external mk_bvadd_no_underflow : context -> ast -> ast -> ast 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 @@ -8482,9 +7203,7 @@ external mk_bvsub_no_overflow : context -> ast -> ast -> ast 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 @@ -8492,11 +7211,9 @@ external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast (** Summary: \[ [ mk_bvsdiv_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed division + 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 @@ -8504,11 +7221,9 @@ external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvneg_no_overflow c t1 ] \] - Check that bit-wise negation does not overflow when + 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 @@ -8518,9 +7233,7 @@ external mk_bvneg_no_overflow : context -> ast -> ast 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 @@ -8530,9 +7243,7 @@ external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast 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 @@ -8544,15 +7255,12 @@ external mk_bvmul_no_underflow : context -> ast -> ast -> ast (** 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] }, + 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 @@ -8561,18 +7269,15 @@ external mk_select : context -> ast -> ast -> ast (** 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: + 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 + 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 @@ -8580,14 +7285,11 @@ external mk_store : context -> ast -> ast -> ast -> ast (** Summary: Create the constant array. - - The resulting term is an array, such that a [select] on an arbitrary index + 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 @@ -8596,15 +7298,12 @@ external mk_const_array : context -> sort -> ast -> ast (** 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 }. + 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 @@ -8612,12 +7311,10 @@ external mk_map : context -> func_decl -> int -> ast -> ast (** Summary: Access the array default value. - Produces the default range value, for arrays that can be represented as + 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 @@ -8628,7 +7325,6 @@ external mk_array_default : context -> ast -> ast *) (** Summary: Create Set type. - def_API('mk_set_sort', SORT, (_in(CONTEXT), _in(SORT))) *) external mk_set_sort : context -> sort -> sort @@ -8636,7 +7332,6 @@ external mk_set_sort : context -> sort -> sort (** Summary: Create the empty set. - def_API('mk_empty_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_empty_set : context -> sort -> ast @@ -8644,7 +7339,6 @@ external mk_empty_set : context -> sort -> ast (** Summary: Create the full set. - def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_full_set : context -> sort -> ast @@ -8652,9 +7346,7 @@ external mk_full_set : context -> sort -> ast (** 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 @@ -8662,9 +7354,7 @@ external mk_set_add : context -> ast -> ast -> ast (** 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 @@ -8672,7 +7362,6 @@ external mk_set_del : context -> ast -> ast -> ast (** 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 @@ -8680,7 +7369,6 @@ external mk_set_union : context -> ast array -> ast (** 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 @@ -8688,7 +7376,6 @@ external mk_set_intersect : context -> ast array -> ast (** 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 @@ -8696,7 +7383,6 @@ external mk_set_difference : context -> ast -> ast -> ast (** Summary: Take the complement of a set. - def_API('mk_set_complement', AST, (_in(CONTEXT), _in(AST))) *) external mk_set_complement : context -> ast -> ast @@ -8704,9 +7390,7 @@ external mk_set_complement : context -> ast -> ast (** 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 @@ -8714,7 +7398,6 @@ external mk_set_member : context -> ast -> ast -> ast (** 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 @@ -8724,18 +7407,14 @@ external mk_set_subset : context -> ast -> ast -> ast {2 {L Numerals}} *) (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** - Summary: Create a numeral of a given sort. - + 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. - + @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 @@ -8743,43 +7422,32 @@ external mk_numeral : context -> string -> sort -> ast (** 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. - + 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. - + 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 @@ -8790,22 +7458,17 @@ external mk_int64 : context -> int64 -> sort -> ast *) (** 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 + 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 @@ -8813,12 +7476,10 @@ external mk_pattern : context -> ast array -> 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 + {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 @@ -8826,18 +7487,14 @@ external mk_pattern : context -> ast array -> pattern 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 @@ -8846,21 +7503,17 @@ external mk_bound : context -> int -> sort -> ast (** 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 + 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. - - + 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. @@ -8869,33 +7522,28 @@ external mk_bound : context -> int -> sort -> ast @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_z3V3_Z3_mk_forall" + = "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_z3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" + = "camlidl_z3V3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" (** - Summary: Create a quantifier - universal or existential, with pattern hints. + 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. @@ -8905,20 +7553,17 @@ external mk_exists : context -> int -> pattern array -> sort array -> symbol arr @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_z3V3_Z3_mk_quantifier" + = "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 @@ -8932,33 +7577,28 @@ external mk_quantifier : context -> bool -> int -> pattern array -> sort array - @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_z3V3_Z3_mk_quantifier_ex" + = "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 + @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 @@ -8966,61 +7606,54 @@ external mk_forall_const : context -> int -> app array -> pattern array -> ast - (** 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 + @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 + 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_z3V3_Z3_mk_quantifier_const" + = "camlidl_z3V3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" (** - Summary: Create a universal or existential + 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_z3V3_Z3_mk_quantifier_const_ex" + = "camlidl_z3V3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" (** {2 {L Accessors}} *) (** - {3 {L Symbols}} + {3 {L Symbols}} *) (** - {4 {L Redundant low-level API}} + {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 @@ -9028,12 +7661,9 @@ external get_symbol_kind : context -> symbol -> symbol_kind (** Summary: \[ [ get_symbol_int c s ] \] - Return the symbol int value. - + 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 @@ -9041,27 +7671,19 @@ external get_symbol_int : context -> symbol -> int (** Summary: \[ [ get_symbol_string c s ] \] - Return the symbol name. - + 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" (** - {3 {L Sorts}} + {3 {L Sorts}} *) (** - Summary: Return the sort name as a symbol. - + 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 @@ -9069,20 +7691,18 @@ external get_sort_name : context -> sort -> symbol (** Summary: Return a unique identifier for [s]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {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" (** - {4 {L Redundant low-level API}} + {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)]. - + 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 @@ -9090,8 +7710,7 @@ external sort_to_ast : context -> sort -> ast (** Summary: compare sorts. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {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 @@ -9099,9 +7718,7 @@ external is_eq_sort : context -> sort -> sort -> 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 @@ -9109,23 +7726,18 @@ external get_sort_kind : context -> sort -> sort_kind (** Summary: \[ [ get_bv_sort_size c t ] \] - Return the size of the given bit-vector sort. - + 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" (** - - Summary: Return the size of the sort in [r]. Return [None] if the call failed. + 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 @@ -9134,26 +7746,20 @@ external get_finite_domain_sort_size : context -> sort -> int64 option (** 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. - + 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 @@ -9162,13 +7768,10 @@ external get_array_sort_range : context -> sort -> sort (** Summary: \[ [ get_tuple_sort_mk_decl c t ] \] Return the constructor declaration of the given tuple - sort. - + 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 @@ -9176,13 +7779,10 @@ external get_tuple_sort_mk_decl : context -> sort -> func_decl (** Summary: \[ [ get_tuple_sort_num_fields c t ] \] - Return the number of fields of the given tuple sort. - + 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 @@ -9191,14 +7791,11 @@ external get_tuple_sort_num_fields : context -> sort -> int (** 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. - + 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 @@ -9206,13 +7803,10 @@ external get_tuple_sort_field_decl : context -> sort -> int -> func_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 @@ -9220,14 +7814,11 @@ external get_datatype_sort_num_constructors : context -> sort -> int (** 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 @@ -9235,14 +7826,11 @@ external get_datatype_sort_constructor : context -> sort -> int -> func_decl (** 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 @@ -9250,15 +7838,12 @@ external get_datatype_sort_recognizer : context -> sort -> int -> func_decl (** 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 @@ -9266,11 +7851,8 @@ external get_datatype_sort_constructor_accessor : context -> sort -> int -> int (** 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 @@ -9278,24 +7860,20 @@ external get_relation_arity : context -> sort -> int (** 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" (** - {3 {L Function Declarations}} + {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)]. - + 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 @@ -9303,8 +7881,7 @@ external func_decl_to_ast : context -> func_decl -> ast (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {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 @@ -9312,16 +7889,14 @@ external is_eq_func_decl : context -> func_decl -> func_decl -> bool (** Summary: Return a unique identifier for [f]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {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" (** - Summary: Return the constant declaration name as a symbol. - + 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 @@ -9329,7 +7904,6 @@ external get_decl_name : context -> func_decl -> symbol (** 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 @@ -9337,9 +7911,7 @@ external get_decl_kind : context -> func_decl -> 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 @@ -9347,9 +7919,7 @@ external get_domain_size : context -> func_decl -> int (** 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 @@ -9358,11 +7928,8 @@ external get_arity : context -> func_decl -> int (** 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 @@ -9370,11 +7937,9 @@ external get_domain : context -> func_decl -> int -> sort (** Summary: \[ [ get_range c d ] \] - Return the range of the given declaration. - + 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 @@ -9382,7 +7947,6 @@ external get_range : context -> func_decl -> sort (** 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 @@ -9390,11 +7954,9 @@ external get_decl_num_parameters : context -> func_decl -> int (** 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 @@ -9402,9 +7964,7 @@ external get_decl_parameter_kind : context -> func_decl -> int -> 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 @@ -9412,9 +7972,7 @@ external get_decl_int_parameter : context -> func_decl -> int -> int (** 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 @@ -9422,9 +7980,7 @@ external get_decl_double_parameter : context -> func_decl -> int -> float (** 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 @@ -9432,9 +7988,7 @@ external get_decl_symbol_parameter : context -> func_decl -> int -> symbol (** 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 @@ -9442,9 +7996,7 @@ external get_decl_sort_parameter : context -> func_decl -> int -> sort (** 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 @@ -9452,9 +8004,7 @@ external get_decl_ast_parameter : context -> func_decl -> int -> ast (** 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 @@ -9462,21 +8012,18 @@ external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl (** 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" (** - {3 {L Applications}} + {3 {L Applications}} *) (** - Summary: Convert a [app] into [ast]. - - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. - + 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 @@ -9484,7 +8031,6 @@ external app_to_ast : context -> app -> 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 @@ -9494,7 +8040,6 @@ external get_app_decl : context -> app -> func_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 @@ -9503,21 +8048,18 @@ external get_app_num_args : context -> app -> int (** 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" (** - {3 {L Terms}} + {3 {L Terms}} *) (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {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 @@ -9525,8 +8067,7 @@ external is_eq_ast : context -> ast -> ast -> bool (** 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]. - + - {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 @@ -9534,8 +8075,7 @@ external get_ast_id : context -> ast -> int (** 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]. - + - {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 @@ -9543,9 +8083,7 @@ external get_ast_hash : context -> ast -> int (** 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 @@ -9553,7 +8091,6 @@ external get_sort : context -> ast -> 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 @@ -9561,7 +8098,6 @@ external is_well_sorted : context -> ast -> 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 @@ -9569,14 +8105,13 @@ external get_bool_value : context -> ast -> lbool (** 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" (** - def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) + def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) *) external is_app : context -> ast -> bool = "camlidl_z3V3_Z3_is_app" @@ -9589,17 +8124,14 @@ external is_numeral_ast : context -> ast -> 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" (** - Summary: Convert an [ast] into an [APP_AST]. - - - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} - + 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 @@ -9607,25 +8139,21 @@ external to_app : context -> ast -> 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} - + - {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" (** - {4 {L Numerals}} + {4 {L Numerals}} *) (** - {5 {L Low-level API}} + {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 @@ -9634,19 +8162,15 @@ external get_numeral_string : context -> ast -> 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))) + 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" (** 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 @@ -9654,9 +8178,7 @@ external get_numerator : context -> ast -> ast (** 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 @@ -9664,16 +8186,12 @@ external get_denominator : context -> ast -> ast (** 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 @@ -9683,11 +8201,8 @@ external get_numeral_small : context -> ast -> bool * int64 * int64 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 @@ -9697,11 +8212,8 @@ external get_numeral_int : context -> ast -> bool * 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 @@ -9711,47 +8223,39 @@ external get_numeral_int64 : context -> ast -> bool * 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. + 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. + 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" (** - {4 {L Patterns}} + {4 {L Patterns}} *) (** - Summary: Convert a pattern into ast. - - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. - + 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 @@ -9759,7 +8263,6 @@ external pattern_to_ast : context -> pattern -> ast (** 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 @@ -9767,20 +8270,17 @@ external get_pattern_num_terms : context -> pattern -> int (** 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" (** - {4 {L Quantifiers}} + {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 @@ -9788,29 +8288,23 @@ external get_index_value : context -> ast -> int (** Summary: Determine if quantifier is universal. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - - def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) + def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) *) external is_quantifier_forall : context -> ast -> bool = "camlidl_z3V3_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))) + def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_weight : context -> ast -> int = "camlidl_z3V3_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 @@ -9818,9 +8312,7 @@ external get_quantifier_num_patterns : context -> ast -> int (** 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 @@ -9828,9 +8320,7 @@ external get_quantifier_pattern_ast : context -> ast -> int -> pattern (** 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 @@ -9838,9 +8328,7 @@ external get_quantifier_num_no_patterns : context -> ast -> int (** 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 @@ -9848,9 +8336,7 @@ external get_quantifier_no_pattern_ast : context -> ast -> int -> 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 @@ -9858,9 +8344,7 @@ external get_quantifier_num_bound : context -> ast -> int (** 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 @@ -9868,9 +8352,7 @@ external get_quantifier_bound_name : context -> ast -> int -> symbol (** 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 @@ -9878,22 +8360,18 @@ external get_quantifier_bound_sort : context -> ast -> int -> 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_z3V3_Z3_get_quantifier_body" (** - {3 {L Simplification}} + {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 @@ -9904,10 +8382,9 @@ external simplify : context -> ast -> ast *) (** Summary: Update the arguments of term [a] using the arguments [args]. - The number of arguments [num_args] should coincide + 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 @@ -9917,7 +8394,6 @@ external update_term : context -> ast -> ast array -> ast 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 @@ -9926,7 +8402,6 @@ external substitute : context -> ast -> ast array -> ast array -> ast (** 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 @@ -9937,7 +8412,6 @@ external substitute_vars : context -> ast -> ast array -> ast *) (** Summary: Log interaction to a file. - extra_API('open_log', INT, (_in(STRING),)) *) external open_log : string -> bool @@ -9945,11 +8419,9 @@ external open_log : string -> bool (** 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 @@ -9957,7 +8429,6 @@ external append_log : string -> unit (** Summary: Close interaction log. - extra_API('close_log', VOID, ()) *) external close_log : unit -> unit @@ -9965,10 +8436,8 @@ external close_log : unit -> unit (** 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]. - + suppressed after calling this method with [false]. def_API('toggle_warning_messages', VOID, (_in(BOOL),)) *) external toggle_warning_messages : bool -> unit @@ -9979,19 +8448,16 @@ external toggle_warning_messages : bool -> unit *) (** 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 + 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, + 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 @@ -9999,13 +8465,8 @@ external set_ast_print_mode : context -> ast_print_mode -> unit (** 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 @@ -10031,11 +8492,6 @@ external func_decl_to_string : context -> func_decl -> 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 @@ -10043,80 +8499,66 @@ external model_to_string : context -> model -> 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 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_z3V3_Z3_benchmark_to_smtlib_string" + = "camlidl_z3V3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" (** {2 {L Parser interface}} *) (** Summary: \[ [ parse_smtlib2_string c str ] \] - Parse the given string using the SMT-LIB2 parser. - + 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_z3V3_Z3_parse_smtlib2_string" + = "camlidl_z3V3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_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_z3V3_Z3_parse_smtlib2_file" + = "camlidl_z3V3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" (** - {4 {L Low-level API}} + {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. + 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_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_z3V3_Z3_parse_smtlib_string" + = "camlidl_z3V3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_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_z3V3_Z3_parse_smtlib_file" + = "camlidl_z3V3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_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 @@ -10125,9 +8567,7 @@ external get_smtlib_num_formulas : context -> int (** 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 @@ -10135,7 +8575,6 @@ external get_smtlib_formula : context -> int -> ast (** 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 @@ -10144,9 +8583,7 @@ external get_smtlib_num_assumptions : context -> int (** 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 @@ -10154,7 +8591,6 @@ external get_smtlib_assumption : context -> int -> ast (** 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 @@ -10163,9 +8599,7 @@ external get_smtlib_num_decls : context -> int (** 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 @@ -10173,7 +8607,6 @@ external get_smtlib_decl : context -> int -> func_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 @@ -10182,9 +8615,7 @@ external get_smtlib_num_sorts : context -> int (** 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 @@ -10193,50 +8624,43 @@ external get_smtlib_sort : context -> int -> 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_z3V3_Z3_get_smtlib_error" -(** - Summary: \[ [ parse_z3_string c str ] \] - Parse the given string using the Z3 native parser. - - Return the conjunction of asserts made in the input. - - def_API('parse_z3_string', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_string" - -(** - Summary: Similar to {!parse_z3_string}, but reads the benchmark from a file. - - def_API('parse_z3_file', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_file" - (** {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" (** - Summary: Reset all allocated resources. + 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" - Use this facility on out-of memory errors. +(** + 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 @@ -10277,15 +8701,12 @@ external theory_get_context : theory -> 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. - + 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. *) @@ -10296,7 +8717,6 @@ external theory_assert_axiom : theory -> ast -> unit 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 @@ -10304,7 +8724,7 @@ external theory_assume_eq : theory -> ast -> ast -> unit (** Summary: Enable/disable the simplification of theory axioms asserted using {!theory_assert_axiom}. - By default, the simplification of theory specific operators is disabled. + 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. *) @@ -10319,12 +8739,11 @@ external theory_get_eqc_root : theory -> ast -> ast (** 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 + 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 + {v ast curr = n; do curr = theory_get_eqc_next(theory, curr); @@ -10335,14 +8754,14 @@ external theory_get_eqc_next : theory -> ast -> ast = "camlidl_z3V3_Z3_theory_get_eqc_next" (** - Summary: Return the number of parents of [n] that are operators of the given theory. + 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" (** - Summary: Return the i-th parent of [n]. - See {!theory_get_num_parents}. + 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" @@ -10369,7 +8788,6 @@ external theory_get_num_elems : theory -> int (** 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 @@ -10385,7 +8803,6 @@ external theory_get_num_apps : theory -> int (** 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 @@ -10396,11 +8813,9 @@ external theory_get_app : theory -> int -> ast *) (** 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 @@ -10414,9 +8829,7 @@ external mk_injective_function : context -> symbol -> sort array -> sort -> func 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 @@ -10424,15 +8837,11 @@ external set_logic : context -> string -> bool (** Summary: Create a backtracking point. - - The logical context can be viewed as a stack of contexts. The + 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 @@ -10440,17 +8849,13 @@ external push : context -> unit (** 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 + 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 @@ -10458,38 +8863,17 @@ external pop : context -> int -> unit (** 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" (** - - - - - - - - - - - - - - - - - @deprecated This function has no effect. - + @deprecated This function has no effect. def_API('persist_ast', VOID, (_in(CONTEXT), _in(AST), _in(UINT))) *) external persist_ast : context -> ast -> int -> unit @@ -10497,18 +8881,13 @@ external persist_ast : context -> ast -> int -> unit (** Summary: Assert a constraint into the logical context. - After one assertion, the logical context may become - inconsistent. - + 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 @@ -10516,25 +8895,13 @@ external assert_cnstr : context -> ast -> unit (** 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. - - - - - - + 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 @@ -10542,13 +8909,9 @@ external check_and_get_model : context -> lbool * 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 @@ -10556,40 +8919,23 @@ external check : context -> lbool (** 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. - - - - - + 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. + @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, + 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 @@ -10597,25 +8943,20 @@ external check_assumptions : context -> ast array -> int -> ast array -> lbool * (** 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, + 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. The function return L_FALSE if the current assertions are not satisfiable. - - {b See also}: {!check_and_get_model} - {b See also}: {!check} - @deprecated Subsumed by solver API - def_API('get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) *) external get_implied_equalities : context -> ast array -> lbool * int array @@ -10623,11 +8964,8 @@ external get_implied_equalities : context -> ast array -> lbool * int array (** 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 @@ -10638,13 +8976,10 @@ external del_model : context -> model -> unit *) (** 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 @@ -10652,12 +8987,9 @@ external soft_check_cancel : context -> unit (** Summary: Retrieve reason for search failure. - - If a call to {!check} or {!check_and_get_model} returns L_UNDEF, + 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 @@ -10668,20 +9000,16 @@ external get_search_failure : context -> search_failure *) (** 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 + 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 @@ -10690,14 +9018,11 @@ external mk_label : context -> symbol -> bool -> ast -> ast (** 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 @@ -10705,30 +9030,24 @@ external get_relevant_labels : context -> literals (** 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 + 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 @@ -10736,11 +9055,8 @@ external get_guessed_literals : context -> 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 @@ -10748,11 +9064,8 @@ external del_literals : context -> literals -> unit (** 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 @@ -10760,9 +9073,7 @@ external get_num_literals : context -> literals -> 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 @@ -10770,9 +9081,7 @@ external get_label_symbol : context -> literals -> int -> symbol (** 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 @@ -10780,13 +9089,9 @@ external get_literal : context -> literals -> int -> ast (** 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 @@ -10794,9 +9099,7 @@ external disable_literal : context -> literals -> int -> unit (** 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 @@ -10807,13 +9110,9 @@ external block_literals : context -> literals -> unit *) (** Summary: Return the number of constants assigned by the given model. - - - {b Remarks}: Consider using {!get_model_constants}. - + - {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 @@ -10821,14 +9120,10 @@ external get_model_num_constants : context -> model -> int (** Summary: \[ [ get_model_constant c m i ] \] - Return the i-th constant in the given model. - - - {b Remarks}: Consider using {!get_model_constants}. - + 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 @@ -10836,12 +9131,9 @@ external get_model_constant : context -> model -> int -> func_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. - @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 @@ -10850,24 +9142,18 @@ external get_model_num_funcs : context -> model -> int (** 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))) *) 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 + 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))) *) external eval_func_decl : context -> model -> func_decl -> bool * ast @@ -10875,17 +9161,14 @@ external eval_func_decl : context -> model -> func_decl -> bool * ast (** 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 + 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 @@ -10895,11 +9178,8 @@ external is_array_value : context -> model -> ast -> bool * int 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 - + - {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 @@ -10908,20 +9188,14 @@ external get_array_value : context -> model -> ast -> ast array -> ast array -> (** 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 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 @@ -10930,20 +9204,14 @@ external get_model_func_else : context -> model -> int -> ast (** 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 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 @@ -10953,24 +9221,16 @@ external get_model_func_num_entries : context -> model -> int -> 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 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 @@ -10980,25 +9240,17 @@ external get_model_func_entry_num_args : context -> model -> int -> int -> int 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 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 @@ -11008,23 +9260,15 @@ external get_model_func_entry_arg : context -> model -> int -> int -> int -> ast 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 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 @@ -11032,21 +9276,14 @@ external get_model_func_entry_value : context -> model -> int -> int -> ast (** 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. - + 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 @@ -11054,12 +9291,9 @@ external eval : context -> model -> ast -> bool * ast (** 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 @@ -11070,17 +9304,10 @@ external eval_decl : context -> model -> func_decl -> ast array -> bool * ast *) (** 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 + @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 @@ -11088,17 +9315,10 @@ external context_to_string : context -> string (** 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. + @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 @@ -11106,129 +9326,98 @@ external statistics_to_string : context -> string (** 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}. - + 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 - +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 +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 -> +val get_model_funcs: context -> model -> (symbol * - (ast array * ast) array * + (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} @@ -11237,13 +9426,9 @@ val get_model_funcs: context -> model -> - {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} @@ -11252,13 +9437,9 @@ val get_smtlib_formulas: context -> ast array - {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} @@ -11267,13 +9448,9 @@ val get_smtlib_assumptions: context -> ast array - {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} @@ -11283,52 +9460,38 @@ val get_smtlib_decls: context -> func_decl array - {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. - + \[ [ 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. - + \[ [ 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} *) @@ -11336,23 +9499,17 @@ 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}: {!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 @@ -11364,122 +9521,91 @@ type sort_refined = | 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}: {!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 - +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 - +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 +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_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} + - {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. + - {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 - end diff --git a/src/api/ml/z3_stubs.c b/src/api/ml/z3_stubs.c index 0f32cb20e..0cf20fb2e 100644 --- a/src/api/ml/z3_stubs.c +++ b/src/api/ml/z3_stubs.c @@ -18,16 +18,13 @@ #define xstr(s) str(s) #define str(s) #s -#pragma warning(disable:4090) 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) { @@ -39,7 +36,6 @@ Z3_context last_ctx; } caml_final_register(**closure, v); } - value c2ml_Z3_context (Z3_context* c) { static value* finalize_Z3_context_closure = NULL; @@ -50,13 +46,11 @@ Z3_context last_ctx; (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; @@ -87,17 +81,15 @@ 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 int id1, id2; + unsigned id1, id2; ac1 = Data_custom_val(v1); ac2 = Data_custom_val(v2); id1 = Z3_get_ast_id(ac1->ctx, ac1->ast); @@ -106,11 +98,10 @@ static int compare_Z3_ast (value v1, value v2) check_error_code(ac2->ctx); return id2 - id1; } - static intnat hash_Z3_ast (value v) { Z3_ast_context* ac; - unsigned int hash; + unsigned hash; ac = Data_custom_val(v); hash = Z3_get_ast_hash(ac->ctx, ac->ast); check_error_code(ac->ctx); @@ -126,7 +117,6 @@ static intnat hash_Z3_ast (value v) check_error_code(ac->ctx); return Val_unit; } - static struct custom_operations cops_Z3_ast = { NULL, custom_finalize_default, @@ -135,7 +125,6 @@ static intnat hash_Z3_ast (value v) custom_serialize_default, custom_deserialize_default }; - value c2ml_Z3_ast (Z3_ast* c) { static value* finalize_Z3_ast_closure = NULL; @@ -156,7 +145,7 @@ static intnat hash_Z3_ast (value v) #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 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) @@ -177,7 +166,7 @@ DEFINE_SUBAST_OPS(Z3_pattern) #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 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) @@ -248,7 +237,7 @@ DEFINE_RC_OPS(Z3_stats) #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 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) @@ -682,9 +671,12 @@ value _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 }; @@ -703,8 +695,7 @@ void check_error_code (Z3_context c) 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_11[4] = { @@ -743,9 +734,7 @@ value caml_z3_mk_context(value key_val_list) 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); @@ -756,7 +745,6 @@ value caml_z3_mk_context(value key_val_list) 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); @@ -1238,7 +1226,7 @@ value camlidl_z3_Z3_mk_finite_domain_sort( { Z3_context c; /*in*/ Z3_symbol name; /*in*/ - __int64 size; /*in*/ + unsigned long long size; /*in*/ Z3_sort _res; value _vres; @@ -4286,7 +4274,7 @@ value camlidl_z3_Z3_mk_int64( value _v_ty) { Z3_context c; /*in*/ - __int64 v; /*in*/ + long long v; /*in*/ Z3_sort ty; /*in*/ Z3_ast _res; value _vres; @@ -5105,8 +5093,8 @@ value camlidl_z3_Z3_get_finite_domain_sort_size( { Z3_context c; /*in*/ Z3_sort s; /*in*/ - __int64 *r; /*out*/ - __int64 _c1; + unsigned long long *r; /*out*/ + unsigned long long _c1; value _v2; value _vres; @@ -6273,13 +6261,13 @@ value camlidl_z3_Z3_get_numeral_small( { Z3_context c; /*in*/ Z3_ast a; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -6342,11 +6330,11 @@ value camlidl_z3_Z3_get_numeral_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *i; /*out*/ + long long *i; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; + long long _c1; value _vresult; value _vres[2] = { 0, 0, }; @@ -6374,13 +6362,13 @@ value camlidl_z3_Z3_get_numeral_rational_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -8170,50 +8158,6 @@ check_error_code(c); return _vres; } -value camlidl_z3_Z3_parse_z3_string( - value _v_c, - value _v_str) -{ - Z3_context c; /*in*/ - Z3_string str; /*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_str, &str, _ctx); - _res = Z3_parse_z3_string(c, str); - _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_z3_file( - value _v_c, - value _v_file_name) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*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_file_name, &file_name, _ctx); - _res = Z3_parse_z3_file(c, file_name); - _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_set_error( value _v_c, value _v_e) @@ -8286,6 +8230,30 @@ value camlidl_z3_Z3_get_version(value _unit) 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) { @@ -8669,46 +8637,42 @@ check_error_code(c); return Val_unit; } -value camlidl_z3_Z3_fixedpoint_simplify_rules( +value camlidl_z3_Z3_fixedpoint_get_rules( value _v_c, - value _v_f, - value _v_rules, - value _v_outputs) + value _v_f) { Z3_context c; /*in*/ Z3_fixedpoint f; /*in*/ - unsigned int num_rules; /*in*/ - Z3_ast *rules; /*in*/ - unsigned int num_outputs; /*in*/ - Z3_func_decl *outputs; /*in*/ Z3_ast_vector _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_fixedpoint(_v_f, &f, _ctx); - _c1 = Wosize_val(_v_rules); - rules = camlidl_malloc(_c1 * sizeof(Z3_ast ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_rules, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &rules[_c2], _ctx); - } - num_rules = _c1; - _c4 = Wosize_val(_v_outputs); - outputs = camlidl_malloc(_c4 * sizeof(Z3_func_decl ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_outputs, _c5); - camlidl_ml2c_z3_Z3_func_decl(_v6, &outputs[_c5], _ctx); - } - num_outputs = _c4; - _res = Z3_fixedpoint_simplify_rules(c, f, num_rules, rules, num_outputs, outputs); + _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 */ @@ -8817,6 +8781,56 @@ check_error_code(c); 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) @@ -10692,6 +10706,30 @@ check_error_code(c); 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) @@ -11072,7 +11110,6 @@ check_error_code(c); return _vres; } -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); } } void camlidl_ml2c_z3V3_Z3_symbol(value _v1, Z3_symbol * _c2, camlidl_ctx _ctx) { *_c2 = *((Z3_symbol *) Bp_val(_v1)); @@ -11604,6 +11641,54 @@ value _v1; 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; @@ -11661,7 +11746,7 @@ value camlidl_z3V3_Z3_mk_context( _vres = camlidl_c2ml_z3V3_Z3_context(&_res, _ctx); camlidl_free(_ctx); /* begin user-supplied deallocation sequence */ -Z3_set_error_handler(_res, caml_z3_error_handler); +Z3_set_error_handler(_res, (void*)caml_z3_error_handler); /* end user-supplied deallocation sequence */ return _vres; } @@ -11857,7 +11942,7 @@ value camlidl_z3V3_Z3_mk_finite_domain_sort( { Z3_context c; /*in*/ Z3_symbol name; /*in*/ - __int64 size; /*in*/ + unsigned long long size; /*in*/ Z3_sort _res; value _vres; @@ -14575,7 +14660,7 @@ value camlidl_z3V3_Z3_mk_int64( value _v_ty) { Z3_context c; /*in*/ - __int64 v; /*in*/ + long long v; /*in*/ Z3_sort ty; /*in*/ Z3_ast _res; value _vres; @@ -15334,8 +15419,8 @@ value camlidl_z3V3_Z3_get_finite_domain_sort_size( { Z3_context c; /*in*/ Z3_sort s; /*in*/ - __int64 *r; /*out*/ - __int64 _c1; + unsigned long long *r; /*out*/ + unsigned long long _c1; value _v2; value _vres; @@ -16352,13 +16437,13 @@ value camlidl_z3V3_Z3_get_numeral_small( { Z3_context c; /*in*/ Z3_ast a; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -16415,11 +16500,11 @@ value camlidl_z3V3_Z3_get_numeral_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *i; /*out*/ + long long *i; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; + long long _c1; value _vresult; value _vres[2] = { 0, 0, }; @@ -16444,13 +16529,13 @@ value camlidl_z3V3_Z3_get_numeral_rational_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -17570,44 +17655,6 @@ value camlidl_z3V3_Z3_get_smtlib_error( return _vres; } -value camlidl_z3_Z3_parse_z3V3_string( - value _v_c, - value _v_str) -{ - Z3_context c; /*in*/ - Z3_string str; /*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_str, &str, _ctx); - _res = Z3_parse_z3_string(c, str); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3_Z3_parse_z3V3_file( - value _v_c, - value _v_file_name) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*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_file_name, &file_name, _ctx); - _res = Z3_parse_z3_file(c, file_name); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - value camlidl_z3V3_Z3_get_version(value _unit) { unsigned int *major; /*out*/ @@ -17640,6 +17687,30 @@ value camlidl_z3V3_Z3_get_version(value _unit) 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(); From 0831e020e39349134ef46a54bd55ab66f2b136bb Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 10 Dec 2012 17:25:28 -0800 Subject: [PATCH 10/57] add qe-lite tatic Signed-off-by: Nikolaj Bjorner --- src/muz_qe/qe_lite.cpp | 207 ++++++++++++++++++++++++++++++++++++----- src/muz_qe/qe_lite.h | 10 ++ 2 files changed, 195 insertions(+), 22 deletions(-) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index 8880a9ba5..3e15818e4 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -35,7 +35,7 @@ Revision History: #include "dl_util.h" #include "for_each_expr.h" #include "expr_safe_replace.h" - +#include "cooperate.h" class is_variable_proc { public: @@ -91,6 +91,7 @@ namespace eq { expr_ref_vector m_subst_map; expr_ref_buffer m_new_args; th_rewriter m_rewriter; + volatile bool m_cancel; void der_sort_vars(ptr_vector & vars, ptr_vector & definitions, unsigned_vector & order) { order.reset(); @@ -530,6 +531,7 @@ namespace eq { // Find all definitions for (unsigned i = 0; i < num_args; i++) { + checkpoint(); if (is_var_def(is_exists, args[i], v, t)) { unsigned idx = v->get_idx(); if(m_map.get(idx, 0) == 0) { @@ -569,6 +571,12 @@ namespace eq { return false; } + void checkpoint() { + cooperate("der"); + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + } + public: der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m) {} @@ -588,6 +596,7 @@ namespace eq { r = q; // Keep applying reduce_quantifier1 until r doesn't change anymore do { + checkpoint(); proof_ref curr_pr(m); q = to_quantifier(r); reduce_quantifier1(q, r, curr_pr); @@ -605,6 +614,12 @@ namespace eq { } ast_manager& get_manager() const { return m; } + + void set_cancel(bool f) { + m_rewriter.set_cancel(f); + m_cancel = f; + } + }; }; // namespace eq @@ -618,6 +633,7 @@ namespace ar { is_variable_proc* m_is_variable; ptr_vector m_todo; expr_mark m_visited; + volatile bool m_cancel; bool is_variable(expr * e) const { return (*m_is_variable)(e); @@ -723,13 +739,19 @@ namespace ar { return false; } + void checkpoint() { + cooperate("der"); + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + } public: - der(ast_manager& m): m(m), a(m), m_is_variable(0) {} + der(ast_manager& m): m(m), a(m), m_is_variable(0), m_cancel(false) {} void operator()(expr_ref_vector& fmls) { for (unsigned i = 0; i < fmls.size(); ++i) { + checkpoint(); solve_select(fmls, i, fmls[i].get()); solve_neq_select(fmls, i, fmls[i].get()); } @@ -738,6 +760,10 @@ namespace ar { void operator()(expr* e) {} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} + + void set_cancel(bool f) { + m_cancel = f; + } }; }; // namespace ar @@ -866,7 +892,6 @@ namespace fm { unsigned m_fm_cutoff2; unsigned m_fm_extra; bool m_fm_occ; - unsigned long long m_max_memory; unsigned m_counter; bool m_inconsistent; expr_dependency_ref m_inconsistent_core; @@ -1243,7 +1268,7 @@ namespace fm { // // --------------------------- - fm(ast_manager & _m, params_ref const & p): + fm(ast_manager & _m): m(_m), m_allocator("fm-elim"), m_util(m), @@ -1251,7 +1276,6 @@ namespace fm { m_var2expr(m), m_new_fmls(m), m_inconsistent_core(m) { - updt_params(p); m_cancel = false; } @@ -1259,14 +1283,13 @@ namespace fm { reset_constraints(); } - void updt_params(params_ref const & p) { - m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); - m_fm_real_only = p.get_bool("fm_real_only", true); - m_fm_limit = p.get_uint("fm_limit", 5000000); - m_fm_cutoff1 = p.get_uint("fm_cutoff1", 8); - m_fm_cutoff2 = p.get_uint("fm_cutoff2", 256); - m_fm_extra = p.get_uint("fm_extra", 0); - m_fm_occ = p.get_bool("fm_occ", false); + void updt_params() { + m_fm_real_only = true; + m_fm_limit = 5000000; + m_fm_cutoff1 = 8; + m_fm_cutoff2 = 256; + m_fm_extra = 0; + m_fm_occ = false; } void set_cancel(bool f) { @@ -2010,11 +2033,9 @@ namespace fm { } void checkpoint() { - // cooperate("fm"); + cooperate("fm"); if (m_cancel) throw tactic_exception(TACTIC_CANCELED_MSG); - if (memory::get_allocation_size() > m_max_memory) - throw tactic_exception(TACTIC_MAX_MEMORY_MSG); } public: @@ -2084,7 +2105,6 @@ namespace fm { class qe_lite::impl { ast_manager& m; - params_ref m_params; eq::der m_der; fm::fm m_fm; ar::der m_array_der; @@ -2106,7 +2126,7 @@ class qe_lite::impl { } public: - impl(ast_manager& m): m(m), m_der(m), m_fm(m, m_params), m_array_der(m) {} + impl(ast_manager& m): m(m), m_der(m), m_fm(m), m_array_der(m) {} void operator()(app_ref_vector& vars, expr_ref& fml) { if (vars.empty()) { @@ -2148,10 +2168,18 @@ public: } void operator()(expr_ref& fml, proof_ref& pr) { - // TODO apply der everywhere as a rewriting rule. - // TODO add cancel method. - if (is_quantifier(fml)) { - m_der(to_quantifier(fml), fml, pr); + if (is_exists(fml)) { + quantifier* q = to_quantifier(fml); + expr_ref body(m); + body = q->get_expr(); + uint_set indices; + for (unsigned i = 0; i < q->get_num_decls(); ++i) { + indices.insert(i); + } + (*this)(indices, true, body); + fml = m.update_quantifier(q, body); + th_rewriter rewriter(m); + rewriter(fml); } } @@ -2195,6 +2223,12 @@ public: TRACE("qe_lite", for (unsigned i = 0; i < fmls.size(); ++i) tout << mk_pp(fmls[i].get(), m) << "\n";); } + void set_cancel(bool f) { + m_der.set_cancel(f); + m_array_der.set_cancel(f); + m_fm.set_cancel(f); + } + }; qe_lite::qe_lite(ast_manager& m) { @@ -2209,6 +2243,10 @@ void qe_lite::operator()(app_ref_vector& vars, expr_ref& fml) { (*m_impl)(vars, fml); } +void qe_lite::set_cancel(bool f) { + m_impl->set_cancel(f); +} + void qe_lite::operator()(expr_ref& fml, proof_ref& pr) { (*m_impl)(fml, pr); } @@ -2220,3 +2258,128 @@ void qe_lite::operator()(uint_set const& index_set, bool index_of_bound, expr_re void qe_lite::operator()(uint_set const& index_set, bool index_of_bound, expr_ref_vector& fmls) { (*m_impl)(index_set, index_of_bound, fmls); } + +class qe_lite_tactic : public tactic { + + struct imp { + ast_manager& m; + qe_lite m_qe; + volatile bool m_cancel; + + imp(ast_manager& m, params_ref const& p): + m(m), + m_qe(m), + m_cancel(false) + {} + + void set_cancel(bool f) { + m_cancel = f; + m_qe.set_cancel(f); + } + + void checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("qe-lite"); + } + + void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + mc = 0; pc = 0; core = 0; + tactic_report report("qe-lite", *g); + proof_ref new_pr(m); + expr_ref new_f(m); + bool produce_proofs = g->proofs_enabled(); + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + checkpoint(); + if (g->inconsistent()) + break; + expr * f = g->form(i); + if (!has_quantifiers(f)) + continue; + new_f = f; + m_qe(new_f, new_pr); + if (produce_proofs) { + new_pr = m.mk_modus_ponens(g->pr(i), new_pr); + } + g->update(i, new_f, new_pr, g->dep(i)); + } + g->inc_depth(); + result.push_back(g.get()); + TRACE("qe", g->display(tout);); + SASSERT(g->is_well_sorted()); + } + + }; + + params_ref m_params; + imp * m_imp; + +public: + qe_lite_tactic(ast_manager & m, params_ref const & p): + m_params(p) { + m_imp = alloc(imp, m, p); + } + + virtual tactic * translate(ast_manager & m) { + return alloc(qe_lite_tactic, m, m_params); + } + + virtual ~qe_lite_tactic() { + dealloc(m_imp); + } + + virtual void updt_params(params_ref const & p) { + m_params = p; + // m_imp->updt_params(p); + } + + + virtual void collect_param_descrs(param_descrs & r) { + // m_imp->collect_param_descrs(r); + } + + virtual void operator()(goal_ref const & in, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + (*m_imp)(in, result, mc, pc, core); + } + + + virtual void collect_statistics(statistics & st) const { + // m_imp->collect_statistics(st); + } + + virtual void reset_statistics() { + // m_imp->reset_statistics(); + } + + + virtual void cleanup() { + ast_manager & m = m_imp->m; + imp * d = m_imp; + #pragma omp critical (tactic_cancel) + { + m_imp = 0; + } + dealloc(d); + d = alloc(imp, m, m_params); + #pragma omp critical (tactic_cancel) + { + m_imp = d; + } + } + +}; + +tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p) { + return alloc(qe_lite_tactic, m, p); +} diff --git a/src/muz_qe/qe_lite.h b/src/muz_qe/qe_lite.h index 3ffbf8fad..7d9239fa7 100644 --- a/src/muz_qe/qe_lite.h +++ b/src/muz_qe/qe_lite.h @@ -23,6 +23,9 @@ Revision History: #include "ast.h" #include "uint_set.h" +#include "params.h" + +class tactic; class qe_lite { class impl; @@ -56,6 +59,13 @@ public: \brief full rewriting based light-weight quantifier elimination round. */ void operator()(expr_ref& fml, proof_ref& pr); + + void set_cancel(bool f); }; +tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p = params_ref()); +/* + ADD_TACTIC("qe-light", "apply light-weight quantifier elimination.", "mk_qe_lite_tactic(m, p)") +*/ + #endif From 589f2c6bb36c85b70353d3cfbfc2c28f9674ede5 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 18:46:02 -0800 Subject: [PATCH 11/57] improved unknown parameter error msg Signed-off-by: Leonardo de Moura --- src/util/gparams.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 1305a1e02..8b1fbe40e 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -52,6 +52,7 @@ char const * g_params_renames[] = { "qi_cost", "smt.qi.cost", "qi_eager_threshold", "smt.qi.eager_threshold", "nl_arith", "smt.arith.nl", + "pull_nested_quantifiers", "smt.pull_nested_quantifiers", "nnf_sk_hack", "nnf.sk_hack", "model_v2", "model.v2", "pi_non_nested_arith_weight", "pi.non_nested_arith_weight", From 730801e2f01a71cc184008506789d8444eca5b8d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 10 Dec 2012 21:21:02 -0800 Subject: [PATCH 12/57] fix unintialized variable Signed-off-by: Nikolaj Bjorner --- src/muz_qe/qe_lite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index 3e15818e4..cced1ed50 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -578,7 +578,7 @@ namespace eq { } public: - der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m) {} + der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m), m_cancel(false) {} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} From b6459a8a92a347ec326e07052e5220406fb8a2f2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 10:53:21 -0800 Subject: [PATCH 13/57] add solver object to get_implied_equalities Signed-off-by: Nikolaj Bjorner --- src/api/api_solver_old.cpp | 7 +++++-- src/api/z3_api.h | 7 ++++--- src/smt/smt_implied_equalities.cpp | 32 ++++++++++++++---------------- src/smt/smt_implied_equalities.h | 7 +++++-- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/api/api_solver_old.cpp b/src/api/api_solver_old.cpp index cd4b797e3..d43e103c2 100644 --- a/src/api/api_solver_old.cpp +++ b/src/api/api_solver_old.cpp @@ -24,6 +24,7 @@ Revision History: #include"api_model.h" #include"smt_implied_equalities.h" #include"cancel_eh.h" +#include"api_solver.h" extern "C" { @@ -113,14 +114,16 @@ extern "C" { } Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c, + Z3_solver s, unsigned num_terms, Z3_ast const terms[], unsigned class_ids[]) { Z3_TRY; - LOG_Z3_get_implied_equalities(c, num_terms, terms, class_ids); + LOG_Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); + ast_manager& m = mk_c(c)->m(); RESET_ERROR_CODE(); CHECK_SEARCHING(c); - lbool result = smt::implied_equalities(mk_c(c)->get_smt_kernel(), num_terms, to_exprs(terms), class_ids); + lbool result = smt::implied_equalities(m, *to_solver_ref(s), num_terms, to_exprs(terms), class_ids); return static_cast(result); Z3_CATCH_RETURN(Z3_L_UNDEF); } diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 49d59e125..e12ce3591 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -7123,18 +7123,19 @@ END_MLAPI_EXCLUDE 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. + A side-effect of the function is a satisfiability check on the assertions on the solver that is passed in. The function return Z3_L_FALSE if the current assertions are not satisfiable. \sa Z3_check_and_get_model \sa Z3_check - \deprecated Subsumed by Z3_solver API + \deprecated To be moved outside of API. - def_API('Z3_get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) + def_API('Z3_get_implied_equalities', UINT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST), _out_array(2, UINT))) */ Z3_lbool Z3_API Z3_get_implied_equalities( __in Z3_context c, + __in Z3_solver s, __in unsigned num_terms, __in_ecount(num_terms) Z3_ast const terms[], __out_ecount(num_terms) unsigned class_ids[] diff --git a/src/smt/smt_implied_equalities.cpp b/src/smt/smt_implied_equalities.cpp index c6f28d4b2..70229ccab 100644 --- a/src/smt/smt_implied_equalities.cpp +++ b/src/smt/smt_implied_equalities.cpp @@ -21,23 +21,21 @@ Revision History: #include "smt_implied_equalities.h" #include "union_find.h" -#include "cmd_context.h" -#include "parametric_cmd.h" #include "ast_pp.h" -#include "arith_decl_plugin.h" -#include "datatype_decl_plugin.h" #include "array_decl_plugin.h" #include "uint_set.h" -#include "model_v2_pp.h" #include "smt_value_sort.h" - +#include "model_smt2_pp.h" +#include "stopwatch.h" +#include "model.h" +#include "solver.h" namespace smt { class get_implied_equalities_impl { ast_manager& m; - smt::kernel& m_solver; + solver& m_solver; union_find_default_ctx m_df; union_find m_uf; array_util m_array_util; @@ -98,7 +96,7 @@ namespace smt { ++m_stats_calls; m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(s, t))); - bool is_eq = l_false == m_solver.check(); + bool is_eq = l_false == m_solver.check_sat(0,0); m_solver.pop(1); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << (is_eq?"eq":"unrelated") << "\n";); if (is_eq) { @@ -125,7 +123,7 @@ namespace smt { m_stats_timer.start(); m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(s, t))); - bool is_eq = l_false == m_solver.check(); + bool is_eq = l_false == m_solver.check_sat(0,0); m_solver.pop(1); m_stats_timer.stop(); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << (is_eq?"eq":"unrelated") << "\n";); @@ -168,7 +166,7 @@ namespace smt { terms[i].term = m.mk_app(m_array_util.get_family_id(), OP_SELECT, 0, 0, args.size(), args.c_ptr()); } assert_relevant(terms); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); model_ref model1; m_solver.get_model(model1); SASSERT(model1.get()); @@ -218,7 +216,7 @@ namespace smt { expr* s = terms[vec[j]].term; m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(t, s))); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); m_solver.pop(1); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << is_sat << "\n";); if (is_sat == l_false) { @@ -237,7 +235,7 @@ namespace smt { if (!non_values.empty()) { - TRACE("get_implied_equalities", model_v2_pp(tout, *model, true);); + TRACE("get_implied_equalities", model_smt2_pp(tout, m, *model, 0);); get_implied_equalities_filter_basic(non_values, terms); //get_implied_equalities_basic(terms); } @@ -321,7 +319,7 @@ namespace smt { public: - get_implied_equalities_impl(smt::kernel& s) : m(s.m()), m_solver(s), m_uf(m_df), m_array_util(m), m_stats_calls(0) {} + get_implied_equalities_impl(ast_manager& m, solver& s) : m(m), m_solver(s), m_uf(m_df), m_array_util(m), m_stats_calls(0) {} lbool operator()(unsigned num_terms, expr* const* terms, unsigned* class_ids) { params_ref p; @@ -338,7 +336,7 @@ namespace smt { m_solver.push(); assert_relevant(num_terms, terms); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); if (is_sat != l_false) { model_ref model; @@ -374,8 +372,8 @@ namespace smt { stopwatch get_implied_equalities_impl::s_timer; stopwatch get_implied_equalities_impl::s_stats_val_eq_timer; - lbool implied_equalities(smt::kernel& solver, unsigned num_terms, expr* const* terms, unsigned* class_ids) { - get_implied_equalities_impl gi(solver); + lbool implied_equalities(ast_manager& m, solver& solver, unsigned num_terms, expr* const* terms, unsigned* class_ids) { + get_implied_equalities_impl gi(m, solver); return gi(num_terms, terms, class_ids); } }; @@ -552,7 +550,7 @@ namespace smt { m_solver.assert_expr(m.mk_implies(eq_lit, eq)); } m_solver.assert_expr(m.mk_not(m.mk_and(eqs.size(), eqs.c_ptr()))); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); switch(is_sat) { case l_false: for (unsigned i = 0; i + 1 < terms.size(); ++i) { diff --git a/src/smt/smt_implied_equalities.h b/src/smt/smt_implied_equalities.h index 6fc002ff1..ec9b4bd21 100644 --- a/src/smt/smt_implied_equalities.h +++ b/src/smt/smt_implied_equalities.h @@ -23,13 +23,16 @@ Revision History: #ifndef __SMT_IMPLIED_EQUALITIES_H__ #define __SMT_IMPLIED_EQUALITIES_H__ -#include"smt_kernel.h" +#include"smt_solver.h" +#include"lbool.h" +#include"ast.h" namespace smt { lbool implied_equalities( - kernel & solver, + ast_manager & m, + solver & solver, unsigned num_terms, expr* const* terms, unsigned* class_ids); From 2c9b14ada8549152fcaf60f3b9cec0148ea3e960 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 11:37:29 -0800 Subject: [PATCH 14/57] removed private API based on deprecated features Signed-off-by: Leonardo de Moura --- src/api/api_parsers.cpp | 74 ----------------------------------------- src/api/z3_private.h | 32 ------------------ 2 files changed, 106 deletions(-) diff --git a/src/api/api_parsers.cpp b/src/api/api_parsers.cpp index 69ca1fc81..8f6eb1125 100644 --- a/src/api/api_parsers.cpp +++ b/src/api/api_parsers.cpp @@ -252,42 +252,6 @@ extern "C" { // --------------- // Support for SMTLIB2 - class z3_context_solver : public solver_na2as { - api::context & m_ctx; - smt::kernel & ctx() const { return m_ctx.get_smt_kernel(); } - public: - virtual ~z3_context_solver() {} - z3_context_solver(api::context& c) : m_ctx(c) {} - virtual void init_core(ast_manager & m, symbol const & logic) {} - virtual void collect_statistics(statistics & st) const {} - virtual void reset_core() { ctx().reset(); } - virtual void assert_expr(expr * t) { ctx().assert_expr(t); } - virtual void push_core() { ctx().push(); } - virtual void pop_core(unsigned n) { ctx().pop(n); } - virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - return ctx().check(num_assumptions, assumptions); - } - virtual void get_unsat_core(ptr_vector & r) { - unsigned sz = ctx().get_unsat_core_size(); - for (unsigned i = 0; i < sz; i++) - r.push_back(ctx().get_unsat_core_expr(i)); - } - virtual void get_model(model_ref & m) { ctx().get_model(m); } - virtual proof * get_proof() { return ctx().get_proof(); } - virtual std::string reason_unknown() const { return ctx().last_failure_as_string(); } - virtual void get_labels(svector & r) { - buffer tmp; - ctx().get_relevant_labels(0, tmp); - r.append(tmp.size(), tmp.c_ptr()); - } - - // These are controlled by the main API - virtual void set_cancel(bool f) { } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - virtual void set_progress_callback(progress_callback * callback) {} - }; - Z3_ast parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is, unsigned num_sorts, Z3_symbol const sort_names[], @@ -298,9 +262,6 @@ extern "C" { Z3_TRY; cmd_context ctx(false, &(mk_c(c)->m())); ctx.set_ignore_check(true); - if (exec) { - ctx.set_solver(alloc(z3_context_solver, *mk_c(c))); - } for (unsigned i = 0; i < num_decls; ++i) { ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i])); } @@ -353,39 +314,4 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - - Z3_ast Z3_API Z3_exec_smtlib2_string(Z3_context c, Z3_string str, - unsigned num_sorts, - Z3_symbol sort_names[], - Z3_sort sorts[], - unsigned num_decls, - Z3_symbol decl_names[], - Z3_func_decl decls[]) { - Z3_TRY; - cmd_context ctx(false, &(mk_c(c)->m())); - std::string s(str); - std::istringstream is(s); - // No logging for this one, since it private. - return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - Z3_CATCH_RETURN(0); - } - - Z3_ast Z3_API Z3_exec_smtlib2_file(Z3_context c, Z3_string file_name, - unsigned num_sorts, - Z3_symbol sort_names[], - Z3_sort sorts[], - unsigned num_decls, - Z3_symbol decl_names[], - Z3_func_decl decls[]) { - Z3_TRY; - std::ifstream is(file_name); - if (!is) { - SET_ERROR_CODE(Z3_PARSER_ERROR); - return 0; - } - // No logging for this one, since it private. - return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - Z3_CATCH_RETURN(0); - } - }; diff --git a/src/api/z3_private.h b/src/api/z3_private.h index 17075a6c6..91becd158 100644 --- a/src/api/z3_private.h +++ b/src/api/z3_private.h @@ -36,38 +36,6 @@ extern "C" { Z3_bool Z3_API Z3_get_numeral_rational(__in Z3_context c, __in Z3_ast a, rational& r); - /** - \brief \mlh exec_smtlib2_string c str \endmlh - Parse the given string using the SMT-LIB2 parser and execute its commands. - - It returns a formula comprising of the conjunction of assertions in the scope - (up to push/pop) at the end of the string. - The returned formula is also asserted to the logical context on return. - */ - Z3_ast Z3_API Z3_exec_smtlib2_string(__in Z3_context c, - __in Z3_string str, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol sort_names[], - __in_ecount(num_sorts) Z3_sort sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol decl_names[], - __in_ecount(num_decls) Z3_func_decl decls[] - ); - - /** - \brief Similar to #Z3_exec_smtlib2_string, but reads the commands from a file. - */ - Z3_ast Z3_API Z3_exec_smtlib2_file(__in Z3_context c, - __in Z3_string file_name, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol sort_names[], - __in_ecount(num_sorts) Z3_sort sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol decl_names[], - __in_ecount(num_decls) Z3_func_decl decls[] - ); - - #ifndef CAMLIDL #ifdef __cplusplus }; From 299c5eb94726d4d6855ac2fe1ec865eeadbe9b89 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 16:41:25 -0800 Subject: [PATCH 15/57] make qe-light routine do a little more about traversal Signed-off-by: Nikolaj Bjorner --- src/muz_qe/qe_lite.cpp | 76 +++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index cced1ed50..df4a55475 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -2104,10 +2104,56 @@ namespace fm { } // namespace fm class qe_lite::impl { +public: + struct elim_cfg : public default_rewriter_cfg { + impl& m_imp; + ast_manager& m; + public: + elim_cfg(impl& i): m_imp(i), m(i.m) {} + + bool reduce_quantifier(quantifier * q, + expr * new_body, + expr * const * new_patterns, + expr * const * new_no_patterns, + expr_ref & result, + proof_ref & result_pr) { + result = new_body; + if (is_forall(q)) { + result = m.mk_not(result); + } + uint_set indices; + for (unsigned i = 0; i < q->get_num_decls(); ++i) { + indices.insert(i); + } + m_imp(indices, true, result); + if (is_forall(q)) { + result = m.mk_not(result); + } + result = m.update_quantifier( + q, + q->get_num_patterns(), new_patterns, + q->get_num_no_patterns(), new_no_patterns, result); + m_imp.m_rewriter(result); + return true; + } + }; + + class elim_star : public rewriter_tpl { + elim_cfg m_cfg; + public: + elim_star(impl& i): + rewriter_tpl(i.m, false, m_cfg), + m_cfg(i) + {} + }; + +private: ast_manager& m; eq::der m_der; fm::fm m_fm; ar::der m_array_der; + elim_star m_elim_star; + th_rewriter m_rewriter; bool has_unique_non_ground(expr_ref_vector const& fmls, unsigned& index) { index = fmls.size(); @@ -2126,7 +2172,13 @@ class qe_lite::impl { } public: - impl(ast_manager& m): m(m), m_der(m), m_fm(m), m_array_der(m) {} + impl(ast_manager& m): + m(m), + m_der(m), + m_fm(m), + m_array_der(m), + m_elim_star(*this), + m_rewriter(m) {} void operator()(app_ref_vector& vars, expr_ref& fml) { if (vars.empty()) { @@ -2165,22 +2217,12 @@ public: else { fml = tmp; } - } + } void operator()(expr_ref& fml, proof_ref& pr) { - if (is_exists(fml)) { - quantifier* q = to_quantifier(fml); - expr_ref body(m); - body = q->get_expr(); - uint_set indices; - for (unsigned i = 0; i < q->get_num_decls(); ++i) { - indices.insert(i); - } - (*this)(indices, true, body); - fml = m.update_quantifier(q, body); - th_rewriter rewriter(m); - rewriter(fml); - } + expr_ref tmp(m); + m_elim_star(fml, tmp, pr); + fml = tmp; } void operator()(uint_set const& index_set, bool index_of_bound, expr_ref& fml) { @@ -2227,6 +2269,8 @@ public: m_der.set_cancel(f); m_array_der.set_cancel(f); m_fm.set_cancel(f); + m_elim_star.set_cancel(f); + m_rewriter.set_cancel(f); } }; @@ -2383,3 +2427,5 @@ public: tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p) { return alloc(qe_lite_tactic, m, p); } + +template class rewriter_tpl; From 639f902ad170a96ec534b7c833c0ab3507eaa37a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 17:01:00 -0800 Subject: [PATCH 16/57] fix bug in difference logic recognizer, assert in proof_util Signed-off-by: Nikolaj Bjorner --- src/muz_qe/pdr_util.cpp | 6 +++++- src/muz_qe/proof_utils.cpp | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/muz_qe/pdr_util.cpp b/src/muz_qe/pdr_util.cpp index fd08b1aad..1ea705e6e 100644 --- a/src/muz_qe/pdr_util.cpp +++ b/src/muz_qe/pdr_util.cpp @@ -1129,7 +1129,11 @@ namespace pdr { if (a.is_numeral(lhs) || a.is_numeral(rhs)) { return test_ineq(e); } - return test_term(lhs) && test_term(rhs); + return + test_term(lhs) && + test_term(rhs) && + !a.is_mul(lhs) && + !a.is_mul(rhs); } bool test_term(expr* e) const { diff --git a/src/muz_qe/proof_utils.cpp b/src/muz_qe/proof_utils.cpp index 75c9cbb15..1e837b578 100644 --- a/src/muz_qe/proof_utils.cpp +++ b/src/muz_qe/proof_utils.cpp @@ -312,9 +312,10 @@ public: }; void proof_utils::reduce_hypotheses(proof_ref& pr) { - class reduce_hypotheses reduce(pr.get_manager()); + ast_manager& m = pr.get_manager(); + class reduce_hypotheses reduce(m); reduce(pr); - SASSERT(is_closed(pr.get_manager(), pr)); + CTRACE("proof_utils", !is_closed(m, pr), tout << mk_pp(pr, m) << "\n";); } class proof_is_closed { From 8198e62cbd0627ef698084a6fe2edf04b55101bc Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 17:47:27 -0800 Subject: [PATCH 17/57] solver factories, cleanup solver API, simplified strategic solver, added combined solver Signed-off-by: Leonardo de Moura --- src/api/api_solver.cpp | 37 +- src/api/api_solver.h | 15 +- src/cmd_context/cmd_context.cpp | 21 +- src/cmd_context/cmd_context.h | 6 +- src/cmd_context/context_params.cpp | 10 +- src/cmd_context/context_params.h | 9 +- src/parsers/smt/smtlib_solver.cpp | 2 +- src/shell/smtlib_frontend.cpp | 6 +- src/smt/smt_solver.cpp | 138 +++----- src/smt/smt_solver.h | 9 +- src/solver/combined_solver.cpp | 289 ++++++++++++++++ src/solver/combined_solver.h | 32 ++ src/solver/combined_solver_params.pyg | 9 + src/solver/solver.h | 31 +- src/solver/solver_na2as.cpp | 29 +- src/solver/solver_na2as.h | 8 +- src/solver/strategic_solver.cpp | 2 + src/solver/strategic_solver.h | 7 +- src/solver/tactic2solver.cpp | 326 ++++++++++-------- src/solver/tactic2solver.h | 96 +----- src/tactic/portfolio/smt_strategic_solver.cpp | 124 ++++--- src/tactic/portfolio/smt_strategic_solver.h | 6 +- 22 files changed, 720 insertions(+), 492 deletions(-) create mode 100644 src/solver/combined_solver.cpp create mode 100644 src/solver/combined_solver.h create mode 100644 src/solver/combined_solver_params.pyg diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 89bfd9519..6bf184708 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -34,15 +34,15 @@ Revision History: extern "C" { static void init_solver_core(Z3_context c, Z3_solver _s) { - ast_manager & m = mk_c(c)->m(); Z3_solver_ref * s = to_solver(_s); - mk_c(c)->params().init_solver_params(mk_c(c)->m(), *(s->m_solver), s->m_params); - s->m_solver->init(m, s->m_logic); - s->m_initialized = true; + bool proofs_enabled, models_enabled, unsat_core_enabled; + 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); } static void init_solver(Z3_context c, Z3_solver s) { - if (!to_solver(s)->m_initialized) + if (to_solver(s)->m_solver.get() == 0) init_solver_core(c, s); } @@ -50,8 +50,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_simple_solver(c); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = mk_smt_solver(); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_solver_factory()); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -62,8 +61,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver(c); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = mk_smt_strategic_solver(); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_strategic_solver_factory()); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -74,8 +72,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver_for_logic(c, logic); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref, to_symbol(logic)); - s->m_solver = mk_smt_strategic_solver(true /* force solver to use tactics even when auto_config is disabled */); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_strategic_solver_factory(to_symbol(logic))); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -86,8 +83,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver_from_tactic(c, t); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = alloc(tactic2solver, to_tactic_ref(t)); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_tactic2solver_factory(to_tactic_ref(t))); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -100,7 +96,12 @@ extern "C" { RESET_ERROR_CODE(); std::ostringstream buffer; param_descrs descrs; + bool initialized = to_solver(s)->m_solver.get() != 0; + if (!initialized) + init_solver(c, s); to_solver_ref(s)->collect_param_descrs(descrs); + if (!initialized) + to_solver(s)->m_solver = 0; descrs.display(buffer); return mk_c(c)->mk_external_string(buffer.str()); Z3_CATCH_RETURN(""); @@ -112,7 +113,12 @@ extern "C" { RESET_ERROR_CODE(); Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref); mk_c(c)->save_object(d); + bool initialized = to_solver(s)->m_solver.get() != 0; + if (!initialized) + init_solver(c, s); to_solver_ref(s)->collect_param_descrs(d->m_descrs); + if (!initialized) + to_solver(s)->m_solver = 0; Z3_param_descrs r = of_param_descrs(d); RETURN_Z3(r); Z3_CATCH_RETURN(0); @@ -122,7 +128,7 @@ extern "C" { Z3_TRY; LOG_Z3_solver_set_params(c, s, p); RESET_ERROR_CODE(); - if (to_solver(s)->m_initialized) { + if (to_solver(s)->m_solver) { bool old_model = to_solver(s)->m_params.get_bool("model", true); bool new_model = to_param_ref(p).get_bool("model", true); if (old_model != new_model) @@ -176,8 +182,7 @@ extern "C" { Z3_TRY; LOG_Z3_solver_reset(c, s); RESET_ERROR_CODE(); - to_solver_ref(s)->reset(); - to_solver(s)->m_initialized = false; + to_solver(s)->m_solver = 0; Z3_CATCH; } diff --git a/src/api/api_solver.h b/src/api/api_solver.h index 1569ef0da..f11c9bfd8 100644 --- a/src/api/api_solver.h +++ b/src/api/api_solver.h @@ -22,17 +22,16 @@ Revision History: #include"solver.h" struct Z3_solver_ref : public api::object { - solver * m_solver; - params_ref m_params; - bool m_initialized; - symbol m_logic; - Z3_solver_ref():m_solver(0), m_initialized(false), m_logic(symbol::null) {} - Z3_solver_ref(symbol const & logic):m_solver(0), m_initialized(false), m_logic(logic) {} - virtual ~Z3_solver_ref() { dealloc(m_solver); } + scoped_ptr m_solver_factory; + ref m_solver; + params_ref m_params; + symbol m_logic; + Z3_solver_ref(solver_factory * f):m_solver_factory(f), m_solver(0), m_logic(symbol::null) {} + virtual ~Z3_solver_ref() {} }; inline Z3_solver_ref * to_solver(Z3_solver s) { return reinterpret_cast(s); } inline Z3_solver of_solver(Z3_solver_ref * s) { return reinterpret_cast(s); } -inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver; } +inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver.get(); } #endif diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 828cc3a68..e86e56b69 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -582,8 +582,8 @@ void cmd_context::init_manager_core(bool new_manager) { // it prevents clashes with builtin types. insert(pm().mk_plist_decl()); } - if (m_solver) { - init_solver_options(m_solver.get()); + if (m_solver_factory) { + mk_solver(); } m_check_logic.set_logic(m(), m_logic); } @@ -1119,7 +1119,7 @@ void cmd_context::reset(bool finalize) { reset_func_decls(); restore_assertions(0); if (m_solver) - m_solver->reset(); + m_solver = 0; m_pp_env = 0; m_dt_eh = 0; if (m_manager) { @@ -1441,17 +1441,18 @@ void cmd_context::validate_model() { } } -void cmd_context::init_solver_options(solver * s) { +void cmd_context::mk_solver() { + bool proofs_enabled, models_enabled, unsat_core_enabled; params_ref p; - m_params.init_solver_params(m(), *m_solver, p); - m_solver->init(m(), m_logic); + m_params.get_solver_params(m(), p, proofs_enabled, models_enabled, unsat_core_enabled); + m_solver = (*m_solver_factory)(m(), p, proofs_enabled, models_enabled, unsat_core_enabled, m_logic); } -void cmd_context::set_solver(solver * s) { +void cmd_context::set_solver_factory(solver_factory * f) { + m_solver_factory = f; m_check_sat_result = 0; - m_solver = s; - if (has_manager() && s != 0) { - init_solver_options(s); + if (has_manager() && f != 0) { + mk_solver(); // assert formulas and create scopes in the new solver. unsigned lim = 0; svector::iterator it = m_scopes.begin(); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 2edc87ca6..63e5e7040 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -185,6 +185,7 @@ protected: }; svector m_scopes; + scoped_ptr m_solver_factory; ref m_solver; ref m_check_sat_result; @@ -243,7 +244,7 @@ protected: void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; } void print_unsupported_info(symbol const& s) { if (s != symbol::null) diagnostic_stream() << "; " << s << std::endl;} - void init_solver_options(solver * s); + void mk_solver(); public: cmd_context(bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null); @@ -289,8 +290,7 @@ public: 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; } - void set_solver(solver * s); - solver * get_solver() const { return m_solver.get(); } + void set_solver_factory(solver_factory * s); void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; } check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); } check_sat_state cs_state() const; diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 6d9222a37..2752967dd 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -131,11 +131,11 @@ params_ref context_params::merge_default_params(params_ref const & p) { } } -void context_params::init_solver_params(ast_manager & m, solver & s, params_ref const & p) { - s.set_produce_proofs(m.proofs_enabled() && m_proof); - s.set_produce_models(p.get_bool("model", m_model)); - s.set_produce_unsat_cores(p.get_bool("unsat_core", m_unsat_core)); - s.updt_params(merge_default_params(p)); +void context_params::get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled) { + proofs_enabled = m.proofs_enabled() && p.get_bool("proof", m_proof); + models_enabled = p.get_bool("model", m_model); + unsat_core_enabled = p.get_bool("unsat_core", m_unsat_core); + p = merge_default_params(p); } ast_manager * context_params::mk_ast_manager() { diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index dd60b9616..526b4f517 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -22,7 +22,6 @@ Notes: #include"params.h" class ast_manager; -class solver; class context_params { void set_bool(bool & opt, char const * param, char const * value); @@ -50,13 +49,9 @@ public: */ /** - \brief Goodie for updating the solver params - based on the configuration of the context_params object. - - This method is used when creating solvers from the - cmd_context and API. + \brief Goodies for extracting parameters for creating a solver object. */ - void init_solver_params(ast_manager & m, solver & s, params_ref const & p); + void get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled); /** \brief Include in p parameters derived from this context_params. diff --git a/src/parsers/smt/smtlib_solver.cpp b/src/parsers/smt/smtlib_solver.cpp index ef28216bf..7c8572ad8 100644 --- a/src/parsers/smt/smtlib_solver.cpp +++ b/src/parsers/smt/smtlib_solver.cpp @@ -86,7 +86,7 @@ namespace smtlib { benchmark.add_formula(m_ast_manager.mk_true()); } m_ctx = alloc(cmd_context, true, &m_ast_manager, benchmark.get_logic()); - m_ctx->set_solver(mk_smt_strategic_solver(false)); + m_ctx->set_solver_factory(mk_smt_strategic_solver_factory()); theory::expr_iterator fit = benchmark.begin_formulas(); theory::expr_iterator fend = benchmark.end_formulas(); for (; fit != fend; ++fit) diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 1551329c6..ef0b4ad6b 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -30,9 +30,6 @@ Revision History: #include"subpaving_cmds.h" #include"smt_strategic_solver.h" -#include"tactic2solver.h" -#include"qfnra_nlsat_tactic.h" - extern bool g_display_statistics; extern void display_config(); static clock_t g_start_time; @@ -98,8 +95,7 @@ unsigned read_smtlib2_commands(char const * file_name) { signal(SIGINT, on_ctrl_c); cmd_context ctx; - solver * s = mk_smt_strategic_solver(false); - ctx.set_solver(s); + ctx.set_solver_factory(mk_smt_strategic_solver_factory()); install_dl_cmds(ctx); install_dbg_cmds(ctx); diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index e8c1c6698..1fbb58847 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -25,166 +25,114 @@ namespace smt { class solver : public solver_na2as { smt_params m_params; - smt::kernel * m_context; + smt::kernel m_context; progress_callback * m_callback; + symbol m_logic; public: - solver():m_context(0), m_callback(0) {} - + solver(ast_manager & m, params_ref const & p, symbol const & l): + solver_na2as(m), + m_params(p), + m_context(m, m_params) { + m_logic = l; + if (m_logic != symbol::null) + m_context.set_logic(m_logic); + } + virtual ~solver() { - if (m_context != 0) - dealloc(m_context); } virtual void updt_params(params_ref const & p) { m_params.updt_params(p); - if (m_context == 0) - return; - m_context->updt_params(p); + m_context.updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - if (m_context == 0) { - ast_manager m; - reg_decl_plugins(m); - smt::kernel s(m, m_params); - s.collect_param_descrs(r); - } - else { - m_context->collect_param_descrs(r); - } - } - - virtual void init_core(ast_manager & m, symbol const & logic) { - reset(); - // We can throw exceptions when creating a smt::kernel object - // So, we should create the smt::kernel outside of the criticial section - // block. OMP does not allow exceptions to cross critical section boundaries. - smt::kernel * new_kernel = alloc(smt::kernel, m, m_params); - #pragma omp critical (solver) - { - m_context = new_kernel; - if (m_callback) - m_context->set_progress_callback(m_callback); - } - if (logic != symbol::null) - m_context->set_logic(logic); + m_context.collect_param_descrs(r); } virtual void collect_statistics(statistics & st) const { - if (m_context == 0) { - return; - } - else { - m_context->collect_statistics(st); - } - } - - virtual void reset_core() { - if (m_context != 0) { - #pragma omp critical (solver) - { - dealloc(m_context); - m_context = 0; - } - } - } - - // An exception may be thrown when creating a smt::kernel. - // So, there is no guarantee that m_context != 0 when - // using smt_solver from the SMT 2.0 command line frontend. - void check_context() const { - if (m_context == 0) - throw default_exception("Z3 failed to create solver, check previous error messages"); + m_context.collect_statistics(st); } virtual void assert_expr(expr * t) { - check_context(); - m_context->assert_expr(t); + m_context.assert_expr(t); } virtual void push_core() { - check_context(); - m_context->push(); + m_context.push(); } virtual void pop_core(unsigned n) { - check_context(); - m_context->pop(n); + m_context.pop(n); } virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - check_context(); TRACE("solver_na2as", tout << "smt_solver::check_sat_core: " << num_assumptions << "\n";); - return m_context->check(num_assumptions, assumptions); + return m_context.check(num_assumptions, assumptions); } virtual void get_unsat_core(ptr_vector & r) { - check_context(); - unsigned sz = m_context->get_unsat_core_size(); + unsigned sz = m_context.get_unsat_core_size(); for (unsigned i = 0; i < sz; i++) - r.push_back(m_context->get_unsat_core_expr(i)); + r.push_back(m_context.get_unsat_core_expr(i)); } virtual void get_model(model_ref & m) { - check_context(); - m_context->get_model(m); + m_context.get_model(m); } virtual proof * get_proof() { - check_context(); - return m_context->get_proof(); + return m_context.get_proof(); } virtual std::string reason_unknown() const { - check_context(); - return m_context->last_failure_as_string(); + return m_context.last_failure_as_string(); } virtual void get_labels(svector & r) { - check_context(); buffer tmp; - m_context->get_relevant_labels(0, tmp); + m_context.get_relevant_labels(0, tmp); r.append(tmp.size(), tmp.c_ptr()); } virtual void set_cancel(bool f) { -#pragma omp critical (solver) - { - if (m_context) - m_context->set_cancel(f); - } + m_context.set_cancel(f); } virtual void set_progress_callback(progress_callback * callback) { m_callback = callback; - if (m_context) - m_context->set_progress_callback(callback); + m_context.set_progress_callback(callback); } virtual unsigned get_num_assertions() const { - if (m_context) - return m_context->size(); - else - return 0; + return m_context.size(); } virtual expr * get_assertion(unsigned idx) const { - SASSERT(m_context); SASSERT(idx < get_num_assertions()); - return m_context->get_formulas()[idx]; + return m_context.get_formulas()[idx]; } virtual void display(std::ostream & out) const { - if (m_context) - m_context->display(out); - else - out << "(solver)"; + m_context.display(out); } }; }; -solver * mk_smt_solver() { - return alloc(smt::solver); +solver * mk_smt_solver(ast_manager & m, params_ref const & p, symbol const & logic) { + return alloc(smt::solver, m, p, logic); } + +class smt_solver_factory : public solver_factory { +public: + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_smt_solver(m, p, logic); + } +}; + +solver_factory * mk_smt_solver_factory() { + return alloc(smt_solver_factory); +} + diff --git a/src/smt/smt_solver.h b/src/smt/smt_solver.h index e9af9aafa..81c9a1319 100644 --- a/src/smt/smt_solver.h +++ b/src/smt/smt_solver.h @@ -21,8 +21,13 @@ Notes: #ifndef _SMT_SOLVER_H_ #define _SMT_SOLVER_H_ -class solver; +#include"ast.h" +#include"params.h" -solver * mk_smt_solver(); +class solver; +class solver_factory; + +solver * mk_smt_solver(ast_manager & m, params_ref const & p, symbol const & logic); +solver_factory * mk_smt_solver_factory(); #endif diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp new file mode 100644 index 000000000..cd4191e76 --- /dev/null +++ b/src/solver/combined_solver.cpp @@ -0,0 +1,289 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + combined_solver.cpp + +Abstract: + + Implements the solver API by combining two solvers. + + This is a replacement for the strategic_solver class. + +Author: + + Leonardo (leonardo) 2012-12-11 + +Notes: + +--*/ +#include"solver.h" +#include"scoped_timer.h" +#include"combined_solver_params.hpp" +#define PS_VB_LVL 15 + +/** + \brief Implementation of the solver API that combines two given solvers. + + The combined solver has two modes: + - non-incremental + - incremental + In non-incremental mode, the first solver is used. + In incremental mode, the second one is used. + + A timeout for the second solver can be specified. + If the timeout is reached, then the first solver is executed. + + The object switches to incremental when: + - push is used + - assertions are peformed after a check_sat + - parameter ignore_solver1==false +*/ +class combined_solver : public solver { +public: + // Behavior when the incremental solver returns unknown. + enum inc_unknown_behavior { + IUB_RETURN_UNDEF, // just return unknown + IUB_USE_TACTIC_IF_QF, // invoke tactic if problem is quantifier free + IUB_USE_TACTIC // invoke tactic + }; + +private: + bool m_inc_mode; + bool m_check_sat_executed; + bool m_use_solver1_results; + ref m_solver1; + ref m_solver2; + + bool m_ignore_solver1; + inc_unknown_behavior m_inc_unknown_behavior; + unsigned m_inc_timeout; + + void switch_inc_mode() { + m_inc_mode = true; + } + + struct aux_timeout_eh : public event_handler { + solver * m_solver; + volatile bool m_canceled; + aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {} + virtual void operator()() { + m_solver->cancel(); + m_canceled = true; + } + }; + + void updt_local_params(params_ref const & _p) { + combined_solver_params p(_p); + m_inc_timeout = p.solver2_timeout(); + m_ignore_solver1 = p.ignore_solver1(); + m_inc_unknown_behavior = static_cast(p.solver2_unknown()); + } + + bool has_quantifiers() const { + unsigned sz = get_num_assertions(); + for (unsigned i = 0; i < sz; i++) { + if (::has_quantifiers(get_assertion(i))) + return true; + } + return false; + } + + bool use_solver1_when_undef() const { + switch (m_inc_unknown_behavior) { + case IUB_RETURN_UNDEF: return false; + case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); + case IUB_USE_TACTIC: return true; + default: + UNREACHABLE(); + return false; + } + } + +public: + combined_solver(solver * s1, solver * s2, params_ref const & p) { + m_solver1 = s1; + m_solver2 = s2; + updt_local_params(p); + m_inc_mode = false; + m_check_sat_executed = false; + m_use_solver1_results = true; + } + + virtual void updt_params(params_ref const & p) { + m_solver1->updt_params(p); + m_solver2->updt_params(p); + updt_local_params(p); + } + + virtual void collect_param_descrs(param_descrs & r) { + m_solver1->collect_param_descrs(r); + m_solver2->collect_param_descrs(r); + combined_solver_params::collect_param_descrs(r); + } + + virtual void set_produce_models(bool f) { + m_solver1->set_produce_models(f); + m_solver2->set_produce_models(f); + } + + virtual void assert_expr(expr * t) { + if (m_check_sat_executed) + switch_inc_mode(); + m_solver1->assert_expr(t); + m_solver2->assert_expr(t); + } + + virtual void assert_expr(expr * t, expr * a) { + if (m_check_sat_executed) + switch_inc_mode(); + m_solver1->assert_expr(t, a); + m_solver2->assert_expr(t, a); + } + + virtual void push() { + switch_inc_mode(); + m_solver1->push(); + m_solver2->push(); + } + + virtual void pop(unsigned n) { + switch_inc_mode(); + m_solver1->pop(n); + m_solver2->pop(n); + } + + virtual unsigned get_scope_level() const { + return m_solver1->get_scope_level(); + } + + virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) { + m_check_sat_executed = true; + + if (num_assumptions > 0 || // assumptions were provided + m_ignore_solver1) { + // must use incremental solver + switch_inc_mode(); + m_use_solver1_results = false; + return m_solver2->check_sat(num_assumptions, assumptions); + } + + if (m_inc_mode) { + if (m_inc_timeout == UINT_MAX) { + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";); + lbool r = m_solver2->check_sat(0, 0); + if (r != l_undef || !use_solver1_when_undef()) { + m_use_solver1_results = false; + return r; + } + } + else { + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (with timeout)\")\n";); + aux_timeout_eh eh(m_solver2.get()); + lbool r; + { + scoped_timer timer(m_inc_timeout, &eh); + r = m_solver2->check_sat(0, 0); + } + if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) { + m_use_solver1_results = false; + return r; + } + } + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";); + } + + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";); + m_use_solver1_results = true; + return m_solver1->check_sat(0, 0); + } + + virtual void set_cancel(bool f) { + m_solver1->set_cancel(f); + m_solver2->set_cancel(f); + } + + virtual void set_progress_callback(progress_callback * callback) { + m_solver1->set_progress_callback(callback); + m_solver2->set_progress_callback(callback); + } + + virtual unsigned get_num_assertions() const { + return m_solver1->get_num_assertions(); + } + + virtual expr * get_assertion(unsigned idx) const { + return m_solver1->get_assertion(idx); + } + + virtual void display(std::ostream & out) const { + m_solver1->display(out); + } + + virtual void collect_statistics(statistics & st) const { + if (m_use_solver1_results) + m_solver1->collect_statistics(st); + else + m_solver2->collect_statistics(st); + } + + virtual void get_unsat_core(ptr_vector & r) { + if (m_use_solver1_results) + m_solver1->get_unsat_core(r); + else + m_solver2->get_unsat_core(r); + } + + virtual void get_model(model_ref & m) { + if (m_use_solver1_results) + m_solver1->get_model(m); + else + m_solver2->get_model(m); + } + + virtual proof * get_proof() { + if (m_use_solver1_results) + return m_solver1->get_proof(); + else + return m_solver2->get_proof(); + } + + virtual std::string reason_unknown() const { + if (m_use_solver1_results) + return m_solver1->reason_unknown(); + else + return m_solver2->reason_unknown(); + } + + virtual void get_labels(svector & r) { + if (m_use_solver1_results) + return m_solver1->get_labels(r); + else + return m_solver2->get_labels(r); + } + +}; + + +solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p) { + return alloc(combined_solver, s1, s2, p); +} + +class combined_solver_factory : public solver_factory { + scoped_ptr m_f1; + scoped_ptr m_f2; +public: + combined_solver_factory(solver_factory * f1, solver_factory * f2):m_f1(f1), m_f2(f2) {} + virtual ~combined_solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_combined_solver((*m_f1)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic), + (*m_f2)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic), + p); + } +}; + +solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2) { + return alloc(combined_solver_factory, f1, f2); +} diff --git a/src/solver/combined_solver.h b/src/solver/combined_solver.h new file mode 100644 index 000000000..2ccace7f0 --- /dev/null +++ b/src/solver/combined_solver.h @@ -0,0 +1,32 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + combined_solver.cpp + +Abstract: + + Implements the solver API by combining two solvers. + + This is a replacement for the strategic_solver class. + +Author: + + Leonardo (leonardo) 2012-12-11 + +Notes: + +--*/ +#ifndef _COMBINED_SOLVER_H_ +#define _COMBINED_SOLVER_H_ + +#include"params.h" + +class solver; +class solver_factory; + +solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p); +solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2); + +#endif diff --git a/src/solver/combined_solver_params.pyg b/src/solver/combined_solver_params.pyg new file mode 100644 index 000000000..7e1635c16 --- /dev/null +++ b/src/solver/combined_solver_params.pyg @@ -0,0 +1,9 @@ +def_module_params('combined_solver', + description='combines two solvers: non-incremental (solver1) and incremental (solver2)', + export=True, + params=(('solver2_timeout', UINT, UINT_MAX, "fallback to solver 1 after timeout even when in incremental model"), + ('ignore_solver1', BOOL, False, "if true, solver 2 is always used"), + ('solver2_unknown', UINT, 1, "what should be done when solver 2 returns unknown: 0 - just return unknown, 1 - execute solver 1 if quantifier free problem, 2 - execute solver 1") + )) + + diff --git a/src/solver/solver.h b/src/solver/solver.h index 5cd3da52b..e047bace1 100644 --- a/src/solver/solver.h +++ b/src/solver/solver.h @@ -23,6 +23,14 @@ Notes: #include"progress_callback.h" #include"params.h" +class solver; + +class solver_factory { +public: + virtual ~solver_factory() {} + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) = 0; +}; + /** \brief Abstract interface for making solvers available in the Z3 API and front-ends such as SMT 2.0 and (legacy) SMT 1.0. @@ -34,7 +42,6 @@ Notes: - statistics - results based on check_sat_result API - interruption (set_cancel) - - resets */ class solver : public check_sat_result { public: @@ -50,12 +57,6 @@ public: */ virtual void collect_param_descrs(param_descrs & r) {} - /** - \brief Enable/Disable proof production for this solver object. - - It is invoked before init(m, logic). - */ - virtual void set_produce_proofs(bool f) {} /** \brief Enable/Disable model generation for this solver object. @@ -63,23 +64,7 @@ public: The user may optionally invoke it after init(m, logic). */ virtual void set_produce_models(bool f) {} - /** - \brief Enable/Disable unsat core generation for this solver object. - - It is invoked before init(m, logic). - */ - virtual void set_produce_unsat_cores(bool f) {} - /** - \brief Initialize the solver object with the given ast_manager and logic. - */ - virtual void init(ast_manager & m, symbol const & logic) = 0; - - /** - \brief Reset the solver internal state. All assertions should be removed. - */ - virtual void reset() = 0; - /** \brief Add a new formula to the assertion stack. */ diff --git a/src/solver/solver_na2as.cpp b/src/solver/solver_na2as.cpp index e71a9873b..9889b5872 100644 --- a/src/solver/solver_na2as.cpp +++ b/src/solver/solver_na2as.cpp @@ -22,8 +22,8 @@ Notes: #include"solver_na2as.h" #include"ast_smt2_pp.h" -solver_na2as::solver_na2as() { - m_manager = 0; +solver_na2as::solver_na2as(ast_manager & m): + m_manager(m) { } solver_na2as::~solver_na2as() { @@ -35,23 +35,16 @@ void solver_na2as::assert_expr(expr * t, expr * a) { assert_expr(t); } else { - SASSERT(m_manager != 0); SASSERT(is_uninterp_const(a)); - SASSERT(m_manager->is_bool(a)); - TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, *m_manager) << "\n" << mk_ismt2_pp(a, *m_manager) << "\n";); - m_manager->inc_ref(a); + SASSERT(m_manager.is_bool(a)); + TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, m_manager) << "\n" << mk_ismt2_pp(a, m_manager) << "\n";); + m_manager.inc_ref(a); m_assumptions.push_back(a); - expr_ref new_t(*m_manager); - new_t = m_manager->mk_implies(a, t); + expr_ref new_t(m_manager); + new_t = m_manager.mk_implies(a, t); assert_expr(new_t); } } - -void solver_na2as::init(ast_manager & m, symbol const & logic) { - SASSERT(m_assumptions.empty()); - m_manager = &m; - init_core(m, logic); -} struct append_assumptions { ptr_vector & m_assumptions; @@ -89,9 +82,9 @@ void solver_na2as::pop(unsigned n) { } void solver_na2as::restore_assumptions(unsigned old_sz) { - SASSERT(old_sz == 0 || m_manager != 0); + SASSERT(old_sz == 0); for (unsigned i = old_sz; i < m_assumptions.size(); i++) { - m_manager->dec_ref(m_assumptions[i]); + m_manager.dec_ref(m_assumptions[i]); } m_assumptions.shrink(old_sz); } @@ -100,7 +93,3 @@ unsigned solver_na2as::get_scope_level() const { return m_scopes.size(); } -void solver_na2as::reset() { - reset_core(); - restore_assumptions(0); -} diff --git a/src/solver/solver_na2as.h b/src/solver/solver_na2as.h index eb12479fc..15750344a 100644 --- a/src/solver/solver_na2as.h +++ b/src/solver/solver_na2as.h @@ -25,30 +25,26 @@ Notes: #include"solver.h" class solver_na2as : public solver { - ast_manager * m_manager; + ast_manager & m_manager; ptr_vector m_assumptions; unsigned_vector m_scopes; void restore_assumptions(unsigned old_sz); public: - solver_na2as(); + solver_na2as(ast_manager & m); virtual ~solver_na2as(); virtual void assert_expr(expr * t, expr * a); virtual void assert_expr(expr * t) = 0; // Subclasses of solver_na2as should redefine the following *_core methods instead of these ones. - virtual void init(ast_manager & m, symbol const & logic); virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions); virtual void push(); virtual void pop(unsigned n); virtual unsigned get_scope_level() const; - virtual void reset(); protected: - virtual void init_core(ast_manager & m, symbol const & logic) = 0; virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) = 0; virtual void push_core() = 0; virtual void pop_core(unsigned n) = 0; - virtual void reset_core() = 0; }; diff --git a/src/solver/strategic_solver.cpp b/src/solver/strategic_solver.cpp index 40d77066e..fa7458ea3 100644 --- a/src/solver/strategic_solver.cpp +++ b/src/solver/strategic_solver.cpp @@ -16,6 +16,7 @@ Author: Notes: --*/ +#if 0 #include"strategic_solver.h" #include"scoped_timer.h" #include"ast_smt2_pp.h" @@ -526,6 +527,7 @@ void strategic_solver::display(std::ostream & out) const { } } +#endif diff --git a/src/solver/strategic_solver.h b/src/solver/strategic_solver.h index 1883a88cd..0bae8b254 100644 --- a/src/solver/strategic_solver.h +++ b/src/solver/strategic_solver.h @@ -61,7 +61,8 @@ private: bool m_force_tactic; // use tactics even when auto_config = false bool m_inc_mode; bool m_check_sat_executed; - scoped_ptr m_inc_solver; + scoped_ptr m_inc_solver_factory; + ref m_inc_solver; unsigned m_inc_solver_timeout; inc_unknown_behavior m_inc_unknown_behavior; scoped_ptr m_default_fct; @@ -107,12 +108,12 @@ private: bool use_tactic_when_undef() const; public: - strategic_solver(); + strategic_solver(ast_manager & m, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); ~strategic_solver(); ast_manager & m() const { SASSERT(m_manager); return *m_manager; } - void set_inc_solver(solver * s); + void set_inc_solver_factory(solver_factory * s); void set_inc_solver_timeout(unsigned timeout); void set_default_tactic(tactic_factory * fct); void set_tactic_for(symbol const & logic, tactic_factory * fct); diff --git a/src/solver/tactic2solver.cpp b/src/solver/tactic2solver.cpp index e630f9c78..1268fbcea 100644 --- a/src/solver/tactic2solver.cpp +++ b/src/solver/tactic2solver.cpp @@ -19,96 +19,115 @@ Author: Notes: --*/ -#include"tactic2solver.h" +#include"solver_na2as.h" +#include"tactic.h" #include"ast_smt2_pp.h" -tactic2solver_core::ctx::ctx(ast_manager & m, symbol const & logic): - m_logic(logic), +/** + \brief Simulates the incremental solver interface using a tactic. + + Every query will be solved from scratch. So, this is not a good + option for applications trying to solve many easy queries that a + similar to each other. +*/ +class tactic2solver : public solver_na2as { + expr_ref_vector m_assertions; + unsigned_vector m_scopes; + ref m_result; + tactic_ref m_tactic; + symbol m_logic; + params_ref m_params; + bool m_produce_models; + bool m_produce_proofs; + bool m_produce_unsat_cores; +public: + tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); + virtual ~tactic2solver(); + + virtual void updt_params(params_ref const & p); + virtual void collect_param_descrs(param_descrs & r); + + virtual void set_produce_models(bool f) { m_produce_models = f; } + + virtual void assert_expr(expr * t); + + virtual void push_core(); + virtual void pop_core(unsigned n); + virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); + + virtual void set_cancel(bool f); + + virtual void collect_statistics(statistics & st) const; + virtual void get_unsat_core(ptr_vector & r); + virtual void get_model(model_ref & m); + virtual proof * get_proof(); + virtual std::string reason_unknown() const; + virtual void get_labels(svector & r) {} + + virtual void set_progress_callback(progress_callback * callback) {} + + virtual unsigned get_num_assertions() const; + virtual expr * get_assertion(unsigned idx) const; + + virtual void display(std::ostream & out) const; +}; + +tactic2solver::tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic): + solver_na2as(m), m_assertions(m) { + + m_tactic = t; + m_logic = logic; + m_params = p; + + m_produce_models = produce_models; + m_produce_proofs = produce_proofs; + m_produce_unsat_cores = produce_unsat_cores; } -tactic2solver_core::~tactic2solver_core() { +tactic2solver::~tactic2solver() { } -void tactic2solver_core::init_core(ast_manager & m, symbol const & logic) { - m_ctx = alloc(ctx, m, logic); -} - -void tactic2solver_core::updt_params(params_ref const & p) { +void tactic2solver::updt_params(params_ref const & p) { m_params = p; } -void tactic2solver_core::collect_param_descrs(param_descrs & r) { - if (m_ctx) { - if (!m_ctx->m_tactic) { - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = get_tactic(m_ctx->m(), m_params); - } - - if (m_ctx->m_tactic) { - m_ctx->m_tactic->collect_param_descrs(r); - } - - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = 0; - } - } - else { - m_ctx->m_tactic->collect_param_descrs(r); - } - } +void tactic2solver::collect_param_descrs(param_descrs & r) { + if (m_tactic.get()) + m_tactic->collect_param_descrs(r); } -void tactic2solver_core::reset_core() { - SASSERT(m_ctx); - m_ctx->m_assertions.reset(); - m_ctx->m_scopes.reset(); - m_ctx->m_result = 0; +void tactic2solver::assert_expr(expr * t) { + m_assertions.push_back(t); + m_result = 0; } -void tactic2solver_core::assert_expr(expr * t) { - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - m_ctx->m_result = 0; +void tactic2solver::push_core() { + m_scopes.push_back(m_assertions.size()); + m_result = 0; } -void tactic2solver_core::push_core() { - SASSERT(m_ctx); - m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); - m_ctx->m_result = 0; +void tactic2solver::pop_core(unsigned n) { + unsigned new_lvl = m_scopes.size() - n; + unsigned old_sz = m_scopes[new_lvl]; + m_assertions.shrink(old_sz); + m_scopes.shrink(new_lvl); + m_result = 0; } -void tactic2solver_core::pop_core(unsigned n) { - SASSERT(m_ctx); - unsigned new_lvl = m_ctx->m_scopes.size() - n; - unsigned old_sz = m_ctx->m_scopes[new_lvl]; - m_ctx->m_assertions.shrink(old_sz); - m_ctx->m_scopes.shrink(new_lvl); - m_ctx->m_result = 0; -} - -lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - SASSERT(m_ctx); - ast_manager & m = m_ctx->m(); - params_ref p = m_params; - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = get_tactic(m, p); - if (m_ctx->m_tactic) { - m_ctx->m_result = alloc(simple_check_sat_result, m); - } - } - if (!m_ctx->m_tactic) - return l_undef; - tactic & t = *(m_ctx->m_tactic); - simple_check_sat_result & result = *(m_ctx->m_result); +lbool tactic2solver::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { + if (m_tactic.get() == 0) + return l_false; + ast_manager & m = m_assertions.m(); + m_result = alloc(simple_check_sat_result, m); + m_tactic->cleanup(); + m_tactic->updt_params(m_params); + m_tactic->set_logic(m_logic); goal_ref g = alloc(goal, m, m_produce_proofs, m_produce_models, m_produce_unsat_cores); - t.set_logic(m_ctx->m_logic); - unsigned sz = m_ctx->m_assertions.size(); + + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - g->assert_expr(m_ctx->m_assertions.get(i)); + g->assert_expr(m_assertions.get(i)); } for (unsigned i = 0; i < num_assumptions; i++) { g->assert_expr(assumptions[i], m.mk_asserted(assumptions[i]), m.mk_leaf(assumptions[i])); @@ -119,17 +138,17 @@ lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const expr_dependency_ref core(m); std::string reason_unknown = "unknown"; try { - switch (::check_sat(t, g, md, pr, core, reason_unknown)) { + switch (::check_sat(*m_tactic, g, md, pr, core, reason_unknown)) { case l_true: - result.set_status(l_true); + m_result->set_status(l_true); break; case l_false: - result.set_status(l_false); + m_result->set_status(l_false); break; default: - result.set_status(l_undef); + m_result->set_status(l_undef); if (reason_unknown != "") - result.m_unknown = reason_unknown; + m_result->m_unknown = reason_unknown; break; } } @@ -137,112 +156,115 @@ lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const throw ex; } catch (z3_exception & ex) { - TRACE("tactic2solver_core", tout << "exception: " << ex.msg() << "\n";); - result.set_status(l_undef); - result.m_unknown = ex.msg(); + TRACE("tactic2solver", tout << "exception: " << ex.msg() << "\n";); + m_result->set_status(l_undef); + m_result->m_unknown = ex.msg(); } - t.collect_statistics(result.m_stats); - result.m_model = md; - result.m_proof = pr; + m_tactic->collect_statistics(m_result->m_stats); + m_result->m_model = md; + m_result->m_proof = pr; if (m_produce_unsat_cores) { ptr_vector core_elems; m.linearize(core, core_elems); - result.m_core.append(core_elems.size(), core_elems.c_ptr()); + m_result->m_core.append(core_elems.size(), core_elems.c_ptr()); } - - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = 0; - } - return result.status(); + m_tactic->cleanup(); + return m_result->status(); } -void tactic2solver_core::set_cancel(bool f) { - #pragma omp critical (tactic2solver_core) - { - if (m_ctx && m_ctx->m_tactic) - m_ctx->m_tactic->set_cancel(f); - } +void tactic2solver::set_cancel(bool f) { + if (m_tactic.get()) + m_tactic->set_cancel(f); } -void tactic2solver_core::collect_statistics(statistics & st) const { - if (m_ctx->m_result.get()) - m_ctx->m_result->collect_statistics(st); +void tactic2solver::collect_statistics(statistics & st) const { + if (m_result.get()) + m_result->collect_statistics(st); } -void tactic2solver_core::get_unsat_core(ptr_vector & r) { - if (m_ctx->m_result.get()) - m_ctx->m_result->get_unsat_core(r); +void tactic2solver::get_unsat_core(ptr_vector & r) { + if (m_result.get()) + m_result->get_unsat_core(r); } -void tactic2solver_core::get_model(model_ref & m) { - if (m_ctx->m_result.get()) - m_ctx->m_result->get_model(m); +void tactic2solver::get_model(model_ref & m) { + if (m_result.get()) + m_result->get_model(m); } -proof * tactic2solver_core::get_proof() { - if (m_ctx->m_result.get()) - return m_ctx->m_result->get_proof(); +proof * tactic2solver::get_proof() { + if (m_result.get()) + return m_result->get_proof(); else return 0; } -std::string tactic2solver_core::reason_unknown() const { - if (m_ctx->m_result.get()) - return m_ctx->m_result->reason_unknown(); +std::string tactic2solver::reason_unknown() const { + if (m_result.get()) + return m_result->reason_unknown(); else return std::string("unknown"); } -unsigned tactic2solver_core::get_num_assertions() const { - if (m_ctx) - return m_ctx->m_assertions.size(); - else - return 0; +unsigned tactic2solver::get_num_assertions() const { + return m_assertions.size(); } -expr * tactic2solver_core::get_assertion(unsigned idx) const { - SASSERT(m_ctx); - return m_ctx->m_assertions.get(idx); +expr * tactic2solver::get_assertion(unsigned idx) const { + return m_assertions.get(idx); } -void tactic2solver_core::display(std::ostream & out) const { - if (m_ctx) { - ast_manager & m = m_ctx->m_assertions.m(); - unsigned num = m_ctx->m_assertions.size(); - out << "(solver"; - for (unsigned i = 0; i < num; i++) { - out << "\n " << mk_ismt2_pp(m_ctx->m_assertions.get(i), m, 2); - } - out << ")"; +void tactic2solver::display(std::ostream & out) const { + ast_manager & m = m_assertions.m(); + unsigned num = m_assertions.size(); + out << "(solver"; + for (unsigned i = 0; i < num; i++) { + out << "\n " << mk_ismt2_pp(m_assertions.get(i), m, 2); } - else { - out << "(solver)"; + out << ")"; +} + +solver * mk_tactic2solver(ast_manager & m, + tactic * t, + params_ref const & p, + bool produce_proofs, + bool produce_models, + bool produce_unsat_cores, + symbol const & logic) { + return alloc(tactic2solver, m, t, p, produce_proofs, produce_models, produce_unsat_cores, logic); +} + +class tactic2solver_factory : public solver_factory { + ref m_tactic; +public: + tactic2solver_factory(tactic * t):m_tactic(t) { } + + virtual ~tactic2solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_tactic2solver(m, m_tactic.get(), p, proofs_enabled, models_enabled, unsat_core_enabled, logic); + } +}; + +class tactic_factory2solver_factory : public solver_factory { + scoped_ptr m_factory; +public: + tactic_factory2solver_factory(tactic_factory * f):m_factory(f) { + } + + virtual ~tactic_factory2solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + tactic * t = (*m_factory)(m, p); + return mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, logic); + } +}; + +solver_factory * mk_tactic2solver_factory(tactic * t) { + return alloc(tactic2solver_factory, t); } -tactic2solver::tactic2solver(tactic * t): - m_tactic(t) { -} - -tactic2solver::~tactic2solver() { -} - -tactic * tactic2solver::get_tactic(ast_manager & m, params_ref const & p) { - m_tactic->cleanup(); - m_tactic->updt_params(p); - return m_tactic.get(); -} - -tactic_factory2solver::~tactic_factory2solver() { -} - -void tactic_factory2solver::set_tactic(tactic_factory * f) { - m_tactic_factory = f; -} - -tactic * tactic_factory2solver::get_tactic(ast_manager & m, params_ref const & p) { - if (m_tactic_factory == 0) - return 0; - return (*m_tactic_factory)(m, p); +solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f) { + return alloc(tactic_factory2solver_factory, f); } diff --git a/src/solver/tactic2solver.h b/src/solver/tactic2solver.h index 0a057b04b..f20b1c4dd 100644 --- a/src/solver/tactic2solver.h +++ b/src/solver/tactic2solver.h @@ -22,88 +22,22 @@ Notes: #ifndef _TACTIC2SOLVER_H_ #define _TACTIC2SOLVER_H_ -#include"solver_na2as.h" -#include"tactic.h" +#include"params.h" +class ast_manager; +class tactic; +class tactic_factory; +class solver; +class solver_factory; -/** - \brief Simulates the incremental solver interface using a tactic. - - Every query will be solved from scratch. So, this is not a good - option for applications trying to solve many easy queries that a - similar to each other. -*/ -class tactic2solver_core : public solver_na2as { - struct ctx { - symbol m_logic; - expr_ref_vector m_assertions; - unsigned_vector m_scopes; - ref m_result; - tactic_ref m_tactic; - ctx(ast_manager & m, symbol const & logic); - ast_manager & m() const { return m_assertions.m(); } - }; - scoped_ptr m_ctx; - params_ref m_params; - bool m_produce_models; - bool m_produce_proofs; - bool m_produce_unsat_cores; -public: - tactic2solver_core():m_ctx(0), m_produce_models(false), m_produce_proofs(false), m_produce_unsat_cores(false) {} - virtual ~tactic2solver_core(); - - virtual tactic * get_tactic(ast_manager & m, params_ref const & p) = 0; - - virtual void updt_params(params_ref const & p); - virtual void collect_param_descrs(param_descrs & r); - - virtual void set_produce_proofs(bool f) { m_produce_proofs = f; } - virtual void set_produce_models(bool f) { m_produce_models = f; } - virtual void set_produce_unsat_cores(bool f) { m_produce_unsat_cores = f; } - - virtual void assert_expr(expr * t); - - virtual void init_core(ast_manager & m, symbol const & logic); - virtual void reset_core(); - virtual void push_core(); - virtual void pop_core(unsigned n); - virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); - - virtual void set_cancel(bool f); - - virtual void collect_statistics(statistics & st) const; - virtual void get_unsat_core(ptr_vector & r); - virtual void get_model(model_ref & m); - virtual proof * get_proof(); - virtual std::string reason_unknown() const; - virtual void get_labels(svector & r) {} - - virtual void set_progress_callback(progress_callback * callback) {} - - virtual unsigned get_num_assertions() const; - virtual expr * get_assertion(unsigned idx) const; - - virtual void display(std::ostream & out) const; -}; - -class tactic2solver : public tactic2solver_core { - tactic_ref m_tactic; -public: - tactic2solver(tactic * t); - virtual ~tactic2solver(); - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; - - -class tactic_factory2solver : public tactic2solver_core { - scoped_ptr m_tactic_factory; -public: - virtual ~tactic_factory2solver(); - /** - \brief Set tactic that will be used to process the satisfiability queries. - */ - void set_tactic(tactic_factory * f); - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; +solver * mk_tactic2solver(ast_manager & m, + tactic * t = 0, + params_ref const & p = params_ref(), + bool produce_proofs = false, + bool produce_models = true, + bool produce_unsat_cores = false, + symbol const & logic = symbol::null); +solver_factory * mk_tactic2solver_factory(tactic * t); +solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f); #endif diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 7a274a830..3d83d8815 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -18,7 +18,8 @@ Notes: --*/ #include"cmd_context.h" -#include"strategic_solver.h" +#include"combined_solver.h" +#include"tactic2solver.h" #include"qfbv_tactic.h" #include"qflia_tactic.h" #include"qfnia_tactic.h" @@ -36,57 +37,76 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" -MK_SIMPLE_TACTIC_FACTORY(qfuf_fct, mk_qfuf_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfidl_fct, mk_qfidl_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfauflia_fct, mk_qfauflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(auflia_fct, mk_auflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(auflira_fct, mk_auflira_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(aufnira_fct, mk_aufnira_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(ufnia_fct, mk_ufnia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(uflra_fct, mk_uflra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(lra_fct, mk_lra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfbv_fct, mk_qfbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(default_fct, mk_default_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfaufbv_fct, mk_qfaufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qflra_fct, mk_qflra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qflia_fct, mk_qflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfufbv_fct, mk_qfufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfnia_fct, mk_qfnia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfnra_fct, mk_qfnra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qffpa_fct, mk_qffpa_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(ufbv_fct, mk_ufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(horn_fct, mk_horn_tactic(m, p)); - -static void init(strategic_solver * s) { - s->set_default_tactic(alloc(default_fct)); - s->set_tactic_for(symbol("QF_UF"), alloc(qfuf_fct)); - s->set_tactic_for(symbol("QF_BV"), alloc(qfbv_fct)); - s->set_tactic_for(symbol("QF_IDL"), alloc(qfidl_fct)); - s->set_tactic_for(symbol("QF_LIA"), alloc(qflia_fct)); - s->set_tactic_for(symbol("QF_LRA"), alloc(qflra_fct)); - s->set_tactic_for(symbol("QF_NIA"), alloc(qfnia_fct)); - s->set_tactic_for(symbol("QF_NRA"), alloc(qfnra_fct)); - s->set_tactic_for(symbol("QF_AUFLIA"), alloc(qfauflia_fct)); - s->set_tactic_for(symbol("QF_AUFBV"), alloc(qfaufbv_fct)); - s->set_tactic_for(symbol("QF_ABV"), alloc(qfaufbv_fct)); - s->set_tactic_for(symbol("QF_UFBV"), alloc(qfufbv_fct)); - s->set_tactic_for(symbol("AUFLIA"), alloc(auflia_fct)); - s->set_tactic_for(symbol("AUFLIRA"), alloc(auflira_fct)); - s->set_tactic_for(symbol("AUFNIRA"), alloc(aufnira_fct)); - s->set_tactic_for(symbol("UFNIA"), alloc(ufnia_fct)); - s->set_tactic_for(symbol("UFLRA"), alloc(uflra_fct)); - s->set_tactic_for(symbol("LRA"), alloc(lra_fct)); - s->set_tactic_for(symbol("UFBV"), alloc(ufbv_fct)); - s->set_tactic_for(symbol("BV"), alloc(ufbv_fct)); - s->set_tactic_for(symbol("QF_FPA"), alloc(qffpa_fct)); - s->set_tactic_for(symbol("QF_FPABV"), alloc(qffpa_fct)); - s->set_tactic_for(symbol("HORN"), alloc(horn_fct)); +tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { + if (logic=="QF_UF") + return mk_qfufbv_tactic(m, p); + else if (logic=="QF_BV") + return mk_qfbv_tactic(m, p); + else if (logic=="QF_IDL") + return mk_qfidl_tactic(m, p); + else if (logic=="QF_LIA") + return mk_qflia_tactic(m, p); + else if (logic=="QF_LRA") + return mk_qflra_tactic(m, p); + else if (logic=="QF_NIA") + return mk_qfnia_tactic(m, p); + else if (logic=="QF_NRA") + return mk_qfnra_tactic(m, p); + else if (logic=="QF_AUFLIA") + return mk_qfauflia_tactic(m, p); + else if (logic=="QF_AUFBV") + return mk_qfaufbv_tactic(m, p); + else if (logic=="QF_ABV") + return mk_qfaufbv_tactic(m, p); + else if (logic=="QF_UFBV") + return mk_qfufbv_tactic(m, p); + else if (logic=="AUFLIA") + return mk_auflia_tactic(m, p); + else if (logic=="AUFLIRA") + return mk_auflira_tactic(m, p); + else if (logic=="AUFNIRA") + return mk_aufnira_tactic(m, p); + else if (logic=="UFNIA") + return mk_ufnia_tactic(m, p); + else if (logic=="UFLRA") + return mk_uflra_tactic(m, p); + else if (logic=="LRA") + return mk_lra_tactic(m, p); + else if (logic=="UFBV") + 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=="HORN") + return mk_horn_tactic(m, p); + else + return mk_default_tactic(m, p); } -solver * mk_smt_strategic_solver(bool force_tactic) { - strategic_solver * s = alloc(strategic_solver); - s->force_tactic(force_tactic); - s->set_inc_solver(mk_smt_solver()); - init(s); - return s; +class smt_strategic_solver_factory : public solver_factory { + symbol const & m_logic; +public: + smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {} + + virtual ~smt_strategic_solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + symbol l; + if (m_logic != symbol::null) + l = m_logic; + else + l = logic; + tactic * t = mk_tactic_for_logic(m, p, logic); + return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l), + mk_smt_solver(m, p, l), + p); + } +}; + +solver_factory * mk_smt_strategic_solver_factory(symbol const & logic) { + return alloc(smt_strategic_solver_factory, logic); } + diff --git a/src/tactic/portfolio/smt_strategic_solver.h b/src/tactic/portfolio/smt_strategic_solver.h index 060721e09..1d132532a 100644 --- a/src/tactic/portfolio/smt_strategic_solver.h +++ b/src/tactic/portfolio/smt_strategic_solver.h @@ -20,8 +20,8 @@ Notes: #ifndef _SMT_STRATEGIC_SOLVER_H_ #define _SMT_STRATEGIC_SOLVER_H_ -class solver; -// Create a strategic solver for the Z3 API -solver * mk_smt_strategic_solver(bool force_tactic=false); +class solver_factory; + +solver_factory * mk_smt_strategic_solver_factory(symbol const & logic = symbol::null); #endif From 528f34802220d93d95761b9c1466915b402c6343 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 17:51:49 -0800 Subject: [PATCH 18/57] Fixed bug Signed-off-by: Leonardo de Moura --- src/tactic/portfolio/smt_strategic_solver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 3d83d8815..4813cbe1a 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -87,7 +87,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const } class smt_strategic_solver_factory : public solver_factory { - symbol const & m_logic; + symbol m_logic; public: smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {} @@ -99,7 +99,7 @@ public: l = m_logic; else l = logic; - tactic * t = mk_tactic_for_logic(m, p, logic); + tactic * t = mk_tactic_for_logic(m, p, l); return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l), mk_smt_solver(m, p, l), p); From 13dda76ddb4be2453254333e7033fdcf634c17d6 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 18:00:09 -0800 Subject: [PATCH 19/57] Removed dead code Signed-off-by: Leonardo de Moura --- src/solver/strategic_solver.cpp | 535 -------------------------------- src/solver/strategic_solver.h | 154 --------- 2 files changed, 689 deletions(-) delete mode 100644 src/solver/strategic_solver.cpp delete mode 100644 src/solver/strategic_solver.h diff --git a/src/solver/strategic_solver.cpp b/src/solver/strategic_solver.cpp deleted file mode 100644 index fa7458ea3..000000000 --- a/src/solver/strategic_solver.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - strategic_solver.h - -Abstract: - - Strategies -> Solver - -Author: - - Leonardo (leonardo) 2011-05-19 - -Notes: - ---*/ -#if 0 -#include"strategic_solver.h" -#include"scoped_timer.h" -#include"ast_smt2_pp.h" - -// minimum verbosity level for portfolio verbose messages -#define PS_VB_LVL 15 - - -strategic_solver::ctx::ctx(ast_manager & m): - m_assertions(m), - m_assertion_names(m) { - } - -strategic_solver::strategic_solver(): - m_manager(0), - m_force_tactic(false), - m_inc_mode(false), - m_check_sat_executed(false), - m_inc_solver(0), - m_inc_solver_timeout(UINT_MAX), - m_inc_unknown_behavior(IUB_USE_TACTIC_IF_QF), - m_default_fct(0), - m_curr_tactic(0), - m_proof(0), - m_core(0), - m_callback(0) { - m_use_inc_solver_results = false; - DEBUG_CODE(m_num_scopes = 0;); - m_produce_proofs = false; - m_produce_models = false; - m_produce_unsat_cores = false; - m_auto_config = true; -} - -strategic_solver::~strategic_solver() { - SASSERT(!m_curr_tactic); - dictionary::iterator it = m_logic2fct.begin(); - dictionary::iterator end = m_logic2fct.end(); - for (; it != end; ++it) { - dealloc(it->m_value); - } - if (m_proof) - m().dec_ref(m_proof); - if (m_core) - m().dec_ref(m_core); -} - -bool strategic_solver::has_quantifiers() const { - unsigned sz = get_num_assertions(); - for (unsigned i = 0; i < sz; i++) { - if (::has_quantifiers(get_assertion(i))) - return true; - } - return false; -} - -/** - \brief Return true if a tactic should be used when the incremental solver returns unknown. -*/ -bool strategic_solver::use_tactic_when_undef() const { - switch (m_inc_unknown_behavior) { - case IUB_RETURN_UNDEF: return false; - case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); - case IUB_USE_TACTIC: return true; - default: - UNREACHABLE(); - return false; - } -} - -void strategic_solver::set_inc_solver(solver * s) { - SASSERT(m_inc_solver == 0); - SASSERT(m_num_scopes == 0); - m_inc_solver = s; - if (m_callback) - m_inc_solver->set_progress_callback(m_callback); -} - -void strategic_solver::updt_params(params_ref const & p) { - if (m_inc_solver) - m_inc_solver->updt_params(p); - m_params = p; - m_auto_config = p.get_bool("auto_config", true); -} - -void strategic_solver::collect_param_descrs(param_descrs & r) { - if (m_inc_solver) - m_inc_solver->collect_param_descrs(r); -} - -/** - \brief Set a timeout for each check_sat query that is processed by the inc_solver. - timeout == UINT_MAX means infinite - After the timeout a strategy is used. -*/ -void strategic_solver::set_inc_solver_timeout(unsigned timeout) { - m_inc_solver_timeout = timeout; -} - -/** - \brief Set the default tactic factory. - It is used if there is no tactic for a given logic. -*/ -void strategic_solver::set_default_tactic(tactic_factory * fct) { - m_default_fct = fct; -} - -/** - \brief Set a tactic factory for a given logic. -*/ -void strategic_solver::set_tactic_for(symbol const & logic, tactic_factory * fct) { - tactic_factory * old_fct; - if (m_logic2fct.find(logic, old_fct)) { - dealloc(old_fct); - } - m_logic2fct.insert(logic, fct); -} - -void strategic_solver::init(ast_manager & m, symbol const & logic) { - m_manager = &m; - m_logic = logic; - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->init(m, logic); - } - m_ctx = alloc(ctx, m); - TRACE("strategic_solver", tout << "strategic_solver was initialized.\n";); -} - -unsigned strategic_solver::get_num_assertions() const { - if (m_ctx == 0) - return 0; - return m_ctx->m_assertions.size(); -} - -expr * strategic_solver::get_assertion(unsigned idx) const { - SASSERT(m_ctx); - return m_ctx->m_assertions.get(idx); -} - -expr * strategic_solver::get_assertion_name(unsigned idx) const { - SASSERT(m_ctx); - SASSERT(m_produce_unsat_cores); - return m_ctx->m_assertion_names.get(idx); -} - -void strategic_solver::set_produce_proofs(bool f) { - m_produce_proofs = f; - // do not need to propagate to inc_solver since flag cannot be changed after initialization -} - -void strategic_solver::set_produce_models(bool f) { - m_produce_models = f; - if (m_inc_solver) - m_inc_solver->set_produce_models(f); -} - -void strategic_solver::set_produce_unsat_cores(bool f) { - m_produce_unsat_cores = f; - // do not need to propagate to inc_solver since flag cannot be changed after initialization -} - -// delayed inc solver initialization -void strategic_solver::init_inc_solver() { - if (m_inc_mode) - return; // solver was already initialized - if (!m_inc_solver) - return; // inc solver was not installed - m_inc_mode = true; - m_inc_solver->set_produce_proofs(m_produce_proofs); - m_inc_solver->set_produce_models(m_produce_models); - m_inc_solver->set_produce_unsat_cores(m_produce_unsat_cores); - m_inc_solver->init(m(), m_logic); - unsigned sz = get_num_assertions(); - if (m_produce_unsat_cores) { - SASSERT(m_ctx->m_assertions.size() == m_ctx->m_assertion_names.size()); - for (unsigned i = 0; i < sz; i++) { - m_inc_solver->assert_expr(get_assertion(i), get_assertion_name(i)); - } - } - else { - for (unsigned i = 0; i < sz; i++) { - m_inc_solver->assert_expr(get_assertion(i)); - } - } -} - -void strategic_solver::collect_statistics(statistics & st) const { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->collect_statistics(st); - } - else { - if (m_curr_tactic) - m_curr_tactic->collect_statistics(st); // m_curr_tactic is still being executed. - else - st.copy(m_stats); - } -} - -void strategic_solver::reset() { - m_ctx = 0; - m_logic = symbol::null; - m_inc_mode = false; - m_check_sat_executed = false; - if (m_inc_solver) - m_inc_solver->reset(); - SASSERT(!m_curr_tactic); - m_use_inc_solver_results = false; - reset_results(); -} - -void strategic_solver::reset_results() { - m_use_inc_solver_results = false; - m_model = 0; - if (m_proof) { - m().dec_ref(m_proof); - m_proof = 0; - } - if (m_core) { - m().dec_ref(m_core); - m_core = 0; - } - m_reason_unknown.clear(); - m_stats.reset(); -} - -void strategic_solver::assert_expr(expr * t) { - if (m_check_sat_executed && !m_inc_mode) { - // a check sat was already executed --> switch to incremental mode - init_inc_solver(); - SASSERT(m_inc_solver == 0 || m_inc_mode); - } - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->assert_expr(t); - } - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.push_back(0); -} - -void strategic_solver::assert_expr(expr * t, expr * a) { - if (m_check_sat_executed && !m_inc_mode) { - // a check sat was already executed --> switch to incremental mode - init_inc_solver(); - SASSERT(m_inc_solver == 0 || m_inc_mode); - } - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->assert_expr(t, a); - } - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.push_back(a); -} - -void strategic_solver::push() { - DEBUG_CODE(m_num_scopes++;); - init_inc_solver(); - if (m_inc_solver) - m_inc_solver->push(); - m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); -} - -void strategic_solver::pop(unsigned n) { - DEBUG_CODE({ - SASSERT(n <= m_num_scopes); - m_num_scopes -= n; - }); - init_inc_solver(); - if (m_inc_solver) - m_inc_solver->pop(n); - - SASSERT(m_ctx); - unsigned new_lvl = m_ctx->m_scopes.size() - n; - unsigned old_sz = m_ctx->m_scopes[new_lvl]; - m_ctx->m_assertions.shrink(old_sz); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.shrink(old_sz); - m_ctx->m_scopes.shrink(new_lvl); -} - -unsigned strategic_solver::get_scope_level() const { - if (m_ctx == 0) - return 0; - return m_ctx->m_scopes.size(); -} - -struct aux_timeout_eh : public event_handler { - solver * m_solver; - volatile bool m_canceled; - aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {} - virtual void operator()() { - m_solver->cancel(); - m_canceled = true; - } -}; - -struct strategic_solver::mk_tactic { - strategic_solver * m_solver; - - mk_tactic(strategic_solver * s, tactic_factory * f, params_ref const & p):m_solver(s) { - ast_manager & m = s->m(); - tactic * tct = (*f)(m, p); - tct->set_logic(s->m_logic); - if (s->m_callback) - tct->set_progress_callback(s->m_callback); - #pragma omp critical (strategic_solver) - { - s->m_curr_tactic = tct; - } - } - - ~mk_tactic() { - #pragma omp critical (strategic_solver) - { - m_solver->m_curr_tactic = 0; - } - } -}; - -tactic_factory * strategic_solver::get_tactic_factory() const { - tactic_factory * f = 0; - if (m_logic2fct.find(m_logic, f)) - return f; - return m_default_fct.get(); -} - -lbool strategic_solver::check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions) { - if (!m_inc_solver) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver was not installed, returning unknown...\n";); - m_use_inc_solver_results = false; - m_reason_unknown = "incomplete"; - return l_undef; - } - init_inc_solver(); - m_use_inc_solver_results = true; - TRACE("strategic_solver", tout << "invoking inc_solver with " << num_assumptions << " assumptions\n";); - return m_inc_solver->check_sat(num_assumptions, assumptions); -} - -lbool strategic_solver::check_sat(unsigned num_assumptions, expr * const * assumptions) { - TRACE("strategic_solver", tout << "assumptions at strategic_solver:\n"; - for (unsigned i = 0; i < num_assumptions; i++) { - tout << mk_ismt2_pp(assumptions[i], m()) << "\n"; - } - tout << "m_produce_unsat_cores: " << m_produce_unsat_cores << ", m_inc_mode: " << m_inc_mode << "\n";); - reset_results(); - m_check_sat_executed = true; - if (num_assumptions > 0 || // assumptions were provided - (!m_auto_config && !m_force_tactic) // auto config and force_tactic are turned off - ) { - // must use incremental solver - return check_sat_with_assumptions(num_assumptions, assumptions); - } - - tactic_factory * factory = get_tactic_factory(); - if (factory == 0) - init_inc_solver(); // try to switch to incremental solver - - if (m_inc_mode) { - SASSERT(m_inc_solver); - unsigned timeout = m_inc_solver_timeout; - if (factory == 0) - timeout = UINT_MAX; // there is no tactic available - if (timeout == UINT_MAX) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "using incremental solver (without a timeout).\n";); - m_use_inc_solver_results = true; - lbool r = m_inc_solver->check_sat(0, 0); - if (r != l_undef || factory == 0 || !use_tactic_when_undef()) { - m_use_inc_solver_results = true; - return r; - } - } - else { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "using incremental solver (with timeout).\n";); - SASSERT(factory != 0); - aux_timeout_eh eh(m_inc_solver.get()); - lbool r; - { - scoped_timer timer(m_inc_solver_timeout, &eh); - r = m_inc_solver->check_sat(0, 0); - } - if ((r != l_undef || !use_tactic_when_undef()) && !eh.m_canceled) { - m_use_inc_solver_results = true; - return r; - } - } - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver failed, trying tactic.\n";); - } - - m_use_inc_solver_results = false; - - if (factory == 0) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "there is no tactic available for the current logic.\n";); - m_reason_unknown = "incomplete"; - return l_undef; - } - - goal_ref g = alloc(goal, m(), m_produce_proofs, m_produce_models, m_produce_unsat_cores); - unsigned sz = get_num_assertions(); - if (m_produce_unsat_cores) { - SASSERT(m_ctx->m_assertions.size() == m_ctx->m_assertion_names.size()); - for (unsigned i = 0; i < sz; i++) - g->assert_expr(get_assertion(i), get_assertion_name(i)); - } - else { - for (unsigned i = 0; i < sz; i++) - g->assert_expr(get_assertion(i)); - } - expr_dependency_ref core(m()); - - TRACE("strategic_solver", tout << "using goal...\n"; g->display_with_dependencies(tout);); - - mk_tactic tct_maker(this, factory, m_params); - SASSERT(m_curr_tactic); - - proof_ref pr(m()); - lbool r = ::check_sat(*(m_curr_tactic.get()), g, m_model, pr, core, m_reason_unknown); - m_curr_tactic->collect_statistics(m_stats); - if (pr) { - m_proof = pr; - m().inc_ref(m_proof); - } - if (core) { - m_core = core; - m().inc_ref(m_core); - } - return r; -} - -void strategic_solver::set_cancel(bool f) { - if (m_inc_solver) - m_inc_solver->set_cancel(f); - #pragma omp critical (strategic_solver) - { - if (m_curr_tactic) - m_curr_tactic->set_cancel(f); - } -} - -void strategic_solver::get_unsat_core(ptr_vector & r) { - TRACE("strategic_solver", tout << "get_unsat_core, m_use_inc_solver_results: " << m_use_inc_solver_results << "\n";); - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_unsat_core(r); - } - else { - m().linearize(m_core, r); - } -} - -void strategic_solver::get_model(model_ref & m) { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_model(m); - } - else { - m = m_model; - } -} - -proof * strategic_solver::get_proof() { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - return m_inc_solver->get_proof(); - } - else { - return m_proof; - } -} - -std::string strategic_solver::reason_unknown() const { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - return m_inc_solver->reason_unknown(); - } - return m_reason_unknown; -} - -void strategic_solver::get_labels(svector & r) { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_labels(r); - } -} - -void strategic_solver::set_progress_callback(progress_callback * callback) { - m_callback = callback; - if (m_inc_solver) - m_inc_solver->set_progress_callback(callback); -} - -void strategic_solver::display(std::ostream & out) const { - if (m_manager) { - unsigned num = get_num_assertions(); - out << "(solver"; - for (unsigned i = 0; i < num; i++) { - out << "\n " << mk_ismt2_pp(get_assertion(i), m(), 2); - } - out << ")"; - } - else { - out << "(solver)"; - } -} - -#endif - - - - - diff --git a/src/solver/strategic_solver.h b/src/solver/strategic_solver.h deleted file mode 100644 index 0bae8b254..000000000 --- a/src/solver/strategic_solver.h +++ /dev/null @@ -1,154 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - strategic_solver.h - -Abstract: - - Strategies -> Solver - -Author: - - Leonardo (leonardo) 2011-05-19 - -Notes: - ---*/ -#ifndef _STRATEGIC_SOLVER_H_ -#define _STRATEGIC_SOLVER_H_ - -#include"solver.h" -#include"tactic.h" - -class progress_callback; - -/** - \brief Implementation of the solver API that supports: - - a different tactic for each logic - - a general purpose tactic - - a default incremental solver - - The strategic solver has two modes: - - non-incremental - - incremental - In non-incremental mode, tactics are used. - In incremental model, the incremental (general purpose) solver is used. - - A timeout for the incremental solver can be specified. - If the timeout is reached, then the strategic_solver tries to solve the problem using tactics. - - The strategic_solver switches to incremental when: - - push is used - - assertions are peformed after a check_sat - It goes back to non_incremental mode when: - - reset is invoked. -*/ -class strategic_solver : public solver { -public: - // Behavior when the incremental solver returns unknown. - enum inc_unknown_behavior { - IUB_RETURN_UNDEF, // just return unknown - IUB_USE_TACTIC_IF_QF, // invoke tactic if problem is quantifier free - IUB_USE_TACTIC // invoke tactic - }; - -private: - ast_manager * m_manager; - params_ref m_params; - symbol m_logic; - bool m_force_tactic; // use tactics even when auto_config = false - bool m_inc_mode; - bool m_check_sat_executed; - scoped_ptr m_inc_solver_factory; - ref m_inc_solver; - unsigned m_inc_solver_timeout; - inc_unknown_behavior m_inc_unknown_behavior; - scoped_ptr m_default_fct; - dictionary m_logic2fct; - - ref m_curr_tactic; - - bool m_use_inc_solver_results; - model_ref m_model; - proof * m_proof; - expr_dependency * m_core; - std::string m_reason_unknown; - statistics m_stats; - - struct ctx { - expr_ref_vector m_assertions; - expr_ref_vector m_assertion_names; - unsigned_vector m_scopes; - ctx(ast_manager & m); - }; - scoped_ptr m_ctx; - -#ifdef Z3DEBUG - unsigned m_num_scopes; -#endif - - bool m_produce_proofs; - bool m_produce_models; - bool m_produce_unsat_cores; - - bool m_auto_config; - - progress_callback * m_callback; - - void reset_results(); - void init_inc_solver(); - tactic_factory * get_tactic_factory() const; - lbool check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions); - - struct mk_tactic; - - bool has_quantifiers() const; - bool use_tactic_when_undef() const; - -public: - strategic_solver(ast_manager & m, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); - ~strategic_solver(); - - ast_manager & m() const { SASSERT(m_manager); return *m_manager; } - - void set_inc_solver_factory(solver_factory * s); - void set_inc_solver_timeout(unsigned timeout); - void set_default_tactic(tactic_factory * fct); - void set_tactic_for(symbol const & logic, tactic_factory * fct); - void set_inc_unknown_behavior(inc_unknown_behavior b) { m_inc_unknown_behavior = b; } - void force_tactic(bool f) { m_force_tactic = f; } - - virtual void updt_params(params_ref const & p); - virtual void collect_param_descrs(param_descrs & r); - - virtual void set_produce_proofs(bool f); - virtual void set_produce_models(bool f); - virtual void set_produce_unsat_cores(bool f); - - unsigned get_num_assertions() const; - expr * get_assertion(unsigned idx) const; - expr * get_assertion_name(unsigned idx) const; - - virtual void display(std::ostream & out) const; - - virtual void init(ast_manager & m, symbol const & logic); - virtual void collect_statistics(statistics & st) const; - virtual void reset(); - virtual void assert_expr(expr * t); - virtual void assert_expr(expr * t, expr * a); - virtual void push(); - virtual void pop(unsigned n); - virtual unsigned get_scope_level() const; - virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions); - virtual void get_unsat_core(ptr_vector & r); - virtual void get_model(model_ref & m); - virtual proof * get_proof(); - virtual std::string reason_unknown() const; - virtual void get_labels(svector & r); - virtual void set_cancel(bool f); - virtual void set_progress_callback(progress_callback * callback); -}; - -#endif From 635aabf2d58763818acefbfe471eb7fb77b6fbfa Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 21:39:31 -0800 Subject: [PATCH 20/57] fix get_implied equalities and the unit test Signed-off-by: Nikolaj Bjorner --- src/api/api_solver.cpp | 19 +++++++++++++++++++ src/api/api_solver_old.cpp | 17 ----------------- src/test/get_implied_equalities.cpp | 28 +++++++++++++++++----------- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 6bf184708..9ace149af 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -30,6 +30,7 @@ Revision History: #include"scoped_timer.h" #include"smt_strategic_solver.h" #include"smt_solver.h" +#include"smt_implied_equalities.h" extern "C" { @@ -357,4 +358,22 @@ extern "C" { return mk_c(c)->mk_external_string(buffer.str()); Z3_CATCH_RETURN(""); } + + + Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c, + Z3_solver s, + unsigned num_terms, + Z3_ast const terms[], + unsigned class_ids[]) { + Z3_TRY; + LOG_Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); + ast_manager& m = mk_c(c)->m(); + RESET_ERROR_CODE(); + CHECK_SEARCHING(c); + init_solver(c, s); + lbool result = smt::implied_equalities(m, *to_solver_ref(s), num_terms, to_exprs(terms), class_ids); + return static_cast(result); + Z3_CATCH_RETURN(Z3_L_UNDEF); + } + }; diff --git a/src/api/api_solver_old.cpp b/src/api/api_solver_old.cpp index d43e103c2..c89f89873 100644 --- a/src/api/api_solver_old.cpp +++ b/src/api/api_solver_old.cpp @@ -22,9 +22,7 @@ Revision History: #include"api_log_macros.h" #include"api_context.h" #include"api_model.h" -#include"smt_implied_equalities.h" #include"cancel_eh.h" -#include"api_solver.h" extern "C" { @@ -113,21 +111,6 @@ extern "C" { Z3_CATCH_RETURN(Z3_L_UNDEF); } - Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c, - Z3_solver s, - unsigned num_terms, - Z3_ast const terms[], - unsigned class_ids[]) { - Z3_TRY; - LOG_Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); - ast_manager& m = mk_c(c)->m(); - RESET_ERROR_CODE(); - CHECK_SEARCHING(c); - lbool result = smt::implied_equalities(m, *to_solver_ref(s), num_terms, to_exprs(terms), class_ids); - return static_cast(result); - Z3_CATCH_RETURN(Z3_L_UNDEF); - } - Z3_lbool Z3_API Z3_check_assumptions(Z3_context c, unsigned num_assumptions, Z3_ast const assumptions[], diff --git a/src/test/get_implied_equalities.cpp b/src/test/get_implied_equalities.cpp index 91c71438f..2576920cc 100644 --- a/src/test/get_implied_equalities.cpp +++ b/src/test/get_implied_equalities.cpp @@ -3,11 +3,11 @@ #include "debug.h" static Z3_ast mk_var(Z3_context ctx, char const* name, Z3_sort s) { - return Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, name), s); + return Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, name), s); } static Z3_ast mk_int_var(Z3_context ctx, char const* name) { - return mk_var(ctx, name, Z3_mk_int_sort(ctx)); + return mk_var(ctx, name, Z3_mk_int_sort(ctx)); } @@ -29,13 +29,15 @@ static void tst_get_implied_equalities1() { unsigned i; Z3_ast terms[7] = { a, b, c, d, fa, fb, fc }; unsigned class_ids[7] = { 0, 0, 0, 0, 0, 0, 0 }; + Z3_solver solver = Z3_mk_simple_solver(ctx); + Z3_solver_inc_ref(ctx, solver); - Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, a, b)); - Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, b, d)); - Z3_assert_cnstr(ctx, Z3_mk_le(ctx, fa, fc)); - Z3_assert_cnstr(ctx, Z3_mk_le(ctx, fc, d)); + Z3_solver_assert(ctx, solver, Z3_mk_eq(ctx, a, b)); + Z3_solver_assert(ctx, solver, Z3_mk_eq(ctx, b, d)); + Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, fa, fc)); + Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, fc, d)); - Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); + Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids); for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } @@ -48,8 +50,8 @@ static void tst_get_implied_equalities1() { SASSERT(class_ids[4] == class_ids[5]); printf("asserting b <= f(a)\n"); - Z3_assert_cnstr(ctx, Z3_mk_le(ctx, b, fa)); - Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); + Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, b, fa)); + Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids); for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } @@ -61,6 +63,7 @@ static void tst_get_implied_equalities1() { SASSERT(class_ids[6] == class_ids[0]); + Z3_solver_dec_ref(ctx, solver); /* delete logical context */ Z3_del_context(ctx); } @@ -72,6 +75,8 @@ static void tst_get_implied_equalities2() { Z3_config cfg = Z3_mk_config(); Z3_context ctx = Z3_mk_context(cfg); Z3_del_config(cfg); + Z3_solver solver = Z3_mk_simple_solver(ctx); + Z3_solver_inc_ref(ctx, solver); Z3_sort int_ty = Z3_mk_int_sort(ctx); Z3_ast a = mk_int_var(ctx,"a"); Z3_ast b = mk_int_var(ctx,"b"); @@ -87,7 +92,7 @@ static void tst_get_implied_equalities2() { Z3_ast terms[5] = { x, y, z, u, v}; unsigned class_ids[5] = { 0, 0, 0, 0, 0}; - Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); + Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids); for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } @@ -100,9 +105,10 @@ static void tst_get_implied_equalities2() { SASSERT(class_ids[2] != class_ids[1]); SASSERT(class_ids[3] != class_ids[1]); SASSERT(class_ids[4] != class_ids[1]); - SASSERT(class_ids[3] != class_ids[2]); + SASSERT(class_ids[3] != class_ids[2]); /* delete logical context */ + Z3_solver_dec_ref(ctx, solver); Z3_del_context(ctx); } From e13e12636a689be7a03c182220a0cb02d70d9d81 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 07:07:52 -0800 Subject: [PATCH 21/57] fixed mk_win_dist.py Signed-off-by: Leonardo de Moura --- scripts/mk_win_dist.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 57ae66b03..85360260c 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -18,8 +18,8 @@ from mk_exception import * from mk_project import * BUILD_DIR='build-dist' -BUILD_X64_DIR='build-dist/x64' -BUILD_X86_DIR='build-dist/x86' +BUILD_X64_DIR=os.path.join('build-dist', 'x64') +BUILD_X86_DIR=os.path.join('build-dist', 'x86') VERBOSE=True DIST_DIR='dist' FORCE_MK=False @@ -38,8 +38,8 @@ def mk_dir(d): def set_build_dir(path): global BUILD_DIR BUILD_DIR = path - BUILD_X86_DIR = '%s/x86' % path - BUILD_X64_DIR = '%s/x64' % path + BUILD_X86_DIR = os.path.join(path, 'x86') + BUILD_X64_DIR = os.path.join(path, 'x64') mk_dir(BUILD_X86_DIR) mk_dir(BUILD_X64_DIR) @@ -80,12 +80,12 @@ def parse_options(): # Check whether build directory already exists or not def check_build_dir(path): - return os.path.exists(path) and os.path.exists('%s/Makefile' % path) + return os.path.exists(path) and os.path.exists(os.path.join(path, 'Makefile')) # Create a build directory using mk_make.py def mk_build_dir(path, x64): if not check_build_dir(path) or FORCE_MK: - opts = ["python", "scripts/mk_make.py", "-b", path] + opts = ["python", os.path.join('scripts', 'mk_make.py'), "-b", path] if x64: opts.append('-x') if subprocess.call(opts) != 0: @@ -147,7 +147,7 @@ def mk_dist_dir_core(x64): else: platform = "x86" build_path = BUILD_X86_DIR - dist_path = '%s/z3-%s.%s.%s-%s' % (DIST_DIR, major, minor, build, platform) + dist_path = os.path.join(DIST_DIR, 'z3-%s.%s.%s-%s' % (major, minor, build, platform)) mk_dir(dist_path) mk_win_dist(build_path, dist_path) if is_verbose(): @@ -225,7 +225,7 @@ def cp_vs_runtime_core(x64): path = '%sredist\\%s' % (vcdir, platform) VS_RUNTIME_FILES = [] os.path.walk(path, cp_vs_runtime_visitor, '*.dll') - bin_dist_path = '%s/%s/bin' % (DIST_DIR, get_dist_path(x64)) + bin_dist_path = os.path.join(DIST_DIR, get_dist_path(x64), 'bin') for f in VS_RUNTIME_FILES: shutil.copy(f, bin_dist_path) if is_verbose(): @@ -236,8 +236,8 @@ def cp_vs_runtime(): cp_vs_runtime_core(False) def cp_license(): - shutil.copy("LICENSE.txt", "%s/%s" % (DIST_DIR, get_dist_path(True))) - shutil.copy("LICENSE.txt", "%s/%s" % (DIST_DIR, get_dist_path(False))) + shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(True))) + shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(False))) # Entry point def main(): From f02d2ee0e3fd0b071ed6354105fa47012e4153e8 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 07:09:26 -0800 Subject: [PATCH 22/57] fixed missing libz3.lib file in the z3 binary distribution for windows (thanks to GManNickG) Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 381f92def..dc0c71ea2 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -933,10 +933,8 @@ class DLLComponent(Component): mk_dir(os.path.join(dist_path, 'bin')) shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name), '%s.dll' % os.path.join(dist_path, 'bin', self.dll_name)) - if self.static: - mk_dir(os.path.join(dist_path, 'bin')) - shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name), - '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name)) + shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name), + '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name)) class DotNetDLLComponent(Component): def __init__(self, name, dll_name, path, deps, assembly_info_dir): From 512cdc182a4aa9610e5b194f1f6503d488b0c917 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 07:29:04 -0800 Subject: [PATCH 23/57] include Java bindinings in the binary distribution Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 5 +++++ scripts/mk_win_dist.py | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index dc0c71ea2..af19cb91c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1040,6 +1040,11 @@ class JavaDLLComponent(Component): def main_component(self): return is_java_enabled() + def mk_win_dist(self, build_path, dist_path): + if JAVA_ENABLED: + mk_dir(os.path.join(dist_path, 'bin')) + shutil.copy('%s.jar' % os.path.join(build_path, self.package_name), + '%s.jar' % os.path.join(dist_path, 'bin', self.package_name)) class ExampleComponent(Component): def __init__(self, name, path): diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 85360260c..dd50a3977 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -16,6 +16,7 @@ import subprocess import zipfile from mk_exception import * from mk_project import * +import mk_util BUILD_DIR='build-dist' BUILD_X64_DIR=os.path.join('build-dist', 'x64') @@ -23,6 +24,7 @@ BUILD_X86_DIR=os.path.join('build-dist', 'x86') VERBOSE=True DIST_DIR='dist' FORCE_MK=False +JAVA_ENABLED=True def set_verbose(flag): global VERBOSE @@ -52,16 +54,18 @@ def display_help(): 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." exit(0) # Parse configuration option for mk_make script def parse_options(): - global FORCE_MK + global FORCE_MK, JAVA_ENABLED path = BUILD_DIR options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=', 'help', 'silent', - 'force' + 'force', + 'nojava' ]) for opt, arg in options: if opt in ('-b', '--build'): @@ -74,6 +78,8 @@ def parse_options(): display_help() elif opt in ('-f', '--force'): FORCE_MK = True + elif opt == '--nojava': + JAVA_ENABLED = False else: raise MKException("Invalid command line option '%s'" % opt) set_build_dir(path) @@ -86,6 +92,8 @@ def check_build_dir(path): def mk_build_dir(path, x64): if not check_build_dir(path) or FORCE_MK: opts = ["python", os.path.join('scripts', 'mk_make.py'), "-b", path] + if JAVA_ENABLED: + opts.append('--java') if x64: opts.append('-x') if subprocess.call(opts) != 0: @@ -149,6 +157,10 @@ def mk_dist_dir_core(x64): build_path = BUILD_X86_DIR dist_path = os.path.join(DIST_DIR, 'z3-%s.%s.%s-%s' % (major, minor, build, platform)) mk_dir(dist_path) + if JAVA_ENABLED: + # HACK: Propagate JAVA_ENABLED flag to mk_util + # TODO: fix this hack + 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) From 3fa05d81317561fd3136db5d1da6d7aad652c86f Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 08:58:10 -0800 Subject: [PATCH 24/57] Added script for tracking all remote branches Signed-off-by: Leonardo de Moura --- scripts/trackall.sh | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 scripts/trackall.sh diff --git a/scripts/trackall.sh b/scripts/trackall.sh new file mode 100644 index 000000000..d8351af24 --- /dev/null +++ b/scripts/trackall.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Script for "cloning" (and tracking) all branches at codeplex. +# On Windows, this script must be executed in the "git Bash" console. +for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do + git branch --track ${branch##*/} $branch +done +git fetch --all +git pull --all From 6348dab24af2a442b6af60389464f7edd24e6f98 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 09:10:47 -0800 Subject: [PATCH 25/57] removed dead code Signed-off-by: Leonardo de Moura --- src/smt/params/qi_params.h | 5 +- src/smt/smt_internalizer.cpp | 6 - src/smt/smt_setup.cpp | 7 - src/smt/theory_instgen.cpp | 1494 ---------------------------------- src/smt/theory_instgen.h | 45 - 5 files changed, 1 insertion(+), 1556 deletions(-) delete mode 100644 src/smt/theory_instgen.cpp delete mode 100644 src/smt/theory_instgen.h diff --git a/src/smt/params/qi_params.h b/src/smt/params/qi_params.h index b0a21e75b..0cd817f22 100644 --- a/src/smt/params/qi_params.h +++ b/src/smt/params/qi_params.h @@ -52,8 +52,6 @@ struct qi_params { bool m_mbqi_trace; unsigned m_mbqi_force_template; - bool m_instgen; - qi_params(params_ref const & p = params_ref()): /* The "weight 0" performance bug @@ -99,8 +97,7 @@ struct qi_params { m_mbqi_max_cexs_incr(1), m_mbqi_max_iterations(1000), m_mbqi_trace(false), - m_mbqi_force_template(10), - m_instgen(false) { + m_mbqi_force_template(10) { updt_params(p); } diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index b3f16a3ce..42e761b61 100644 --- a/src/smt/smt_internalizer.cpp +++ b/src/smt/smt_internalizer.cpp @@ -23,7 +23,6 @@ Revision History: #include"ast_smt2_pp.h" #include"smt_model_finder.h" #include"for_each_expr.h" -#include"theory_instgen.h" namespace smt { @@ -530,11 +529,6 @@ namespace smt { SASSERT(!b_internalized(q)); SASSERT(q->is_forall()); SASSERT(check_patterns(q)); - if (m_fparams.m_instgen) { - theory* th = m_theories.get_plugin(m_manager.get_family_id("inst_gen")); - static_cast(th)->internalize_quantifier(q); - return; - } bool_var v = mk_bool_var(q); unsigned generation = m_generation; unsigned _generation; diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index ac31eb1a9..f0dc1f5a6 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -28,7 +28,6 @@ Revision History: #include"theory_datatype.h" #include"theory_dummy.h" #include"theory_dl.h" -#include"theory_instgen.h" #include"theory_seq_empty.h" namespace smt { @@ -772,11 +771,6 @@ namespace smt { void setup::setup_seq() { m_context.register_plugin(alloc(theory_seq_empty, m_manager)); } - void setup::setup_instgen() { - if (m_params.m_instgen) { - m_context.register_plugin(mk_theory_instgen(m_manager, m_params)); - } - } void setup::setup_unknown() { setup_arith(); @@ -784,7 +778,6 @@ namespace smt { setup_bv(); setup_datatypes(); setup_dl(); - setup_instgen(); setup_seq(); } diff --git a/src/smt/theory_instgen.cpp b/src/smt/theory_instgen.cpp deleted file mode 100644 index 68e04aab0..000000000 --- a/src/smt/theory_instgen.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - theory_instgen.cpp - -Abstract: - - iProver style theory solver. - It provides an instantiation based engine - based on InstGen methods together with - unit propagation. - -Author: - - Krystof Hoder (t-khoder) - Nikolaj Bjorner (nbjorner) 2011-10-6 - -Revision History: - -Main data-structures: - -- Instantiation = Var -> Expr -- MatchingSet = Instantiation-set - operations: - - has_instance : Instantiation -> Bool - has_instance(i) = exists j in MatchingSet . j <= i -- UnificationIndex - operations: - - insert : Expr - - remove : Expr - - unify : Expr -> Expr-set - - set of inserted expressions that unify -- RootClauseMap : Expr -> Quantifier - where RootClauseMap(clause) = The quantifier that originated clause -- Occurs : Expr -> Quantifier-set - the set of quantifiers where non-ground literal occurs. -- LiteralMeanings : Literal -> Expr-set - - set of non-ground literals that were grounded to Literal -- InternalizedFoLits : Expr-set - - forall e in InternalizedFoLits . e \in LiteralMeanings(ground(e)) -- MatchingSets : Quantifier -> MatchingSet - - -Main operation: - - - insert all assigned literals into UnificationIndex - - for l' in LiteralMeanings(l) do: - for m',theta in UnificationIndex.unify(not l') do: - for q in Occurs(l') do: - for q' in Occurs(m') do: - instantiate q with theta - instantiate q' with theta - - instantiate q with theta: - -Discussion of plans: - -- Efficient unit propagation using the tables from dl_ - See addittional notes under unit propagation. - The idea is to perfrm unit propagation using the tables - provided in the dl_ module. This is similar to unit - propagation from the EPR solver and retains succinctness - features, but does not carry over the splitting component. - The efficient propagator is aimed at solving ground problems more efficiently, - for example - -- Reduce set of selected literals when clause already has on selected literal. - -- Subsumption module: - - simplify clause using already asserted clauses. - - check for variants. - -- Completeness for EPR with equality: - The relevant equality clause for EPR are C \/ x = y and C \/ a = x - Destructive E-resolution (DER) removes disequalities. - Two approaches: - 1. Rely on super-position/hyper-resolution of ordinary literals - in the clause. - 2. Instantiate based on congruence closure. - The instantiation based approach takes a clause of the form C \/ x = y, - where all other non-equality literals in C are assigned false by the - current assignment, and (the grounded version U = U' of) x = y is - assigned true. Take the equivalence classes of the type of x and - instantiate x, y using representatives for different equivalence - classes. The number of instantiations is potentially quadratic - in the number of terms. One reduction considers symmetries: - instantiate x by a smaller representative than y. -- Unit propagation: - - Why should unit-propagation matter: hunch: similar role as - theory propagation where conflicts are created close to root - of search tree. - - Add theory identifiers to literals so that assign_eh is invoked. - - Produce explanation objects for unit propagation. - - Unit propagation index. - - Idea only propagate known literals -- Exchange unit literals with super position engine for equalities. - iProver approach: perform unit super-position proof, get instances - by labeling equalities by clauses + substitution (set-labeling) - portfolio approach: exchange unit literals to super-position - (or hypotheses as suggested in more general setting). - ---*/ - -#include "theory_instgen.h" -#include "value_factory.h" -#include "smt_model_generator.h" -#include "smt_context.h" -#include "ast_smt2_pp.h" -#include "substitution.h" -#include "substitution_tree.h" -#include "uint_set.h" -#include "unifier.h" -#include "matcher.h" -#include "rewriter.h" -#include "rewriter_def.h" -#include "var_subst.h" - -#define PP mk_pp - -namespace smt { - - - // - // expression grounding for passing to the SMT solver - // - class grounder { - ast_manager& m; - vector > m_defaults; - expr_ref_vector m_ref_holder; - - class grounding_rewriter_cfg; - - void reserve(unsigned idx) { - if (m_defaults.size() <= idx) { - m_defaults.resize(idx+1); - } - } - - expr* mk_default(sort* s) { - return mk_default(0, s); - } - - expr* mk_default(unsigned i, sort* s) { - expr* d; - reserve(i); - if (!m_defaults[i].find(s, d)) { - d = m.mk_fresh_const("U",s); - m_defaults[i].insert(s, d); - m_ref_holder.push_back(d); - } - return d; - } - - class grounding_rewriter_cfg : public default_rewriter_cfg { - grounder& m_parent; - bool m_collapse; - public: - grounding_rewriter_cfg(grounder& parent, bool collapse) - : m_parent(parent), m_collapse(collapse) {} - - bool get_subst(expr * s, expr * & t, proof * & t_pr) { - SASSERT(is_app(s) || is_var(s)); - if (is_var(s)) { - var* v = to_var(s); - if (m_collapse) { - t = m_parent.mk_default(v->get_sort()); - } - else { - t = m_parent.mk_default(v->get_idx(), v->get_sort()); - } - } - return is_var(s); - } - }; - - void mk(expr * e, app_ref& res, bool collapse) { - if(is_ground(e)) { - res = to_app(e); - } - else { - while (is_quantifier(e)) { - e = to_quantifier(e)->get_expr(); - } - SASSERT(is_app(e)); - grounding_rewriter_cfg r_cfg(*this, collapse); - rewriter_tpl rwr(m, false, r_cfg); - expr_ref res_e(m); - rwr(e, res_e); - res = to_app(res_e); - } - SASSERT(is_ground(res.get())); - } - - public: - grounder(ast_manager& m): m(m), m_ref_holder(m) { - reserve(0); - } - - /** - create a grounding that recycles the same constant for - different variables of the same sort. - - This function can be called either with whole clauses (incl. quantifier), - or with literals one by one (without a quantifier) - */ - void operator()(expr * e, app_ref& res) { - mk(e, res, true); - } - - // - // create a grounding where different variables have different names - // - void mk_diff(expr * e, app_ref& res) { - mk(e, res, false); - } - }; - - // - // Class for first-order subsumption checking. - // if clause[renaming] is a superset of existing clause in context, then clause is subsumed. - // if context => clause then clause is subsumed. - // if context & clause => ~ lit then lit is subsumed from clause - // - // TBD: - // - check unit propagation - // - use internalizer functions directly. The assertions have already been pre-processed. - // - class clause_subsumption { - ast_manager& m; - grounder m_grounder; - smt_params m_params; - context m_ctx; - quantifier_ref_vector m_assumptions; - unsigned_vector m_limit; - public: - clause_subsumption(ast_manager& m, smt_params& p): - m(m), m_grounder(m), m_params(p), m_ctx(m,m_params), m_assumptions(m) { - m_params.m_instgen = false; - } - - void simplify(quantifier* new_clause, expr_ref& result, ptr_vector& assumptions) { -#if 1 - result = new_clause; - return; -#endif - - SASSERT(new_clause->is_forall()); - expr* body = new_clause->get_expr(); - app_ref ground_clause(m); - m_grounder.mk_diff(new_clause, ground_clause); - if (is_subsumed(ground_clause)) { - TRACE("theory_instgen", tout << "subsumed: " << PP(new_clause,m) << "\n";); - result = m.mk_true(); - return; - } - if (is_homomorphic_image(body)) { - result = m.mk_true(); - return; - } - // Assert the current clause. - m_ctx.internalize(ground_clause, true); - m_ctx.assign(m_ctx.get_literal(ground_clause), b_justification()); - TRACE("theory_instgen", tout << "Asserting: " << PP(ground_clause,m) << "\n";); - m_assumptions.push_back(new_clause); - SASSERT(m.is_or(body) == m.is_or(ground_clause)); - if (!m.is_or(body)) { - result = new_clause; - return; - } - SASSERT(to_app(body)->get_num_args() == ground_clause->get_num_args()); - ptr_vector lits; - for (unsigned i = 0; i < to_app(body)->get_num_args(); ++i) { - m_ctx.push(); - m_ctx.assign(m_ctx.get_literal(ground_clause->get_arg(i)), b_justification()); - lbool is_sat = m_ctx.check(); - m_ctx.pop(1); - if (is_sat != l_false) { - lits.push_back(to_app(body)->get_arg(i)); - } - else { - TRACE("theory_instgen", tout << "subsumed literal: " << PP(to_app(body)->get_arg(i),m) << "\n";); - } - } - if (lits.size() == ground_clause->get_num_args()) { - result = new_clause; - } - else { - SASSERT(!lits.empty()); - result = lits.size()==1?lits[0]:m.mk_or(lits.size(), lits.c_ptr()); - result = m.update_quantifier(new_clause, result); - TRACE("theory_instgen", tout << "simplified: " << PP(new_clause,m) << "\n"; - tout << PP(result.get(), m) << "\n"; - ); - //overapproximation of required assumptions - //( m_assumptions.size()-1 ... the -1 is not to make ourselves as an assumption) - assumptions.append(m_assumptions.size()-1, m_assumptions.c_ptr()); - } - } - - void push() { - m_ctx.push(); - m_limit.push_back(m_assumptions.size()); - } - - void pop(unsigned num_scopes) { - m_ctx.pop(num_scopes); - - unsigned last_idx = m_limit.size()-num_scopes; - unsigned restored_assumptions_size = m_limit[last_idx]; - m_limit.resize(last_idx); - m_assumptions.resize(restored_assumptions_size); - } - - private: - - bool is_subsumed(expr* ground_clause) { - m_ctx.push(); - m_ctx.internalize(ground_clause, true); - m_ctx.assign(~m_ctx.get_literal(ground_clause), b_justification()); - lbool is_sat = m_ctx.check(); - m_ctx.pop(1); - TRACE("theory_instgen", - tout << PP(ground_clause, m) << " " << - ((is_sat==l_false)?"unsat":"sat") << "\n";); - return (is_sat == l_false); - } - - bool is_homomorphic_image(expr* body) { - // TBD - return false; - } - - }; - - class fo_clause_internalizer; - class instantiator; - class theory_instgen_impl; - typedef expr_ref_vector inst; - - class instantiation_result { - quantifier_ref m_clause; - inst m_subst; - public: - instantiation_result(ast_manager& m) : m_clause(m), m_subst(m) {} - - void init(quantifier * q, const inst& subst) { - SASSERT(!m_clause); //we init each object at most once - SASSERT(m_subst.empty()); - SASSERT(q); - m_clause = q; - m_subst.append(subst); - } - quantifier * clause() const { return m_clause; } - const inst& subst() const { return m_subst; } - }; - - typedef vector instantiation_result_vector; - - // TBD: replace this by the substitution tree index. - // It should do the trick of identifying instances and generalizers. - // see matching_set2.. - // - class matching_set { - ast_manager& m; - vector m_inst; - - //used in the has_instance function - mutable substitution m_subst; - - public: - matching_set(ast_manager& m) : m(m), m_subst(m) {} - unsigned size() const { return m_inst.size(); } - inst const& operator[](unsigned i) const { return m_inst[i]; } - - void insert(inst const& inst) { - SASSERT(m_inst.empty() || m_inst.back().size() == inst.size()); - TRACE("theory_instgen_verbose", - for (unsigned i = 0; i < inst.size(); ++i) { - tout << PP(inst[i], m) << " "; - } - tout << "\n"; - ); - m_inst.push_back(inst); - } - void insert(unsigned sz, expr* const* exprs) { - insert(inst(m, sz, exprs)); - } - void pop_insert() { m_inst.pop_back(); } - - bool has_instance(inst const& inst) { - unsigned dont_care; - return has_instance(inst, dont_care); - } - - bool has_instance(inst const& new_inst, unsigned& index) { - for (unsigned i = 0; i < size(); ++i) { - if (has_instance(new_inst, m_inst[i])) { - index = i; - return true; - } - } - return false; - } - - class insert_inst : public trail { - matching_set& m_ms; - public: - insert_inst(matching_set& m): m_ms(m) {} - virtual void undo(smt::context& ctx) { m_ms.pop_insert(); } - }; - - static bool is_identity(const inst& subst) { - uint_set vars; - vars.reset(); - unsigned sz = subst.size(); - for(unsigned i=0; iget_idx(); - if(vars.contains(var_idx)) { - return false; - } - vars.insert(var_idx); - } - return true; - } - - private: - // check if old_instance is an instance of new_instance. - bool has_instance(inst const& new_instance, inst const& old_instance) const { - SASSERT(new_instance.size() == old_instance.size()); - unsigned sz = new_instance.size(); - m_subst.reset(); - m_subst.reserve_vars(sz); - m_subst.reserve_offsets(2); - matcher mtchr(m); - for(unsigned i = 0; i < sz; i++) { - TRACE("theory_instgen_verbose", tout << PP(new_instance[i], m) << " " << PP(old_instance[i], m) << "\n";); - if(!mtchr(new_instance[i], old_instance[i], m_subst)) { - return false; - } - } - return true; - } - }; - - - class matching_set2 { - class inst_visitor : public st_visitor { - bool m_found; - public: - inst_visitor(substitution& s): st_visitor(s), m_found(false) {} - virtual bool operator()(expr * e) { - m_found = true; - return false; - } - void reset() { m_found = false; } - bool found() const { return m_found; } - }; - - ast_manager& m; - substitution_tree m_st; - func_decl_ref m_f; - app_ref_vector m_trail; - substitution m_dummy; - inst_visitor m_visitor; - - public: - matching_set2(ast_manager& m) : m(m), m_st(m), m_f(m), m_trail(m), m_dummy(m), m_visitor(m_dummy) {} - - void insert(inst const& inst) { - if (!m_f.get()) { - ptr_buffer domain; - for (unsigned i = 0; i < inst.size(); ++i) { - domain.push_back(m.get_sort(inst[i])); - } - m_f = m.mk_func_decl(symbol("tuple"),inst.size(), domain.c_ptr(), m.mk_bool_sort()); - m_trail.push_back(m.mk_app(m_f, inst.size(), inst.c_ptr())); - m_st.insert(m_trail.back()); - } - } - void insert(unsigned sz, expr* const* exprs) { - insert(inst(m, sz, exprs)); - } - void pop_insert() { - m_st.erase(m_trail.back()); - m_trail.pop_back(); - } - - bool has_instance(inst const& inst) { - app_ref f(m); - f = m.mk_app(m_f, inst.size(), inst.c_ptr()); - m_visitor.reset(); - m_st.inst(f, m_visitor); - return m_visitor.found(); - } - - class insert_inst : public trail { - matching_set& m_ms; - public: - insert_inst(matching_set& m): m_ms(m) {} - virtual void undo(smt::context& ctx) { m_ms.pop_insert(); } - }; - - static bool is_identity(const inst& subst) { - uint_set vars; - vars.reset(); - unsigned sz = subst.size(); - for(unsigned i=0; iget_idx(); - if(vars.contains(var_idx)) { - return false; - } - vars.insert(var_idx); - } - return true; - } - }; - - - ///////////////////////// - // inst_gen_unif_index - // - - class inst_gen_unif_index { - ast_manager & m; - substitution_tree m_st; - unsigned m_num_vars; - app_ref_vector m_ref_holder; - unsigned_vector m_lim; - - class collecting_visitor : public st_visitor { - app_ref_vector& m_acc; - public: - collecting_visitor(app_ref_vector& acc, substitution& subst) - : st_visitor(subst), m_acc(acc) {} - virtual bool operator()(expr * e) { - SASSERT(is_app(e)); - m_acc.push_back(to_app(e)); - return true; - } - }; - - - class st_contains_visitor : public st_visitor { - expr* m_e; - bool m_found; - public: - st_contains_visitor(substitution& s, expr* e): st_visitor(s), m_e(e), m_found(false) {} - virtual bool operator()(expr* e) { - if (e == m_e) { - m_found = true; - return false; - } - return true; - } - bool found() const { return m_found; } - }; - - void debug_st(char const* cmd, app* l) { - expr_ref e(m); - ptr_vector sorts; - svector names; - get_free_vars(l, sorts); - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - sorts[i] = m.mk_bool_sort(); - } - names.push_back(symbol(i)); - } - sorts.reverse(); - if (!sorts.empty()) { - e = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), l); - } - else { - e = l; - } - std::cout << ":" << cmd << " " << PP(e.get(),m) << "\n"; - } - - public: - inst_gen_unif_index(ast_manager & m) : - m(m), m_st(m), m_num_vars(0), m_ref_holder(m) {} - - void insert_literal(app * lit) { - // debug_st("st_insert", lit); - m_ref_holder.push_back(lit); - m_st.insert(lit); - } - - void get_unifications(app * lit, app_ref_vector& res) { - substitution subst(m); - subst.reserve_vars(m_num_vars); - subst.reserve_offsets(m_st.get_approx_num_regs()); - collecting_visitor visitor(res, subst); - // TRACE("theory_instgen", m_st.display(tout); ); - m_st.unify(lit, visitor); - } - void reserve_num_vars(unsigned num_vars) { - if (num_vars > m_num_vars) m_num_vars = num_vars; - } - - void push() { - m_lim.push_back(m_ref_holder.size()); - } - - void pop() { - unsigned sz = m_lim.back(); - m_ref_holder.resize(sz); - m_lim.pop_back(); - m_st.reset(); - } - - void pop_orig() { - unsigned sz = m_lim.back(); - while (m_ref_holder.size() > sz) { - debug_st("st_erase", m_ref_holder.back()); - m_st.erase(m_ref_holder.back()); - - substitution subst(m); - subst.reserve_vars(m_num_vars); - subst.reserve_offsets(m_st.get_approx_num_regs()); - st_contains_visitor cv(subst, m_ref_holder.back()); - m_st.unify(m_ref_holder.back(), cv); - if (cv.found()) { - m_st.display(std::cout); - m_st.erase(m_ref_holder.back()); - } - SASSERT(!cv.found()); - m_ref_holder.pop_back(); - } - m_lim.pop_back(); - } - - void display(std::ostream& out) { - m_st.display(out); - } - - bool empty() const{ - return m_st.empty(); - } - }; - - - /////////////////////////// - // fo_clause_internalizer - // - - class fo_clause_internalizer { - private: - typedef map, default_eq > literal_meaning_map; - typedef obj_map occurs; - typedef obj_map root_clause_map; //for any clause instance it gives us the clause from the original problem - - theory_instgen_impl& m_parent; - expr_ref_vector m_vars; - var_subst m_subst; - occurs m_occurs; - grounder m_grounder; - /** - For each clause which is a result of instantiation contains the - original problem clause from which it derives. - */ - root_clause_map m_root_clause_map; - - - /** - For each SMT literal contains a vector of first-order literals - that are represented by this literal. - */ - literal_meaning_map m_literal_meanings; - - /** - fo literals that have been internalized by this object. - Invariant: any app* fol in this set has a literal l such that - m_literal_meanings[l].contains(fol). - Particularly, l==get_context().get_literal(gnd_fol) where gnd_fol - is a grounded version of this literal - */ - obj_hashtable m_internalized_fo_lits; - - - ast_manager& m() const; - smt::context& get_context() const; - - class insert_occurs_trail : public trail { - occurs& m_occ; - quantifier_ref_vector* m_qs; - expr_ref m_lit; - public: - insert_occurs_trail(occurs& o, expr_ref& lit, quantifier* q): m_occ(o), m_qs(0), m_lit(lit) { - occurs::obj_map_entry* e = m_occ.insert_if_not_there2(lit,0); - m_qs = e->get_data().m_value; - if (!m_qs) { - m_qs = alloc(quantifier_ref_vector, lit.get_manager()); - e->get_data().m_value = m_qs; - } - m_qs->push_back(q); - } - - virtual void undo(smt::context& ctx) { - SASSERT(m_qs && !m_qs->empty()); - SASSERT(m_qs == m_occ.find_core(m_lit)->get_data().m_value); - m_qs->pop_back(); - if (m_qs->empty()) { - m_occ.remove(m_lit); - dealloc(m_qs); - } - } - }; - - class lit_meaning_trail : public trail { - literal_meaning_map& m_map; - app_ref_vector* m_apps; - smt::literal m_smtlit; - public: - - lit_meaning_trail(literal_meaning_map& map, ast_manager& m, smt::literal l, app* lit): - m_map(map), m_smtlit(l) { - literal_meaning_map::entry* e = map.insert_if_not_there2(l, 0); - m_apps = e->get_data().m_value; - if (!m_apps) { - m_apps = alloc(app_ref_vector, m); - e->get_data().m_value = m_apps; - } - m_apps->push_back(lit); - } - - virtual void undo(smt::context& ctx) { - SASSERT(m_apps && !m_apps->empty()); - SASSERT(m_apps == m_map.find_core(m_smtlit)->get_data().m_value); - m_apps->pop_back(); - if (m_apps->empty()) { - m_map.remove(m_smtlit); - dealloc(m_apps); - } - } - }; - - quantifier * get_root_clause(expr* clause) const { - quantifier * root; - if(!m_root_clause_map.find(clause, root)) { - SASSERT(is_forall(clause)); - root = to_quantifier(clause); - } - return root; - } - - void replace_by_root_clauses(ptr_vector& vect) const { - unsigned sz = vect.size(); - for(unsigned i=0; i(t)); - get_context().push_trail(insert_obj_trail(m_internalized_fo_lits, lit)); - get_context().push_trail(lit_meaning_trail(m_literal_meanings, m(), smt_lit, lit)); - TRACE("theory_instgen", tout << smt_lit << " "<< PP(grounded_lit, m()) << " |-> " << PP(lit, m()) << "\n";); - } - get_context().mark_as_relevant(smt_lit); - return smt_lit; - } - - void add_clause_to_smt(expr * clause, quantifier* root_clause, ptr_vector const& assumptions=ptr_vector()); - - void get_instance_clause(instantiation_result const& ir, expr_ref& res); - - /** - return false if nothing was done - - assumptions are instantiated clauses (to get a correct assumption for the SMT solver, we need - to convert the vector to root clauses). - */ - bool simplify_clause(quantifier * clause, expr_ref& result, ptr_vector& assumptions); - - public: - - fo_clause_internalizer(theory_instgen_impl& parent): - m_parent(parent), - m_vars(m()), - m_subst(m()), - m_grounder(m()) { - } - - ~fo_clause_internalizer() { - reset_dealloc_values(m_occurs); - } - - void get_literal_meanings(literal l, ptr_vector& fo_lits) { - app_ref_vector* lits = 0; - m_literal_meanings.find(l, lits); - if (lits) { - fo_lits.append(lits->size(), lits->c_ptr()); - } - } - - void add_initial_clause(quantifier* q) { - add_clause_to_smt(q, 0); - } - - quantifier_ref_vector* find_occurs(app * l) { - quantifier_ref_vector* result = 0; - m_occurs.find(l, result); - return result; - } - - void add_new_instance(instantiation_result const& ir) { - quantifier * root_clause = get_root_clause(ir.clause()); - expr_ref inst_clause(m()); - get_instance_clause(ir, inst_clause); - - ptr_vector assumptions; - if(is_quantifier(inst_clause.get())) { - quantifier * q_clause = to_quantifier(inst_clause.get()); - bool simplified = simplify_clause(q_clause, inst_clause, assumptions); - SASSERT(simplified || assumptions.empty()); - } - replace_by_root_clauses(assumptions); - - if(!m_root_clause_map.contains(inst_clause)) { - m_root_clause_map.insert(inst_clause, root_clause); - get_context().push_trail(insert_obj_map(m_root_clause_map, inst_clause)); - } - add_clause_to_smt(inst_clause, root_clause, assumptions); - } - }; - - - ///////////////// - // instantiator - // - - class instantiator { - private: - typedef quantifier clause_type; - typedef ptr_vector clause_vector; - typedef obj_map matching_sets; - - ast_manager& m; - theory_instgen_impl& m_parent; - fo_clause_internalizer& m_internalizer; - inst_gen_unif_index m_unif_index; - matching_sets m_matching; - unifier m_unifier; //used in the unify method, but we don't want to recreate over and over - - class var_rename_rewriter_cfg : public default_rewriter_cfg { - ast_manager& m; - u_map m_index_rename; - public: - var_rename_rewriter_cfg(ast_manager& m) : m(m) {} - - bool get_subst(expr * s, expr * & t, proof * & t_pr) { - if (is_var(s)) { - unsigned idx = to_var(s)->get_idx(); - unsigned new_idx = 0; - if (!m_index_rename.find(idx, new_idx)) { - new_idx = m_index_rename.size(); - m_index_rename.insert(idx, new_idx); - } - t = m.mk_var(new_idx, to_var(s)->get_sort()); - return true; - } - else { - return false; - } - } - }; - - static void extract_substitution(substitution& s, quantifier * q, unsigned subst_var_cnt, bool is_first_bank, expr_ref_vector& tgt) { - // unsigned var_increment = is_first_bank ? 0 : subst_var_cnt; - unsigned var_offset = is_first_bank ? 0 : 1; - - unsigned deltas[2] = {0, subst_var_cnt}; - ast_manager& m = s.get_manager(); - unsigned var_cnt = q->get_num_decls(); - var_rename_rewriter_cfg r_cfg(m); - rewriter_tpl rwr(m, false, r_cfg); - for(unsigned i=0; iget_decl_sort(i); - unsigned var_idx = var_cnt-1-i; - var_ref v(m.mk_var(var_idx, var_sort), m); - expr_ref tmp(m), subst_result(m); - s.apply(2, deltas, expr_offset(v.get(), var_offset), tmp); - rwr(tmp, subst_result); - tgt.push_back(subst_result); - } - } - - - // just to be sure there's not misunderstanding with the caller, we require the res to be empty:) - void get_literal_occurrences(app * lit, clause_vector& res) { - SASSERT(res.empty()); - quantifier_ref_vector * occurrences = m_internalizer.find_occurs(lit); - if(occurrences) { - res.append(occurrences->size(), occurrences->c_ptr()); - } - } - - /** - check substitution wrt dismatching constraints of clause - (variable offset is to deal with how variable banks are shifted on each - other in the substitution) - */ - bool is_allowed_instantiation(clause_type * clause, const inst& subst) { - matching_set * ms; - return !m_matching.find(clause, ms) || !ms->has_instance(subst); - } - - class new_ms : public trail { - matching_sets& m_ms; - matching_set* m_s; - quantifier* m_q; - public: - new_ms(matching_sets& m, matching_set* s, quantifier* q): m_ms(m), m_s(s), m_q(q) {} - virtual void undo(smt::context& ctx) { dealloc(m_s); m_ms.remove(m_q); } - }; - - // add instantiating substitution among the dismatching constraints - void record_instantiation(instantiation_result const& inst) { - quantifier * cl = inst.clause(); - matching_set * ms; - if(!m_matching.find(cl, ms)) { - ms = alloc(matching_set, m); - m_matching.insert(cl, ms); - get_context().push_trail(new_ms(m_matching, ms, cl)); - } - ms->insert(inst.subst()); - get_context().push_trail(matching_set::insert_inst(*ms)); - } - - void get_result_from_subst(clause_type * clause, const inst& subst, instantiation_result& res) { - res.init(clause, subst); - record_instantiation(res); - } - - void display_vector(expr_ref_vector const& v, std::ostream& out) { - for (unsigned i = 0; i < v.size(); ++i) { - out << PP(v[i], m) << " "; - } - out << "\n"; - } - - - void add_lit(literal lit) { - ptr_vector fo_lits; - m_internalizer.get_literal_meanings(lit, fo_lits); - expr_ref e(m); - get_context().literal2expr(lit, e); - if (is_ground(e.get())) { - fo_lits.push_back(to_app(e)); - } - for (unsigned i = 0; i < fo_lits.size(); ++i) { - app * fol = fo_lits[i]; - m_unif_index.insert_literal(fol); - } - } - - void mk_folit_neg(app * lit, app_ref& res) { - expr * arg; - if(m.is_not(lit, arg)) { - SASSERT(is_app(arg)); - res = to_app(arg); - } - else { - res = m.mk_not(lit); - } - } - - ast_manager& get_manager() const; - context& get_context() const; - - public: - instantiator(fo_clause_internalizer& internalizer, theory_instgen_impl& parent, ast_manager& m) : - m(m), - m_parent(parent), - m_internalizer(internalizer), - m_unif_index(m), - m_unifier(m) {} - - ~instantiator() { - reset_dealloc_values(m_matching); - } - - bool unif_is_empty() const { - return m_unif_index.empty(); - } - - void display(std::ostream& out) { - m_unif_index.display(out); - } - - void add_true_lit(literal lit) { - add_lit(lit); - } - - void push() { - m_unif_index.push(); - } - - void pop() { - m_unif_index.pop(); - } - - void reserve_num_vars(unsigned num_vars) { - m_unif_index.reserve_num_vars(num_vars); - } - - bool instantiate_clauses( - app * lit1, clause_type * clause1, - app * lit2, clause_type * clause2, - instantiation_result_vector& result); - - bool instantiate_clause( - app * lit1, clause_type * clause1, app * lit2, - instantiation_result_vector& result); - - void do_instantiating(literal lit, instantiation_result_vector& res) { - ptr_vector folits; - clause_vector folit_clauses; // clauses in which the first-order literal appears - app_ref_vector unifs(m); // unifying complementary literals - clause_vector comp_clauses; // clauses in which the unifying complementary literal appears - - m_internalizer.get_literal_meanings(lit, folits); - - while(!folits.empty()) { - app * folit = folits.back(); - - folits.pop_back(); - folit_clauses.reset(); - get_literal_occurrences(folit, folit_clauses); - SASSERT(!folit_clauses.empty()); //if we have a literal it should be in some clause (or not?) - - SASSERT(folit->get_ref_count() > 0); - app_ref complementary(m); - mk_folit_neg(folit, complementary); - m_unif_index.get_unifications(complementary, unifs); - - while(!unifs.empty()) { - app * comp_lit = unifs.back(); - unifs.pop_back(); - SASSERT(comp_lit->get_ref_count() > 0); - comp_clauses.reset(); - get_literal_occurrences(comp_lit, comp_clauses); - TRACE("theory_instgen", tout << "Literal " << lit << " meaning: " << PP(folit, m) << "\n"; - tout << "Unifies with: " << PP(comp_lit, m) << "\n";); - // - //if a literal is in the unification index (i.e. was assigned true sometime before), - //it should be in some clause or it is a ground literal. - - //iterate through all clauses that contain the query literal - // - clause_vector::const_iterator fc_end = folit_clauses.end(); - for(clause_vector::const_iterator fc_it = folit_clauses.begin(); fc_it!=fc_end; ++fc_it) { - - //iterate through all clauses that contain the complementary unifying literal - clause_vector::const_iterator end = comp_clauses.end(); - for(clause_vector::const_iterator it = comp_clauses.begin(); it!=end; ++it) { - - instantiate_clauses(folit, *fc_it, comp_lit, *it, res); - } - if (comp_clauses.empty()) { - instantiate_clause(folit, *fc_it, comp_lit, res); - } - } - } - complementary.reset(); - } - } - }; - - - /////////////////////////// - // theory_instgen_impl - // - - class theory_instgen_impl : public theory_instgen { - - friend class instantiator; - friend class fo_clause_internalizer; - - struct stats { - unsigned m_num_axioms; - unsigned m_num_subsumptions; - unsigned m_num_pruned; - stats() { memset(this, 0, sizeof(*this)); } - }; - - ast_manager& m_manager; - smt_params& m_params; - fo_clause_internalizer m_internalizer; - instantiator m_instantiator; - clause_subsumption m_subsumer; - stats m_stats; - - final_check_status instantiate_all_possible() { - // traverse instantiation queue and create initial instances. - - ast_manager& m = get_manager(); - context& ctx = get_context(); - instantiation_result_vector generated_clauses; - unsigned bv_cnt = ctx.get_num_bool_vars(); - - m_instantiator.push(); - - TRACE("theory_instgen", - tout << "Literals:\n"; - for (unsigned v = 0; v < bv_cnt; ++v) { - if (l_undef == ctx.get_assignment(v)) continue; - literal lit(v, ctx.get_assignment(v) == l_false); - expr_ref e(m); - ctx.literal2expr(lit, e); - tout << PP(e.get(),m) << "\n"; - } - ); - - SASSERT(m_instantiator.unif_is_empty()); - - for(unsigned bvi=0; bvi < bv_cnt; ++bvi) { - lbool asgn_val = ctx.get_assignment(bvi); - if(asgn_val==l_undef) { - continue; - } - literal lit(bvi, asgn_val==l_false); - m_instantiator.add_true_lit(lit); - m_instantiator.do_instantiating(lit, generated_clauses); - } - - bool change = !generated_clauses.empty(); - - while(!generated_clauses.empty()) { - m_internalizer.add_new_instance(generated_clauses.back()); - generated_clauses.pop_back(); - } - - m_instantiator.pop(); - - return change?FC_CONTINUE:FC_DONE; - } - - - public: - theory_instgen_impl(ast_manager& m, smt_params& p): - theory_instgen(m.get_family_id("inst_gen")), - m_manager(m), - m_params(p), - m_internalizer(*this), - m_instantiator(m_internalizer, *this, m), - m_subsumer(m, p) - {} - - ast_manager& m() { return m_manager; } - - virtual void internalize_quantifier(quantifier* q) { - TRACE("theory_instgen", tout << PP(q, m()) << "\n";); - context& ctx = get_context(); - if (!ctx.b_internalized(q)) { - bool_var v = ctx.mk_bool_var(q); - ctx.set_var_theory(v, get_id()); - m_instantiator.reserve_num_vars(q->get_num_decls()); - } - } - - virtual bool internalize_atom(app * atom, bool gate_ctx) { - UNREACHABLE(); - return false; - } - - virtual bool internalize_term(app * term) { - UNREACHABLE(); - return false; - } - - virtual void new_eq_eh(theory_var v1, theory_var v2) {} - - virtual void new_diseq_eh(theory_var v1, theory_var v2) {} - - virtual theory * mk_fresh(context * new_ctx) { - return alloc(theory_instgen_impl, get_manager(), m_params); - } - - virtual void assign_eh(bool_var v, bool is_true) { - context& ctx = get_context(); - expr* e = ctx.bool_var2expr(v); - if (is_quantifier(e)) { - if (is_true) { - m_internalizer.add_initial_clause(to_quantifier(e)); - } - else { - // TBD: handle existential force later. - } - } - } - - virtual final_check_status final_check_eh() { - TRACE("theory_instgen", tout << "Final check\n";); - return instantiate_all_possible(); - } - - virtual void init_model(smt::model_generator & m) { } - - virtual smt::model_value_proc * mk_value(smt::enode * n, smt::model_generator & m) { - UNREACHABLE(); - return 0; - } - - virtual void relevant_eh(app * n) { } - - virtual void push_scope_eh() { - m_subsumer.push(); - } - - virtual void pop_scope_eh(unsigned num_scopes) { - m_subsumer.pop(num_scopes); - } - - virtual void collect_statistics(::statistics & st) const { - st.update("inst axiom", m_stats.m_num_axioms); - st.update("inst subsump", m_stats.m_num_subsumptions); - } - - void inc_subsumptions() { - ++m_stats.m_num_subsumptions; - } - - void inc_axioms() { - ++m_stats.m_num_axioms; - } - - void inc_pruned() { - ++m_stats.m_num_pruned; - } - - }; - - theory_instgen* mk_theory_instgen(ast_manager& m, smt_params& p) { - return alloc(theory_instgen_impl, m, p); - } - - ast_manager& instantiator::get_manager() const { - return m_parent.m(); - } - - smt::context& instantiator::get_context() const { - return m_parent.get_context(); - } - - bool instantiator::instantiate_clauses( - app * lit1, clause_type * clause1, - app * lit2, clause_type * clause2, - instantiation_result_vector& result) { - TRACE("theory_instgen", tout << PP(lit1, m) << " " << PP(clause1, m) << "\n"; - tout << PP(lit2, m) << " " << PP(clause2, m) << "\n";); - substitution subst(m); - unsigned var_cnt = std::max(clause1->get_num_decls(), clause2->get_num_decls()); - subst.reserve(2, var_cnt); - //don't trust there offset values too much, it's just what i expect the substitution does:) - app_ref complementary(m); - mk_folit_neg(lit1, complementary); - TRUSTME(m_unifier(complementary, lit2, subst)); - - inst subst1(m); - extract_substitution(subst, clause1, var_cnt, true, subst1); - inst subst2(m); - extract_substitution(subst, clause2, var_cnt, false, subst2); - - bool s1_identity = matching_set::is_identity(subst1); - bool s2_identity = matching_set::is_identity(subst2); - - if((!s1_identity && !is_allowed_instantiation(clause1, subst1)) || - (!s2_identity && !is_allowed_instantiation(clause2, subst2))) { - TRACE("theory_instgen", - tout << "Pruned instantiation\n"; - tout << PP(clause1, m) << "\n"; - display_vector(subst1, tout); - tout << PP(clause2, m) << "\n"; - display_vector(subst2, tout); - ); - m_parent.inc_pruned(); - return false; - } - - // - // both substitutions cannot be identity as then the two complementary - // literals would correspond to the same SAT solver variable - // - SASSERT(!s1_identity || !s2_identity); - - if(!s1_identity) { - instantiation_result res1(m); - get_result_from_subst(clause1, subst1, res1); - result.push_back(res1); - } - - if(!s2_identity) { - instantiation_result res2(m); - get_result_from_subst(clause2, subst2, res2); - result.push_back(res2); - } - return true; - } - - // literal lit2 is ground. It is not associated with a clause. - // literal lit1 is associatd with a non-ground clause. - bool instantiator::instantiate_clause( - app * lit1, clause_type * clause1, app * lit2, - instantiation_result_vector& result) { - TRACE("theory_instgen", tout << PP(lit1, m) << " " << PP(clause1, m) << "\n"; - tout << PP(lit2, m) << "\n";); - if (!is_ground(lit2)) { - // TBD: remove. Debug code. - std::cout << PP(lit1, m) << " " << PP(clause1, m) << "\n"; - std::cout << PP(lit2, m) << "\n"; - m_unif_index.display(std::cout); - } - SASSERT(is_ground(lit2)); - substitution subst(m); - unsigned var_cnt = clause1->get_num_decls(); - subst.reserve(2, var_cnt); - app_ref complementary(m); - mk_folit_neg(lit1, complementary); - - TRUSTME(m_unifier(complementary, lit2, subst)); - - inst subst1(m); - extract_substitution(subst, clause1, var_cnt, true, subst1); - - if(matching_set::is_identity(subst1) || - !is_allowed_instantiation(clause1, subst1)) { - TRACE("theory_instgen", - tout << "Pruned instantiation\n"; - tout << PP(clause1, m) << "\n"; - display_vector(subst1, tout); - ); - m_parent.inc_pruned(); - return false; - } - - instantiation_result res1(m); - get_result_from_subst(clause1, subst1, res1); - result.push_back(res1); - return true; - } - - - //-------------------------- - // - // fo_clause_internalizer - // - //-------------------------- - - smt::context& fo_clause_internalizer::get_context() const { - return m_parent.get_context(); - } - - ast_manager& fo_clause_internalizer::m() const { - return m_parent.m(); - } - - bool fo_clause_internalizer::simplify_clause(quantifier * clause, expr_ref& result, ptr_vector& assumptions) { - m_parent.m_subsumer.simplify(clause, result, assumptions); - bool change = clause!=result.get(); - if (change) { - m_parent.inc_subsumptions(); - } - return change; - } - - void fo_clause_internalizer::get_instance_clause(instantiation_result const& ir, expr_ref& res) { - expr * orig_cl = ir.clause()->get_expr(); - SASSERT(is_app(orig_cl)); - - expr_ref res_inner(m()); //the clause after substitution, we might still need to quantify it - m_subst(orig_cl, ir.subst().size(), ir.subst().c_ptr(), res_inner); - SASSERT(is_app(res_inner.get())); - - if(is_ground(res_inner.get())) { - res = res_inner; - return; //we made it ground! - } - - ptr_vector free_var_sorts; - svector quant_names; - get_free_vars(res_inner.get(), free_var_sorts); - unsigned free_var_cnt = free_var_sorts.size(); - for(unsigned i=0; i const& assumptions) { - SASSERT(!root_clause || root_clause->is_forall()); - SASSERT(is_quantifier(clause) || root_clause); - context& ctx = get_context(); - buffer lits; - ptr_buffer todo; - - bool is_q_clause = is_quantifier(clause); - quantifier * q_clause = is_q_clause ? to_quantifier(clause) : 0; - if (!root_clause) root_clause = q_clause; - - lits.push_back(~get_root_clause_control_literal(root_clause)); - - for(unsigned i=0; iget_expr()):clause); - - while (!todo.empty()) { - expr* e = todo.back(); - todo.pop_back(); - if (m().is_or(e)) { - todo.append(to_app(e)->get_num_args(), to_app(e)->get_args()); - } - else if (is_app(e)) { - lits.push_back(ground_fo_literal(to_app(e), q_clause)); - } - else { - SASSERT(is_var(e) || is_quantifier(e)); - UNREACHABLE(); - //by skipping part of the disjunction we may get unsound - } - } - TRACE("theory_instgen", - tout << "Axiom: \n"; - for (unsigned i = 0; i < lits.size(); ++i) { - expr_ref e(m()); - get_context().literal2expr(lits[i], e); - tout << PP(e.get(), m()) << "\n"; - } - ); - m_parent.inc_axioms(); - ctx.mk_th_axiom(m_parent.get_id(), lits.size(), lits.c_ptr()); - } - - -}; diff --git a/src/smt/theory_instgen.h b/src/smt/theory_instgen.h deleted file mode 100644 index c32636e9b..000000000 --- a/src/smt/theory_instgen.h +++ /dev/null @@ -1,45 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - theory_instgen.h - -Abstract: - - InstGen (iProver) style theory solver. - It provides an instantiation based engine - based on InstGen methods together with - unit propagation. - - -Author: - - Krystof Hoder (t-khoder) - Nikolaj Bjorner (nbjorner) 2011-10-6 - -Revision History: - ---*/ -#ifndef _THEORY_INST_GEN_H_ -#define _THEORY_INST_GEN_H_ - -#include "smt_theory.h" -#include "smt_params.h" - -namespace smt { - - class theory_instgen : public theory { - public: - theory_instgen(family_id fid) : theory(fid) {} - virtual ~theory_instgen() {} - virtual void internalize_quantifier(quantifier* q) = 0; - virtual char const * get_name() const { return "instgen"; } - }; - - theory_instgen* mk_theory_instgen(ast_manager& m, smt_params& p); - -}; - -#endif /* _THEORY_INST_GEN_H_ */ - From a934c6813a89d78e08d0586c9d28f1deb30e2a43 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 13:04:54 -0800 Subject: [PATCH 26/57] Fixed bug reported by Yan Peng from UBC Signed-off-by: Leonardo de Moura --- src/nlsat/nlsat_explain.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/nlsat/nlsat_explain.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index ca58b15af..460e07f58 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -981,6 +981,14 @@ namespace nlsat { bool atom_val = a->get_kind() == atom::EQ; bool lit_val = l.sign() ? !atom_val : atom_val; new_lit = lit_val ? true_literal : false_literal; + if (!info.m_lc_const) { + // We have essentially shown the current factor must be zero If the leading coefficient is not zero. + // Note that, if the current factor is zero, then the whole polynomial is zero. + // The atom is true if it is an equality, and false otherwise. + // The sign of the leading coefficient (info.m_lc) of info.m_eq doesn't matter. + // However, we have to store the fact it is not zero. + info.add_lc_diseq(); + } return; } else if (s == -1 && !is_even) { @@ -1341,3 +1349,32 @@ namespace nlsat { } }; + +#ifdef Z3DEBUG +void pp(nlsat::explain::imp & ex, unsigned num, nlsat::literal const * ls) { + ex.display(std::cout, num, ls); +} +void pp(nlsat::explain::imp & ex, nlsat::scoped_literal_vector & ls) { + ex.display(std::cout, ls); +} +void pp(nlsat::explain::imp & ex, polynomial_ref const & p) { + ex.display(std::cout, p); + std::cout << std::endl; +} +void pp(nlsat::explain::imp & ex, polynomial::polynomial * p) { + polynomial_ref _p(p, ex.m_pm); + ex.display(std::cout, _p); + std::cout << std::endl; +} +void pp(nlsat::explain::imp & ex, polynomial_ref_vector const & ps) { + ex.display(std::cout, ps); +} +void pp_var(nlsat::explain::imp & ex, nlsat::var x) { + ex.display(std::cout, x); + std::cout << std::endl; +} +void pp_lit(nlsat::explain::imp & ex, nlsat::literal l) { + ex.display(std::cout, l); + std::cout << std::endl; +} +#endif diff --git a/src/nlsat/nlsat_explain.h b/src/nlsat/nlsat_explain.h index 08f6201be..5ecb9d385 100644 --- a/src/nlsat/nlsat_explain.h +++ b/src/nlsat/nlsat_explain.h @@ -27,7 +27,9 @@ namespace nlsat { class evaluator; class explain { + public: struct imp; + private: imp * m_imp; public: explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq, From 75f96f0b9b371818d10f098a675e1e686afe1174 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 18:12:04 -0800 Subject: [PATCH 27/57] added hack for nmake limitation Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index af19cb91c..b57e5abbc 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -75,6 +75,8 @@ VER_BUILD=None VER_REVISION=None PREFIX='/usr' GMP=False +VS_PAR=False +VS_PAR_NUM=8 def is_windows(): return IS_WINDOWS @@ -362,6 +364,8 @@ def display_help(exit_code): if not IS_WINDOWS: print " -p , --prefix= installation prefix (default: %s)." % PREFIX print " -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR + else: + print " --parallel=num use cl option /MP with 'num' parallel processes" print " -b , --build= subdirectory where Z3 will be built (default: build)." print " -d, --debug compile Z3 in debug mode." print " -t, --trace enable tracing in release mode." @@ -391,13 +395,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 + 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, PYTHON_PACKAGE_DIR try: options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:dsxhmcvtnp:gjy:', ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', - 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=']) + 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=', 'parallel=']) except: print "ERROR: Invalid command line option" display_help(1) @@ -429,8 +433,11 @@ def parse_options(): DOTNET_ENABLED = False elif opt in ('--staticlib'): STATIC_LIB = True - elif opt in ('-p', '--prefix'): + elif not IS_WINDOWS and opt in ('-p', '--prefix'): PREFIX = arg + elif IS_WINDOWS and opt == '--parallel': + VS_PAR = True + VS_PAR_NUM = int(arg) elif opt in ('-y', '--pydir'): PYTHON_PACKAGE_DIR = arg mk_dir(PYTHON_PACKAGE_DIR) @@ -656,8 +663,32 @@ class Component: out.write(' -I%s' % get_component(dep).to_src_dir) out.write('\n') mk_dir(os.path.join(BUILD_DIR, self.build_dir)) - for cppfile in get_cpp_files(self.src_dir): - self.add_cpp_rules(out, include_defs, cppfile) + if VS_PAR and IS_WINDOWS: + cppfiles = get_cpp_files(self.src_dir) + dependencies = set() + for cppfile in cppfiles: + dependencies.add(os.path.join(self.to_src_dir, cppfile)) + self.add_rule_for_each_include(out, cppfile) + includes = extract_c_includes(os.path.join(self.src_dir, cppfile)) + for include in includes: + owner = self.find_file(include, cppfile) + dependencies.add('%s.node' % os.path.join(owner.build_dir, include)) + for cppfile in cppfiles: + out.write('%s$(OBJ_EXT) ' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0])) + out.write(': ') + for dep in dependencies: + out.write(dep) + out.write(' ') + out.write('\n') + out.write('\t@$(CXX) $(CXXFLAGS) /MP%s $(%s)' % (VS_PAR_NUM, include_defs)) + for cppfile in cppfiles: + out.write(' ') + out.write(os.path.join(self.to_src_dir, cppfile)) + out.write('\n') + out.write('\tmove *.obj %s\n' % self.build_dir) + else: + for cppfile in get_cpp_files(self.src_dir): + self.add_cpp_rules(out, include_defs, cppfile) # Return true if the component should be included in the all: rule def main_component(self): From dfcfd3f0148843d4ce11273af385ab6d2fa14a8f Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 12 Dec 2012 18:16:59 -0800 Subject: [PATCH 28/57] C:/Program Files (x86)/Git/Gm and /MP are incompatible Signed-off-by: Leonardo de Moura --- 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 b57e5abbc..3ffa7e313 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1284,12 +1284,12 @@ def mk_config(): 'SLINK_FLAGS=/nologo /LDd\n') if not VS_X64: config.write( - 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' + 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' '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 /D _CONSOLE /D _TRACE /D _WINDOWS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' + 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' '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: From 85ac2f558c81cc3d6cffdf4aab4b05c35d0b1e58 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 13 Dec 2012 07:23:09 -0800 Subject: [PATCH 29/57] marked script as executable Signed-off-by: Leonardo de Moura --- scripts/trackall.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/trackall.sh diff --git a/scripts/trackall.sh b/scripts/trackall.sh old mode 100644 new mode 100755 From 5b6842fbc5b559a86e65fc3825b4ecccf0f49a86 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 13 Dec 2012 12:37:03 -0800 Subject: [PATCH 30/57] cleaning defined_names Signed-off-by: Leonardo de Moura --- src/ast/normal_forms/defined_names.cpp | 88 ++++++++++++++++++++++++++ src/ast/normal_forms/defined_names.h | 87 ++++--------------------- src/smt/asserted_formulas.cpp | 4 +- 3 files changed, 101 insertions(+), 78 deletions(-) diff --git a/src/ast/normal_forms/defined_names.cpp b/src/ast/normal_forms/defined_names.cpp index dab0ca0d8..91acacf61 100644 --- a/src/ast/normal_forms/defined_names.cpp +++ b/src/ast/normal_forms/defined_names.cpp @@ -17,11 +17,64 @@ Revision History: --*/ #include"defined_names.h" +#include"obj_hashtable.h" #include"used_vars.h" #include"var_subst.h" #include"ast_smt2_pp.h" #include"ast_pp.h" +struct defined_names::impl { + typedef obj_map expr2name; + typedef obj_map expr2proof; + ast_manager & m_manager; + symbol m_z3name; + + /** + \brief Mapping from expressions to their names. A name is an application. + If the expression does not have free variables, then the name is just a constant. + */ + expr2name m_expr2name; + /** + \brief Mapping from expressions to the apply-def proof. + That is, for each expression e, m_expr2proof[e] is the + proof e and m_expr2name[2] are observ. equivalent. + + This mapping is not used if proof production is disabled. + */ + expr2proof m_expr2proof; + + /** + \brief Domain of m_expr2name. It is used to keep the expressions + alive and for backtracking + */ + expr_ref_vector m_exprs; + expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive. + proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive. + + + unsigned_vector m_lims; //!< Backtracking support. + + impl(ast_manager & m, char const * prefix); + virtual ~impl(); + + app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names); + void cache_new_name(expr * e, app * name); + void cache_new_name_intro_proof(expr * e, proof * pr); + void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref & result); + void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref_buffer & result); + virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); + bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); + void push_scope(); + void pop_scope(unsigned num_scopes); + void reset(); +}; + +struct defined_names::pos_impl : public defined_names::impl { + pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {} + virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); +}; + + defined_names::impl::impl(ast_manager & m, char const * prefix): m_manager(m), m_exprs(m), @@ -222,5 +275,40 @@ void defined_names::impl::reset() { m_lims.reset(); } +defined_names::defined_names(ast_manager & m, char const * fresh_prefix) { + m_impl = alloc(impl, m, fresh_prefix); + m_pos_impl = alloc(pos_impl, m, fresh_prefix); +} + +defined_names::~defined_names() { + dealloc(m_impl); + dealloc(m_pos_impl); +} + +bool defined_names::mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { + return m_impl->mk_name(e, new_def, new_def_pr, n, pr); +} + +bool defined_names::mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { + return m_pos_impl->mk_name(e, new_def, new_def_pr, n, pr); +} + +void defined_names::push() { + m_impl->push_scope(); + m_pos_impl->push_scope(); +} + +void defined_names::pop(unsigned num_scopes) { + m_impl->pop_scope(num_scopes); + m_pos_impl->pop_scope(num_scopes); +} + +void defined_names::reset() { + m_impl->reset(); + m_pos_impl->reset(); +} + + + diff --git a/src/ast/normal_forms/defined_names.h b/src/ast/normal_forms/defined_names.h index c5e4a116f..d720a2fa3 100644 --- a/src/ast/normal_forms/defined_names.h +++ b/src/ast/normal_forms/defined_names.h @@ -21,7 +21,6 @@ Revision History: #define _DEFINED_NAMES_H_ #include"ast.h" -#include"obj_hashtable.h" /** \brief Mapping from expressions to skolem functions that are used to name them. @@ -29,62 +28,13 @@ Revision History: The mapping supports backtracking using the methods #push_scope and #pop_scope. */ class defined_names { - - struct impl { - typedef obj_map expr2name; - typedef obj_map expr2proof; - ast_manager & m_manager; - symbol m_z3name; - - /** - \brief Mapping from expressions to their names. A name is an application. - If the expression does not have free variables, then the name is just a constant. - */ - expr2name m_expr2name; - /** - \brief Mapping from expressions to the apply-def proof. - That is, for each expression e, m_expr2proof[e] is the - proof e and m_expr2name[2] are observ. equivalent. - - This mapping is not used if proof production is disabled. - */ - expr2proof m_expr2proof; - - /** - \brief Domain of m_expr2name. It is used to keep the expressions - alive and for backtracking - */ - expr_ref_vector m_exprs; - expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive. - proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive. - - - unsigned_vector m_lims; //!< Backtracking support. - - impl(ast_manager & m, char const * prefix); - virtual ~impl(); - - app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names); - void cache_new_name(expr * e, app * name); - void cache_new_name_intro_proof(expr * e, proof * pr); - void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref & result); - void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref_buffer & result); - virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); - bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); - void push_scope(); - void pop_scope(unsigned num_scopes); - void reset(); - }; - - struct pos_impl : public impl { - pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {} - virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); - }; - - impl m_impl; - pos_impl m_pos_impl; + struct impl; + struct pos_impl; + impl * m_impl; + pos_impl * m_pos_impl; public: - defined_names(ast_manager & m, char const * fresh_prefix = "z3name"):m_impl(m, fresh_prefix), m_pos_impl(m, fresh_prefix) {} + defined_names(ast_manager & m, char const * fresh_prefix = "z3name"); + ~defined_names(); // ----------------------------------- // @@ -113,9 +63,7 @@ public: Remark: the definitions are closed with an universal quantifier if e contains free variables. */ - bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { - return m_impl.mk_name(e, new_def, new_def_pr, n, pr); - } + bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); /** \brief Create a name for a positive occurrence of the expression \c e. @@ -127,24 +75,11 @@ public: Remark: the definitions are closed with an universal quantifier if e contains free variables. */ - bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { - return m_pos_impl.mk_name(e, new_def, new_def_pr, n, pr); - } + bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); - void push_scope() { - m_impl.push_scope(); - m_pos_impl.push_scope(); - } - - void pop_scope(unsigned num_scopes) { - m_impl.pop_scope(num_scopes); - m_pos_impl.pop_scope(num_scopes); - } - - void reset() { - m_impl.reset(); - m_pos_impl.reset(); - } + void push(); + void pop(unsigned num_scopes); + void reset(); }; #endif /* _DEFINED_NAMES_H_ */ diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 6da2c15f5..5552050db 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -189,7 +189,7 @@ void asserted_formulas::push_scope() { s.m_asserted_formulas_lim = m_asserted_formulas.size(); SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead); s.m_inconsistent_old = m_inconsistent; - m_defined_names.push_scope(); + m_defined_names.push(); m_bv_sharing.push_scope(); commit(); } @@ -201,7 +201,7 @@ void asserted_formulas::pop_scope(unsigned num_scopes) { unsigned new_lvl = m_scopes.size() - num_scopes; scope & s = m_scopes[new_lvl]; m_inconsistent = s.m_inconsistent_old; - m_defined_names.pop_scope(num_scopes); + m_defined_names.pop(num_scopes); m_asserted_formulas.shrink(s.m_asserted_formulas_lim); if (m_manager.proofs_enabled()) m_asserted_formula_prs.shrink(s.m_asserted_formulas_lim); From e0f4d870fd120f0429a557d583035963a0a6cc08 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 13 Dec 2012 14:03:58 -0800 Subject: [PATCH 31/57] Removed auxiliary constants created by the nnf tactic from Z3 models. Fixed model.compact parameter propagation problem. Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 ++ src/ast/normal_forms/defined_names.cpp | 13 +++++++++++++ src/ast/normal_forms/defined_names.h | 3 +++ src/smt/params/smt_params.cpp | 4 +++- src/smt/params/smt_params.h | 2 -- src/tactic/core/nnf_tactic.cpp | 8 ++++++++ 6 files changed, 29 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 7ac026673..19b361acc 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -26,6 +26,8 @@ Version 4.3.2 - Fixed crash reported at http://z3.codeplex.com/workitem/10 +- Removed auxiliary constants created by the nnf tactic from Z3 models. + Version 4.3.1 ============= diff --git a/src/ast/normal_forms/defined_names.cpp b/src/ast/normal_forms/defined_names.cpp index 91acacf61..16e9098fc 100644 --- a/src/ast/normal_forms/defined_names.cpp +++ b/src/ast/normal_forms/defined_names.cpp @@ -67,6 +67,9 @@ struct defined_names::impl { void push_scope(); void pop_scope(unsigned num_scopes); void reset(); + + unsigned get_num_names() const { return m_names.size(); } + func_decl * get_name_decl(unsigned i) const { return to_app(m_names.get(i))->get_decl(); } }; struct defined_names::pos_impl : public defined_names::impl { @@ -308,6 +311,16 @@ void defined_names::reset() { m_pos_impl->reset(); } +unsigned defined_names::get_num_names() const { + return m_impl->get_num_names() + m_pos_impl->get_num_names(); +} + +func_decl * defined_names::get_name_decl(unsigned i) const { + SASSERT(i < get_num_names()); + unsigned n1 = m_impl->get_num_names(); + return i < n1 ? m_impl->get_name_decl(i) : m_pos_impl->get_name_decl(i - n1); +} + diff --git a/src/ast/normal_forms/defined_names.h b/src/ast/normal_forms/defined_names.h index d720a2fa3..0b9f04569 100644 --- a/src/ast/normal_forms/defined_names.h +++ b/src/ast/normal_forms/defined_names.h @@ -80,6 +80,9 @@ public: void push(); void pop(unsigned num_scopes); void reset(); + + unsigned get_num_names() const; + func_decl * get_name_decl(unsigned i) const; }; #endif /* _DEFINED_NAMES_H_ */ diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index e62a3de21..519302c19 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -18,6 +18,7 @@ Revision History: --*/ #include"smt_params.h" #include"smt_params_helper.hpp" +#include"model_params.hpp" void smt_params::updt_local_params(params_ref const & _p) { smt_params_helper p(_p); @@ -33,6 +34,8 @@ void smt_params::updt_local_params(params_ref const & _p) { m_delay_units_threshold = p.delay_units_threshold(); m_preprocess = _p.get_bool("preprocess", true); // hidden parameter m_soft_timeout = p.soft_timeout(); + model_params mp(_p); + m_model_compact = mp.compact(); if (_p.get_bool("arith.greatest_error_pivot", false)) m_arith_pivot_strategy = ARITH_PIVOT_GREATEST_ERROR; else if (_p.get_bool("arith.least_error_pivot", false)) @@ -50,5 +53,4 @@ void smt_params::updt_params(params_ref const & p) { void smt_params::updt_params(context_params const & p) { m_auto_config = p.m_auto_config; m_model = p.m_model; - m_model_validate = p.m_model_validate; } diff --git a/src/smt/params/smt_params.h b/src/smt/params/smt_params.h index 3d823cb51..256c5a646 100644 --- a/src/smt/params/smt_params.h +++ b/src/smt/params/smt_params.h @@ -177,7 +177,6 @@ struct smt_params : public preprocessor_params, // ----------------------------------- bool m_model; bool m_model_compact; - bool m_model_validate; bool m_model_on_timeout; bool m_model_on_final_check; @@ -264,7 +263,6 @@ struct smt_params : public preprocessor_params, m_abort_after_preproc(false), m_model(true), m_model_compact(false), - m_model_validate(false), m_model_on_timeout(false), m_model_on_final_check(false), m_progress_sampling_freq(0), diff --git a/src/tactic/core/nnf_tactic.cpp b/src/tactic/core/nnf_tactic.cpp index a79a4ed06..19190c299 100644 --- a/src/tactic/core/nnf_tactic.cpp +++ b/src/tactic/core/nnf_tactic.cpp @@ -18,6 +18,7 @@ Revision History: --*/ #include"nnf.h" #include"tactical.h" +#include"filter_model_converter.h" class nnf_tactic : public tactic { params_ref m_params; @@ -100,6 +101,13 @@ public: } g->inc_depth(); result.push_back(g.get()); + unsigned num_extra_names = dnames.get_num_names(); + if (num_extra_names > 0) { + filter_model_converter * fmc = alloc(filter_model_converter, m); + mc = fmc; + for (unsigned i = 0; i < num_extra_names; i++) + fmc->insert(dnames.get_name_decl(i)); + } TRACE("nnf", g->display(tout);); SASSERT(g->is_well_sorted()); } From c98f0c830797053a1b3619f97c5175f4db753e7b Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 13 Dec 2012 14:09:52 -0800 Subject: [PATCH 32/57] fixed unused variable warning Signed-off-by: Leonardo de Moura --- src/muz_qe/dl_mk_extract_quantifiers2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/muz_qe/dl_mk_extract_quantifiers2.cpp b/src/muz_qe/dl_mk_extract_quantifiers2.cpp index 97976a6be..58255d2a1 100644 --- a/src/muz_qe/dl_mk_extract_quantifiers2.cpp +++ b/src/muz_qe/dl_mk_extract_quantifiers2.cpp @@ -332,7 +332,7 @@ namespace datalog { smt::quantifier_manager* qm = ctx.get_quantifier_manager(); qm->get_plugin()->set_instance_plugin(alloc(instance_plugin, *this)); #endif - lbool res = solver.check(); + solver.check(); for (unsigned i = 0; i < m_bindings.size(); ++i) { expr_ref_vector& binding = m_bindings[i]; From 6958b9cdb68e01e9fe7bcd7e3ba66ebb16296f4d Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 13 Dec 2012 15:19:37 -0800 Subject: [PATCH 33/57] Fixed issues with the pretty printer Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 ++ src/ast/ast_smt2_pp.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 19b361acc..2c8d93acd 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -28,6 +28,8 @@ Version 4.3.2 - Removed auxiliary constants created by the nnf tactic from Z3 models. +- Fixed problem in the pretty printer. It was not introducing quotes for attribute names such as |foo:10|. + Version 4.3.1 ============= diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index afe301ddf..1ad2b8222 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -501,7 +501,12 @@ class smt2_printer { } format * pp_simple_attribute(char const * attr, symbol const & s) { - return mk_compose(m(), mk_string(m(), attr), mk_string(m(), s.str().c_str())); + std::string str; + if (is_smt2_quoted_symbol(s)) + str = mk_smt2_quoted_symbol(s); + else + str = s.str(); + return mk_compose(m(), mk_string(m(), attr), mk_string(m(), str.c_str())); } format * pp_labels(bool is_pos, buffer const & names, format * f) { @@ -851,7 +856,7 @@ class smt2_printer { buf.push_back(pp_simple_attribute(":weight ", q->get_weight())); } if (q->get_skid() != symbol::null) { - buf.push_back(pp_simple_attribute(":skid ", q->get_skid())); + buf.push_back(pp_simple_attribute(":skolemid ", q->get_skid())); } if (q->get_qid() != symbol::null) { #if 0 From 4df172e9711c198d81ec382625ea819e2cb703ba Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 14 Dec 2012 08:14:44 -0800 Subject: [PATCH 34/57] Fix file name (use same naming convention) Signed-off-by: Leonardo de Moura --- src/tactic/core/ctx_simplify_tactic.cpp | 4 ++-- .../{num_occurs_goal.cpp => goal_num_occurs.cpp} | 6 +++--- src/tactic/{num_occurs_goal.h => goal_num_occurs.h} | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) rename src/tactic/{num_occurs_goal.cpp => goal_num_occurs.cpp} (75%) rename src/tactic/{num_occurs_goal.h => goal_num_occurs.h} (64%) diff --git a/src/tactic/core/ctx_simplify_tactic.cpp b/src/tactic/core/ctx_simplify_tactic.cpp index cca21b90e..831efa087 100644 --- a/src/tactic/core/ctx_simplify_tactic.cpp +++ b/src/tactic/core/ctx_simplify_tactic.cpp @@ -18,7 +18,7 @@ Notes: --*/ #include"ctx_simplify_tactic.h" #include"mk_simplified_app.h" -#include"num_occurs_goal.h" +#include"goal_num_occurs.h" #include"cooperate.h" #include"ast_ll_pp.h" #include"ast_smt2_pp.h" @@ -51,7 +51,7 @@ struct ctx_simplify_tactic::imp { unsigned m_scope_lvl; unsigned m_depth; unsigned m_num_steps; - num_occurs_goal m_occs; + goal_num_occurs m_occs; mk_simplified_app m_mk_app; unsigned long long m_max_memory; unsigned m_max_depth; diff --git a/src/tactic/num_occurs_goal.cpp b/src/tactic/goal_num_occurs.cpp similarity index 75% rename from src/tactic/num_occurs_goal.cpp rename to src/tactic/goal_num_occurs.cpp index adc412434..6c94e307c 100644 --- a/src/tactic/num_occurs_goal.cpp +++ b/src/tactic/goal_num_occurs.cpp @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - num_occurs_goal.cpp + goal_num_occurs.cpp Abstract: @@ -15,10 +15,10 @@ Author: Revision History: --*/ -#include"num_occurs_goal.h" +#include"goal_num_occurs.h" #include"goal.h" -void num_occurs_goal::operator()(goal const & g) { +void goal_num_occurs::operator()(goal const & g) { expr_fast_mark1 visited; unsigned sz = g.size(); for (unsigned i = 0; i < sz; i++) { diff --git a/src/tactic/num_occurs_goal.h b/src/tactic/goal_num_occurs.h similarity index 64% rename from src/tactic/num_occurs_goal.h rename to src/tactic/goal_num_occurs.h index 5e6e0cc94..33a25e03f 100644 --- a/src/tactic/num_occurs_goal.h +++ b/src/tactic/goal_num_occurs.h @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - num_occurs_goal.h + goal_num_occurs.h Abstract: @@ -15,16 +15,16 @@ Author: Revision History: --*/ -#ifndef _NUM_OCCURS_GOAL_H_ -#define _NUM_OCCURS_GOAL_H_ +#ifndef _GOAL_NUM_OCCURS_H_ +#define _GOAL_NUM_OCCURS_H_ #include"num_occurs.h" class goal; -class num_occurs_goal : public num_occurs { +class goal_num_occurs : public num_occurs { public: - num_occurs_goal(bool ignore_ref_count1 = false, bool ignore_quantifiers = false): + goal_num_occurs(bool ignore_ref_count1 = false, bool ignore_quantifiers = false): num_occurs(ignore_ref_count1, ignore_quantifiers) { } From 9634d66699a4803360561d87df4a5fa352c144c0 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 15 Dec 2012 08:10:48 -0800 Subject: [PATCH 35/57] Fix typo in tactic selection Signed-off-by: Leonardo de Moura --- src/tactic/portfolio/smt_strategic_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 4813cbe1a..0e63255ca 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -39,7 +39,7 @@ Notes: tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { if (logic=="QF_UF") - return mk_qfufbv_tactic(m, p); + return mk_qfuf_tactic(m, p); else if (logic=="QF_BV") return mk_qfbv_tactic(m, p); else if (logic=="QF_IDL") From 050ec0b760a89a1fb4454122af182edebeb0ea83 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 15 Dec 2012 13:26:11 -0800 Subject: [PATCH 36/57] Fix memout detected in nightly regressions Signed-off-by: Leonardo de Moura --- src/solver/combined_solver.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp index cd4191e76..a98e5be49 100644 --- a/src/solver/combined_solver.cpp +++ b/src/solver/combined_solver.cpp @@ -55,13 +55,28 @@ private: bool m_use_solver1_results; ref m_solver1; ref m_solver2; - + // We delay sending assertions to solver 2 + // This is relevant for big benchmarks that are meant to be solved + // by a non-incremental solver. + bool m_solver2_initialized; + bool m_ignore_solver1; inc_unknown_behavior m_inc_unknown_behavior; unsigned m_inc_timeout; + + void init_solver2_assertions() { + if (m_solver2_initialized) + return; + unsigned sz = m_solver1->get_num_assertions(); + for (unsigned i = 0; i < sz; i++) { + m_solver2->assert_expr(m_solver1->get_assertion(i)); + } + m_solver2_initialized = true; + } void switch_inc_mode() { m_inc_mode = true; + init_solver2_assertions(); } struct aux_timeout_eh : public event_handler { @@ -106,6 +121,7 @@ public: m_solver1 = s1; m_solver2 = s2; updt_local_params(p); + m_solver2_initialized = false; m_inc_mode = false; m_check_sat_executed = false; m_use_solver1_results = true; @@ -132,13 +148,15 @@ public: if (m_check_sat_executed) switch_inc_mode(); m_solver1->assert_expr(t); - m_solver2->assert_expr(t); + if (m_solver2_initialized) + m_solver2->assert_expr(t); } virtual void assert_expr(expr * t, expr * a) { if (m_check_sat_executed) switch_inc_mode(); m_solver1->assert_expr(t, a); + init_solver2_assertions(); m_solver2->assert_expr(t, a); } From 7e66a65e980402cb5c6ee464ae9fdb7b669bfd93 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 10:32:00 -0800 Subject: [PATCH 37/57] Add blast_distinct_threshold option to rewriter. Enable blast_distinct in the QF_LIA default strategy Signed-off-by: Leonardo de Moura --- src/ast/rewriter/bool_rewriter.cpp | 3 ++- src/ast/rewriter/bool_rewriter.h | 1 + src/ast/rewriter/bool_rewriter_params.pyg | 4 +++- src/tactic/smtlogics/qflia_tactic.cpp | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ast/rewriter/bool_rewriter.cpp b/src/ast/rewriter/bool_rewriter.cpp index b5f18a461..5b0c38616 100644 --- a/src/ast/rewriter/bool_rewriter.cpp +++ b/src/ast/rewriter/bool_rewriter.cpp @@ -27,6 +27,7 @@ void bool_rewriter::updt_params(params_ref const & _p) { m_local_ctx = p.local_ctx(); m_local_ctx_limit = p.local_ctx_limit(); m_blast_distinct = p.blast_distinct(); + m_blast_distinct_threshold = p.blast_distinct_threshold(); m_ite_extra_rules = p.ite_extra_rules(); } @@ -746,7 +747,7 @@ br_status bool_rewriter::mk_distinct_core(unsigned num_args, expr * const * args return BR_DONE; } - if (m_blast_distinct) { + if (m_blast_distinct && num_args < m_blast_distinct_threshold) { ptr_buffer new_diseqs; for (unsigned i = 0; i < num_args; i++) { for (unsigned j = i + 1; j < num_args; j++) diff --git a/src/ast/rewriter/bool_rewriter.h b/src/ast/rewriter/bool_rewriter.h index b1a177247..ef6dc2d38 100644 --- a/src/ast/rewriter/bool_rewriter.h +++ b/src/ast/rewriter/bool_rewriter.h @@ -55,6 +55,7 @@ class bool_rewriter { bool m_local_ctx; bool m_elim_and; bool m_blast_distinct; + unsigned m_blast_distinct_threshold; bool m_ite_extra_rules; unsigned m_local_ctx_limit; unsigned m_local_ctx_cost; diff --git a/src/ast/rewriter/bool_rewriter_params.pyg b/src/ast/rewriter/bool_rewriter_params.pyg index a5bcf6f5d..531bf4db9 100644 --- a/src/ast/rewriter/bool_rewriter_params.pyg +++ b/src/ast/rewriter/bool_rewriter_params.pyg @@ -6,4 +6,6 @@ def_module_params(module_name='rewriter', ("elim_and", BOOL, False, "conjunctions are rewritten using negation and disjunctions"), ("local_ctx", BOOL, False, "perform local (i.e., cheap) context simplifications"), ("local_ctx_limit", UINT, UINT_MAX, "limit for applying local context simplifier"), - ("blast_distinct", BOOL, False, "expand a distinct predicate into a quadratic number of disequalities"))) + ("blast_distinct", BOOL, False, "expand a distinct predicate into a quadratic number of disequalities"), + ("blast_distinct_threshold", UINT, UINT_MAX, "when blast_distinct is true, only distinct expressions with less than this number of arguments are blasted") + )) diff --git a/src/tactic/smtlogics/qflia_tactic.cpp b/src/tactic/smtlogics/qflia_tactic.cpp index 6b05cff96..6fbf34255 100644 --- a/src/tactic/smtlogics/qflia_tactic.cpp +++ b/src/tactic/smtlogics/qflia_tactic.cpp @@ -172,6 +172,8 @@ tactic * mk_qflia_tactic(ast_manager & m, params_ref const & p) { params_ref main_p; main_p.set_bool("elim_and", true); main_p.set_bool("som", true); + main_p.set_bool("blast_distinct", true); + main_p.set_uint("blast_distinct_threshold", 128); // main_p.set_bool("push_ite_arith", true); params_ref pull_ite_p; From 143b829488f83b8cf10a14aaceb61cf9f519273c Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 13:42:01 -0800 Subject: [PATCH 38/57] Fix literal duplication bug that was introduced after v4.3.1 release Signed-off-by: Leonardo de Moura --- src/smt/asserted_formulas.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 5552050db..3155d9c58 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -439,6 +439,8 @@ void asserted_formulas::nnf_cnf() { expr_ref r1(m_manager); proof_ref pr1(m_manager); CASSERT("well_sorted",is_well_sorted(m_manager, n)); + push_todo.reset(); + push_todo_prs.reset(); apply_nnf(n, push_todo, push_todo_prs, r1, pr1); CASSERT("well_sorted",is_well_sorted(m_manager, r1)); pr = m_manager.mk_modus_ponens(pr, pr1); @@ -855,3 +857,8 @@ void asserted_formulas::max_bv_sharing() { } +#ifdef Z3DEBUG +void pp(asserted_formulas & f) { + f.display(std::cout); +} +#endif From 8c211dd4fcd3299a069fdb6f2ea6ce1a48ff6e57 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 14:07:21 -0800 Subject: [PATCH 39/57] Fix bug reported by Philippe Suter, see RELEASE_NOTES Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 15 +++++++++++++++ src/smt/smt_context.cpp | 12 +++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 2c8d93acd..538626a0e 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -30,6 +30,21 @@ Version 4.3.2 - Fixed problem in the pretty printer. It was not introducing quotes for attribute names such as |foo:10|. +- Fixed bug when using assumptions (Thanks to Philippe Suter) + Consider the following example: + (assert F) + (check-sat a) + (check-sat) + If 'F' is unstatisfiable independently of the assumption 'a', and + the inconsistenty can be detected by just performing propagation, + Then, version <= 4.3.1 may return + unsat + sat + instead of + unsat + unsat + We say may because 'F' may have other unsatisfiable cores. + Version 4.3.1 ============= diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index a7623832f..02ee06985 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -2854,7 +2854,12 @@ namespace smt { m_bool_var2assumption.reset(); m_unsat_core.reset(); if (num_assumptions > 0) { - propagate(); // we must give a chance to the theories to propagate before we create a new scope... + // We must give a chance to the theories to propagate before we create a new scope... + propagate(); + // Internal backtracking scopes (created with push_scope()) must only be created when we are + // in a consistent context. + if (inconsistent()) + return; push_scope(); for (unsigned i = 0; i < num_assumptions; i++) { expr * curr_assumption = assumptions[i]; @@ -3987,3 +3992,8 @@ namespace smt { }; +#ifdef Z3DEBUG +void pp(smt::context & c) { + c.display(std::cout); +} +#endif From f8014f54c18ad6ce58573ed4072ff32b3f2b6f53 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 15:12:36 -0800 Subject: [PATCH 40/57] Fix bug reported at http://stackoverflow.com/questions/13923316/unprintable-solver-model Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 ++ src/api/python/z3.py | 11 +++++++++-- src/api/python/z3printer.py | 6 +++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 538626a0e..75f7e42be 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -45,6 +45,8 @@ Version 4.3.2 unsat We say may because 'F' may have other unsatisfiable cores. +- Fixed bug reported at http://stackoverflow.com/questions/13923316/unprintable-solver-model + Version 4.3.1 ============= diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 924ac0ea5..8a13c7a99 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -5122,7 +5122,10 @@ class FuncInterp(Z3PPObject): Z3_func_interp_dec_ref(self.ctx.ref(), self.f) def else_value(self): - """Return the `else` value for a function interpretation. + """ + Return the `else` value for a function interpretation. + Return None if Z3 did not specify the `else` value for + this object. >>> f = Function('f', IntSort(), IntSort()) >>> s = Solver() @@ -5135,7 +5138,11 @@ class FuncInterp(Z3PPObject): >>> m[f].else_value() 1 """ - return _to_expr_ref(Z3_func_interp_get_else(self.ctx.ref(), self.f), self.ctx) + r = Z3_func_interp_get_else(self.ctx.ref(), self.f) + if r: + return _to_expr_ref(r, self.ctx) + else: + return None def num_entries(self): """Return the number of entries/points in the function interpretation `self`. diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index 920de1a3b..3ad8f21b9 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -791,7 +791,11 @@ class Formatter: r.append(self.pp_ellipses()) break if sz <= self.max_args: - else_pp = self.pp_expr(f.else_value(), 0, []) + else_val = f.else_value() + if else_val == None: + else_pp = to_format('#unspecified') + else: + else_pp = self.pp_expr(else_val, 0, []) r.append(group(seq((to_format('else'), else_pp), self.pp_arrow()))) return seq3(r, '[', ']') From 607fab486c86be5c0a58e82020dce1b198612368 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 18:35:50 -0800 Subject: [PATCH 41/57] Fix incorrect uses of set_cancel() Signed-off-by: Leonardo de Moura --- src/api/api_datalog.h | 1 + src/ast/ast.h | 2 ++ src/cmd_context/cmd_context.cpp | 7 ++++ src/cmd_context/cmd_context.h | 3 ++ src/math/polynomial/algebraic_numbers.cpp | 42 ----------------------- src/math/polynomial/algebraic_numbers.h | 2 +- src/math/polynomial/polynomial.cpp | 1 - src/math/polynomial/polynomial.h | 1 + src/model/model_evaluator.cpp | 4 +-- src/model/model_evaluator.h | 4 ++- src/muz_qe/dl_context.h | 1 + src/parsers/smt2/smt2parser.cpp | 1 + src/smt/smt_kernel.cpp | 2 -- src/tactic/tactic.cpp | 1 - src/tactic/tactical.cpp | 1 - src/util/cancel_eh.h | 1 + 16 files changed, 23 insertions(+), 51 deletions(-) diff --git a/src/api/api_datalog.h b/src/api/api_datalog.h index 1dc0a9cbd..51dbb72ec 100644 --- a/src/api/api_datalog.h +++ b/src/api/api_datalog.h @@ -55,6 +55,7 @@ namespace api { std::string get_last_status(); std::string to_string(unsigned num_queries, expr*const* queries); void cancel() { m_context.cancel(); } + void reset_cancel() { m_context.reset_cancel(); } unsigned get_num_levels(func_decl* pred); expr_ref get_cover_delta(int level, func_decl* pred); diff --git a/src/ast/ast.h b/src/ast/ast.h index e9da41377..6af95e3a7 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1404,6 +1404,8 @@ public: // propagate cancellation signal to decl_plugins void set_cancel(bool f); + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } bool has_trace_stream() const { return m_trace_stream != 0; } std::ostream & trace_stream() { SASSERT(has_trace_stream()); return *m_trace_stream; } diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index e86e56b69..3f32c77d3 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -343,6 +343,13 @@ cmd_context::~cmd_context() { m_check_sat_result = 0; } +void cmd_context::set_cancel(bool f) { + if (m_solver) + m_solver->set_cancel(f); + if (has_manager()) + m().set_cancel(f); +} + void cmd_context::global_params_updated() { m_params.updt_params(); if (m_solver) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 63e5e7040..07b0cf456 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -249,6 +249,9 @@ protected: public: cmd_context(bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null); ~cmd_context(); + void set_cancel(bool f); + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } context_params & params() { return m_params; } void global_params_updated(); // this method should be invoked when global (and module) params are updated. void set_logic(symbol const & s); diff --git a/src/math/polynomial/algebraic_numbers.cpp b/src/math/polynomial/algebraic_numbers.cpp index 90ad6ea9d..804a134e0 100644 --- a/src/math/polynomial/algebraic_numbers.cpp +++ b/src/math/polynomial/algebraic_numbers.cpp @@ -2796,72 +2796,58 @@ namespace algebraic_numbers { } void manager::del(numeral & a) { - set_cancel(false); return m_imp->del(a); } void manager::reset(numeral & a) { - set_cancel(false); return m_imp->reset(a); } bool manager::is_zero(numeral const & a) { - set_cancel(false); return m_imp->is_zero(const_cast(a)); } bool manager::is_pos(numeral const & a) { - set_cancel(false); return m_imp->is_pos(const_cast(a)); } bool manager::is_neg(numeral const & a) { - set_cancel(false); return m_imp->is_neg(const_cast(a)); } bool manager::is_rational(numeral const & a) { - set_cancel(false); return m_imp->is_rational(const_cast(a)); } bool manager::is_int(numeral const & a) { - set_cancel(false); return m_imp->is_int(const_cast(a)); } unsigned manager::degree(numeral const & a) { - set_cancel(false); return m_imp->degree(const_cast(a)); } void manager::to_rational(numeral const & a, mpq & r) { - set_cancel(false); return m_imp->to_rational(const_cast(a), r); } void manager::to_rational(numeral const & a, rational & r) { - set_cancel(false); return m_imp->to_rational(const_cast(a), r); } void manager::swap(numeral & a, numeral & b) { - set_cancel(false); return m_imp->swap(a, b); } void manager::int_lt(numeral const & a, numeral & b) { - set_cancel(false); m_imp->int_lt(const_cast(a), b); } void manager::int_gt(numeral const & a, numeral & b) { - set_cancel(false); m_imp->int_gt(const_cast(a), b); } void manager::select(numeral const & prev, numeral const & curr, numeral & result) { - set_cancel(false); m_imp->select(const_cast(prev), const_cast(curr), result); } @@ -2878,55 +2864,45 @@ namespace algebraic_numbers { } void manager::set(numeral & a, mpq const & n) { - set_cancel(false); m_imp->set(a, n); } void manager::set(numeral & a, numeral const & n) { - set_cancel(false); m_imp->set(a, n); } void manager::isolate_roots(polynomial_ref const & p, numeral_vector & roots) { - set_cancel(false); m_imp->isolate_roots(p, roots); } void manager::isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots) { - set_cancel(false); m_imp->isolate_roots(p, x2v, roots); } void manager::isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots, svector & signs) { - set_cancel(false); m_imp->isolate_roots(p, x2v, roots, signs); } void manager::mk_root(polynomial_ref const & p, unsigned i, numeral & r) { - set_cancel(false); m_imp->mk_root(p, i, r); } void manager::mk_root(sexpr const * p, unsigned i, numeral & r) { - set_cancel(false); m_imp->mk_root(p, i, r); } void manager::root(numeral const & a, unsigned k, numeral & b) { - set_cancel(false); m_imp->root(const_cast(a), k, b); } void manager::power(numeral const & a, unsigned k, numeral & b) { TRACE("anum_detail", display_root(tout, a); tout << "^" << k << "\n";); - set_cancel(false); m_imp->power(const_cast(a), k, b); TRACE("anum_detail", tout << "^ result: "; display_root(tout, b); tout << "\n";); } void manager::add(numeral const & a, numeral const & b, numeral & c) { TRACE("anum_detail", display_root(tout, a); tout << " + "; display_root(tout, b); tout << "\n";); - set_cancel(false); m_imp->add(const_cast(a), const_cast(b), c); TRACE("anum_detail", tout << "+ result: "; display_root(tout, c); tout << "\n";); } @@ -2939,45 +2915,37 @@ namespace algebraic_numbers { void manager::sub(numeral const & a, numeral const & b, numeral & c) { TRACE("anum_detail", display_root(tout, a); tout << " - "; display_root(tout, b); tout << "\n";); - set_cancel(false); m_imp->sub(const_cast(a), const_cast(b), c); TRACE("anum_detail", tout << "- result: "; display_root(tout, c); tout << "\n";); } void manager::mul(numeral const & a, numeral const & b, numeral & c) { TRACE("anum_detail", display_root(tout, a); tout << " * "; display_root(tout, b); tout << "\n";); - set_cancel(false); m_imp->mul(const_cast(a), const_cast(b), c); TRACE("anum_detail", tout << "* result: "; display_root(tout, c); tout << "\n";); } void manager::div(numeral const & a, numeral const & b, numeral & c) { - set_cancel(false); m_imp->div(const_cast(a), const_cast(b), c); } void manager::neg(numeral & a) { - set_cancel(false); m_imp->neg(a); } void manager::inv(numeral & a) { - set_cancel(false); m_imp->inv(a); } int manager::compare(numeral const & a, numeral const & b) { - set_cancel(false); return m_imp->compare(const_cast(a), const_cast(b)); } bool manager::eq(numeral const & a, numeral const & b) { - set_cancel(false); return m_imp->eq(const_cast(a), const_cast(b)); } bool manager::eq(numeral const & a, mpq const & b) { - set_cancel(false); return m_imp->eq(const_cast(a), b); } @@ -2988,12 +2956,10 @@ namespace algebraic_numbers { } bool manager::lt(numeral const & a, numeral const & b) { - set_cancel(false); return m_imp->lt(const_cast(a), const_cast(b)); } bool manager::lt(numeral const & a, mpq const & b) { - set_cancel(false); return m_imp->lt(const_cast(a), b); } @@ -3004,7 +2970,6 @@ namespace algebraic_numbers { } bool manager::gt(numeral const & a, mpq const & b) { - set_cancel(false); return m_imp->gt(const_cast(a), b); } @@ -3073,38 +3038,31 @@ namespace algebraic_numbers { } int manager::eval_sign_at(polynomial_ref const & p, polynomial::var2anum const & x2v) { - set_cancel(false); SASSERT(&(x2v.m()) == this); return m_imp->eval_sign_at(p, x2v); } void manager::display_interval(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_interval(out, a); } void manager::display_decimal(std::ostream & out, numeral const & a, unsigned precision) const { - const_cast(this)->set_cancel(false); m_imp->display_decimal(out, a, precision); } void manager::display_root(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_root(out, a); } void manager::display_mathematica(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_mathematica(out, a); } void manager::display_root_smt2(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_root_smt2(out, a); } void manager::reset_statistics() { - set_cancel(false); m_imp->reset_statistics(); } diff --git a/src/math/polynomial/algebraic_numbers.h b/src/math/polynomial/algebraic_numbers.h index a4669eae6..d11237b86 100644 --- a/src/math/polynomial/algebraic_numbers.h +++ b/src/math/polynomial/algebraic_numbers.h @@ -64,8 +64,8 @@ namespace algebraic_numbers { static void collect_param_descrs(param_descrs & r) { get_param_descrs(r); } void set_cancel(bool f); - void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } void updt_params(params_ref const & p); diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index 4e14c5661..f5d96e740 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -2368,7 +2368,6 @@ namespace polynomial { void checkpoint() { if (m_cancel) { - set_cancel(false); throw polynomial_exception("canceled"); } cooperate("polynomial"); diff --git a/src/math/polynomial/polynomial.h b/src/math/polynomial/polynomial.h index d17d2ac5a..e52dd4fee 100644 --- a/src/math/polynomial/polynomial.h +++ b/src/math/polynomial/polynomial.h @@ -220,6 +220,7 @@ namespace polynomial { void set_cancel(bool f); void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } /** \brief Abstract event handler. diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index beed0061e..dc4c20aa8 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -244,10 +244,10 @@ unsigned model_evaluator::get_num_steps() const { return m_imp->get_num_steps(); } -void model_evaluator::cancel() { +void model_evaluator::set_cancel(bool f) { #pragma omp critical (model_evaluator) { - m_imp->cancel(); + m_imp->set_cancel(f); } } diff --git a/src/model/model_evaluator.h b/src/model/model_evaluator.h index aad06739b..1a7469c6c 100644 --- a/src/model/model_evaluator.h +++ b/src/model/model_evaluator.h @@ -41,7 +41,9 @@ public: void operator()(expr * t, expr_ref & r); - void cancel(); + void set_cancel(bool f); + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } void cleanup(params_ref const & p = params_ref()); void reset(params_ref const & p = params_ref()); diff --git a/src/muz_qe/dl_context.h b/src/muz_qe/dl_context.h index f84050e68..d3309beb5 100644 --- a/src/muz_qe/dl_context.h +++ b/src/muz_qe/dl_context.h @@ -349,6 +349,7 @@ namespace datalog { void cancel(); void cleanup(); + void reset_cancel() { cleanup(); } /** \brief check if query 'q' is satisfied under asserted rules and background. diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index c99c362bd..0698f4eaf 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -390,6 +390,7 @@ namespace smt2 { void check_float(char const * msg) { if (!curr_is_float()) throw parser_exception(msg); } void error(unsigned line, unsigned pos, char const * msg) { + m_ctx.reset_cancel(); if (use_vs_format()) { m_ctx.diagnostic_stream() << "Z3(" << line << ", " << pos << "): ERROR: " << msg; if (msg[strlen(msg)-1] != '\n') diff --git a/src/smt/smt_kernel.cpp b/src/smt/smt_kernel.cpp index 779c68625..8ecd079bf 100644 --- a/src/smt/smt_kernel.cpp +++ b/src/smt/smt_kernel.cpp @@ -253,12 +253,10 @@ namespace smt { } lbool kernel::setup_and_check() { - set_cancel(false); return m_imp->setup_and_check(); } lbool kernel::check(unsigned num_assumptions, expr * const * assumptions) { - set_cancel(false); lbool r = m_imp->check(num_assumptions, assumptions); TRACE("smt_kernel", tout << "check result: " << r << "\n";); return r; diff --git a/src/tactic/tactic.cpp b/src/tactic/tactic.cpp index 4bf9e48f4..198872cf5 100644 --- a/src/tactic/tactic.cpp +++ b/src/tactic/tactic.cpp @@ -175,7 +175,6 @@ tactic * mk_fail_if_undecided_tactic() { void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { t.reset_statistics(); - t.reset_cancel(); try { t(in, result, mc, pc, core); t.cleanup(); diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 785a9d82e..ca66b7a14 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -116,7 +116,6 @@ protected: m_t2->set_cancel(f); } - template tactic * translate_core(ast_manager & m) { tactic * new_t1 = m_t1->translate(m); diff --git a/src/util/cancel_eh.h b/src/util/cancel_eh.h index 74c5040a2..0401e6f03 100644 --- a/src/util/cancel_eh.h +++ b/src/util/cancel_eh.h @@ -29,6 +29,7 @@ class cancel_eh : public event_handler { T & m_obj; public: cancel_eh(T & o):m_obj(o) {} + ~cancel_eh() { m_obj.reset_cancel(); } virtual void operator()() { m_obj.cancel(); } From 9674f511b3c1a7fe68a7888e16d298fb0748f5e4 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 20:46:04 -0800 Subject: [PATCH 42/57] Fix scoped_timer for Linux. Nested timers were misbehaving, and it was not possible to create timers in more than one thread Signed-off-by: Leonardo de Moura --- src/util/scoped_timer.cpp | 42 +++++++-------------------------------- 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/src/util/scoped_timer.cpp b/src/util/scoped_timer.cpp index d475e5489..d0a79cec6 100644 --- a/src/util/scoped_timer.cpp +++ b/src/util/scoped_timer.cpp @@ -73,9 +73,6 @@ struct scoped_timer::imp { pthread_cond_t m_condition_var; #elif defined(_LINUX_) || defined(_FREEBSD_) // Linux & FreeBSD - static void * g_timer; - void (*m_old_handler)(int); - void * m_old_timer; timer_t m_timerid; #else // Other @@ -128,8 +125,9 @@ struct scoped_timer::imp { return st; } #elif defined(_LINUX_) || defined(_FREEBSD_) - static void sig_handler(int) { - static_cast(g_timer)->m_eh->operator()(); + static void sig_handler(union sigval s) { + void * ptr = s.sival_ptr; + static_cast(ptr)->m_eh->operator()(); } #else // Other @@ -156,23 +154,11 @@ struct scoped_timer::imp { throw default_exception("failed to start timer thread"); #elif defined(_LINUX_) || defined(_FREEBSD_) // Linux & FreeBSD - if (omp_in_parallel()) { - // It doesn't work in with more than one thread. - // SIGEV_SIGNAL: the event is handled by the process not by the thread that installed the handler. - // SIGEV_THREAD: the event is handled by a new thread (Z3 crashes with this configuration). - // - // It seems the way to go is SIGEV_SIGNAL, but I have to find a way to identify the thread the event is meant to. - return; - } - m_old_timer = g_timer; - g_timer = this; - m_old_handler = signal(SIG, sig_handler); - struct sigevent sev; memset(&sev, 0, sizeof(sigevent)); - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIG; - sev.sigev_value.sival_ptr = &m_timerid; + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_value.sival_ptr = this; + sev.sigev_notify_function = sig_handler; if (timer_create(CLOCKID, &sev, &m_timerid) == -1) throw default_exception("failed to create timer"); @@ -182,6 +168,7 @@ struct scoped_timer::imp { its.it_value.tv_nsec = nano % 1000000000ull; its.it_interval.tv_sec = 0; // timer experies once its.it_interval.tv_nsec = 0; + if (timer_settime(m_timerid, 0, &its, NULL) == -1) throw default_exception("failed to set timer"); #else @@ -203,12 +190,7 @@ struct scoped_timer::imp { throw default_exception("failed to destroy pthread attributes object"); #elif defined(_LINUX_) || defined(_FREEBSD_) // Linux & FreeBSD - if (omp_in_parallel()) - return; // see comments in the constructor. timer_delete(m_timerid); - if (m_old_handler != SIG_ERR) - signal(SIG, m_old_handler); - g_timer = m_old_timer; #else // Other Platforms #endif @@ -216,16 +198,6 @@ struct scoped_timer::imp { }; -#if defined(_WINDOWS) || defined(_CYGWIN) -#elif defined(__APPLE__) && defined(__MACH__) -// Mac OS X -#elif defined(_LINUX_) || defined(_FREEBSD_) -// Linux & FreeBSD -void * scoped_timer::imp::g_timer = 0; -#else -// Other platforms -#endif - scoped_timer::scoped_timer(unsigned ms, event_handler * eh) { if (ms != UINT_MAX) m_imp = alloc(imp, ms, eh); From 08789b69d4e885446e92689ed34130a0b912b656 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 20:56:20 -0800 Subject: [PATCH 43/57] Fix warning on FreeBSD Signed-off-by: Leonardo de Moura --- src/ast/rewriter/float_rewriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 9678af216..482e280e3 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -443,4 +443,4 @@ br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result br_status float_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) { return BR_FAILED; -} \ No newline at end of file +} From 83f7b294cce2b832a8823dc6f91ca29bb0f09f83 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 17 Dec 2012 21:05:04 -0800 Subject: [PATCH 44/57] Update RELEASE_NOTES with latest bug fix Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 75f7e42be..5f2478dff 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -47,6 +47,8 @@ Version 4.3.2 - Fixed bug reported at http://stackoverflow.com/questions/13923316/unprintable-solver-model +- Fixed timers on Linux and FreeBSD. + Version 4.3.1 ============= From 4f0d5a5756ab144005f6a288e7ef36da18b90edd Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 18 Dec 2012 07:27:20 -0800 Subject: [PATCH 45/57] Add thanks to Etienne Kneuss Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 5f2478dff..234ba03fb 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -30,7 +30,7 @@ Version 4.3.2 - Fixed problem in the pretty printer. It was not introducing quotes for attribute names such as |foo:10|. -- Fixed bug when using assumptions (Thanks to Philippe Suter) +- Fixed bug when using assumptions (Thanks to Philippe Suter and Etienne Kneuss) Consider the following example: (assert F) (check-sat a) From cec328cfdc0deadcc50d412e1cc88b9ed1bab1c2 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 18 Dec 2012 14:44:51 -0800 Subject: [PATCH 46/57] Add get_sort(expr * n) function that does not depend on ast_manager. Move power_of_two to rational class. Add arith_recognizers and bv_recognizers classes. The two new classes contain the 'read-only' methods from arith_util and bv_util. Signed-off-by: Leonardo de Moura --- src/ast/arith_decl_plugin.cpp | 24 +-- src/ast/arith_decl_plugin.h | 69 ++++--- src/ast/ast.cpp | 39 ++-- src/ast/ast.h | 4 +- src/ast/bv_decl_plugin.cpp | 177 +++++++++--------- src/ast/bv_decl_plugin.h | 142 +++++++------- src/ast/rewriter/bit_blaster/bit_blaster.h | 2 +- .../bit_blaster/bit_blaster_rewriter.cpp | 2 +- src/ast/rewriter/bv_rewriter.cpp | 48 ++--- src/ast/simplifier/bv_simplifier_plugin.cpp | 40 ++-- src/ast/simplifier/bv_simplifier_plugin.h | 2 +- src/tactic/arith/bv2int_rewriter.cpp | 2 +- src/tactic/arith/nla2bv_tactic.cpp | 2 +- src/tactic/arith/pb2bv_tactic.cpp | 4 +- src/tactic/core/elim_uncnstr_tactic.cpp | 6 +- src/util/rational.cpp | 26 +++ src/util/rational.h | 7 +- 17 files changed, 314 insertions(+), 282 deletions(-) diff --git a/src/ast/arith_decl_plugin.cpp b/src/ast/arith_decl_plugin.cpp index a89cc18d0..093f6b346 100644 --- a/src/ast/arith_decl_plugin.cpp +++ b/src/ast/arith_decl_plugin.cpp @@ -573,18 +573,7 @@ expr * arith_decl_plugin::get_some_value(sort * s) { return mk_numeral(rational(0), s == m_int_decl); } -arith_util::arith_util(ast_manager & m): - m_manager(m), - m_afid(m.get_family_id("arith")), - m_plugin(0) { -} - -void arith_util::init_plugin() { - SASSERT(m_plugin == 0); - m_plugin = static_cast(m_manager.get_plugin(m_afid)); -} - -bool arith_util::is_numeral(expr const * n, rational & val, bool & is_int) const { +bool arith_recognizers::is_numeral(expr const * n, rational & val, bool & is_int) const { if (!is_app_of(n, m_afid, OP_NUM)) return false; func_decl * decl = to_app(n)->get_decl(); @@ -593,6 +582,17 @@ bool arith_util::is_numeral(expr const * n, rational & val, bool & is_int) const return true; } +arith_util::arith_util(ast_manager & m): + arith_recognizers(m.get_family_id("arith")), + m_manager(m), + m_plugin(0) { +} + +void arith_util::init_plugin() { + SASSERT(m_plugin == 0); + m_plugin = static_cast(m_manager.get_plugin(m_afid)); +} + bool arith_util::is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val) { if (!is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM)) return false; diff --git a/src/ast/arith_decl_plugin.h b/src/ast/arith_decl_plugin.h index c39768d4c..e63e866c3 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -187,36 +187,24 @@ public: virtual void set_cancel(bool f); }; -class arith_util { - ast_manager & m_manager; +/** + \brief Procedures for recognizing arithmetic expressions. + We don't need access to ast_manager, and operations can be simultaneously + executed in different threads. +*/ +class arith_recognizers { +protected: family_id m_afid; - arith_decl_plugin * m_plugin; - - void init_plugin(); - - arith_decl_plugin & plugin() const { - if (!m_plugin) const_cast(this)->init_plugin(); - SASSERT(m_plugin != 0); - return *m_plugin; - } - public: - arith_util(ast_manager & m); + arith_recognizers(family_id id):m_afid(id) {} - ast_manager & get_manager() const { return m_manager; } family_id get_family_id() const { return m_afid; } - algebraic_numbers::manager & am() { - return plugin().am(); - } - bool is_arith_expr(expr const * n) const { return is_app(n) && to_app(n)->get_family_id() == m_afid; } + bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); } bool is_numeral(expr const * n, rational & val, bool & is_int) const; bool is_numeral(expr const * n, rational & val) const { bool is_int; return is_numeral(n, val, is_int); } bool is_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_NUM); } - bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); } - bool is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val); - algebraic_numbers::anum const & to_irrational_algebraic_numeral(expr const * n); bool is_zero(expr const * n) const { rational val; return is_numeral(n, val) && val.is_zero(); } bool is_minus_one(expr * n) const { rational tmp; return is_numeral(n, tmp) && tmp.is_minus_one(); } // return true if \c n is a term of the form (* -1 r) @@ -227,6 +215,7 @@ public: } return false; } + bool is_le(expr const * n) const { return is_app_of(n, m_afid, OP_LE); } bool is_ge(expr const * n) const { return is_app_of(n, m_afid, OP_GE); } bool is_lt(expr const * n) const { return is_app_of(n, m_afid, OP_LT); } @@ -245,14 +234,13 @@ public: bool is_power(expr const * n) const { return is_app_of(n, m_afid, OP_POWER); } bool is_int(sort const * s) const { return is_sort_of(s, m_afid, INT_SORT); } - bool is_int(expr const * n) const { return is_int(m_manager.get_sort(n)); } + bool is_int(expr const * n) const { return is_int(get_sort(n)); } bool is_real(sort const * s) const { return is_sort_of(s, m_afid, REAL_SORT); } - bool is_real(expr const * n) const { return is_real(m_manager.get_sort(n)); } + bool is_real(expr const * n) const { return is_real(get_sort(n)); } bool is_int_real(sort const * s) const { return s->get_family_id() == m_afid; } - bool is_int_real(expr const * n) const { return is_int_real(m_manager.get_sort(n)); } + bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); } MATCH_UNARY(is_uminus); - MATCH_BINARY(is_sub); MATCH_BINARY(is_add); MATCH_BINARY(is_mul); @@ -265,6 +253,34 @@ public: MATCH_BINARY(is_div); MATCH_BINARY(is_idiv); + bool is_pi(expr * arg) { return is_app_of(arg, m_afid, OP_PI); } + bool is_e(expr * arg) { return is_app_of(arg, m_afid, OP_E); } +}; + +class arith_util : public arith_recognizers { + ast_manager & m_manager; + arith_decl_plugin * m_plugin; + + void init_plugin(); + + arith_decl_plugin & plugin() const { + if (!m_plugin) const_cast(this)->init_plugin(); + SASSERT(m_plugin != 0); + return *m_plugin; + } + +public: + arith_util(ast_manager & m); + + ast_manager & get_manager() const { return m_manager; } + + algebraic_numbers::manager & am() { + return plugin().am(); + } + + bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); } + bool is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val); + algebraic_numbers::anum const & to_irrational_algebraic_numeral(expr const * n); sort * mk_int() { return m_manager.mk_sort(m_afid, INT_SORT); } sort * mk_real() { return m_manager.mk_sort(m_afid, REAL_SORT); } @@ -320,9 +336,6 @@ public: app * mk_acosh(expr * arg) { return m_manager.mk_app(m_afid, OP_ACOSH, arg); } app * mk_atanh(expr * arg) { return m_manager.mk_app(m_afid, OP_ATANH, arg); } - bool is_pi(expr * arg) { return is_app_of(arg, m_afid, OP_PI); } - bool is_e(expr * arg) { return is_app_of(arg, m_afid, OP_E); } - app * mk_pi() { return plugin().mk_pi(); } app * mk_e() { return plugin().mk_e(); } diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 3fb422a2e..94637bbdd 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -374,6 +374,31 @@ quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sort memcpy(const_cast(get_no_patterns()), no_patterns, sizeof(expr *) * num_no_patterns); } +// ----------------------------------- +// +// Auxiliary functions +// +// ----------------------------------- + +sort * get_sort(expr const * n) { + while (true) { + switch(n->get_kind()) { + case AST_APP: + return to_app(n)->get_decl()->get_range(); + case AST_VAR: + return to_var(n)->get_sort(); + case AST_QUANTIFIER: + // The sort of the quantifier is the sort of the nested expression. + // This code assumes the given expression is well-sorted. + n = to_quantifier(n)->get_expr(); + break; + default: + UNREACHABLE(); + return 0; + } + } +} + // ----------------------------------- // // AST hash-consing @@ -1495,20 +1520,6 @@ void ast_manager::register_plugin(family_id id, decl_plugin * plugin) { plugin->set_manager(this, id); } -sort * ast_manager::get_sort(expr const * n) const { - switch(n->get_kind()) { - case AST_APP: - return to_app(n)->get_decl()->get_range(); - case AST_VAR: - return to_var(n)->get_sort(); - case AST_QUANTIFIER: - return m_bool_sort; - default: - UNREACHABLE(); - return 0; - } -} - bool ast_manager::is_bool(expr const * n) const { return get_sort(n) == m_bool_sort; } diff --git a/src/ast/ast.h b/src/ast/ast.h index 6af95e3a7..f899ed241 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1287,6 +1287,8 @@ inline bool has_labels(expr const * n) { else return false; } +sort * get_sort(expr const * n); + // ----------------------------------- // // Get Some Value functor @@ -1548,7 +1550,7 @@ protected: } public: - sort * get_sort(expr const * n) const; + sort * get_sort(expr const * n) const { return ::get_sort(n); } void check_sort(func_decl const * decl, unsigned num_args, expr * const * args) const; void check_sorts_core(ast const * n) const; bool check_sorts(ast const * n) const; diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index fd15ca681..434bdaa11 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -41,26 +41,6 @@ bv_decl_plugin::bv_decl_plugin(): m_int_sort(0) { } -void bv_decl_plugin::mk_table_upto(unsigned n) { - if (m_powers.empty()) { - m_powers.push_back(rational(1)); - } - unsigned sz = m_powers.size(); - rational curr = m_powers[sz - 1]; - rational two(2); - for (unsigned i = sz; i <= n; i++) { - curr *= two; - m_powers.push_back(curr); - } -} - -rational bv_decl_plugin::power_of_two(unsigned n) const { - if (n >= m_powers.size()) { - const_cast(this)->mk_table_upto(n + 1); - } - return m_powers[n]; -} - void bv_decl_plugin::set_manager(ast_manager * m, family_id id) { decl_plugin::set_manager(m, id); @@ -169,7 +149,7 @@ void bv_decl_plugin::mk_bv_sort(unsigned bv_size) { sz = sort_size::mk_very_big(); } else { - sz = sort_size(power_of_two(bv_size)); + sz = sort_size(rational::power_of_two(bv_size)); } m_bv_sorts[bv_size] = m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p)); m_manager->inc_ref(m_bv_sorts[bv_size]); @@ -436,7 +416,7 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const // This cannot be enforced now, since some Z3 modules try to generate these invalid numerals. // After SMT-COMP, I should find all offending modules. // For now, I will just simplify the numeral here. - parameter p0(mod(parameters[0].get_rational(), power_of_two(bv_size))); + parameter p0(mod(parameters[0].get_rational(), rational::power_of_two(bv_size))); parameter ps[2] = { p0, parameters[1] }; sort * bv = get_bv_sort(bv_size); return m_manager->mk_const_decl(m_bv_sym, bv, func_decl_info(m_family_id, OP_BV_NUM, num_parameters, ps)); @@ -621,7 +601,7 @@ void bv_decl_plugin::get_offset_term(app * a, expr * & t, rational & offset) con offset = decl->get_parameter(0).get_rational(); sz = decl->get_parameter(1).get_int(); t = a->get_arg(1); - offset = mod(offset, power_of_two(sz)); + offset = mod(offset, rational::power_of_two(sz)); } else { t = a; @@ -729,37 +709,104 @@ expr * bv_decl_plugin::get_some_value(sort * s) { return m_manager->mk_app(m_family_id, OP_BV_NUM, 2, p, 0, 0); } -bv_util::bv_util(ast_manager & m): - m_manager(m) { - SASSERT(m.has_plugin(symbol("bv"))); - m_plugin = static_cast(m.get_plugin(m.get_family_id("bv"))); -} - -rational bv_util::norm(rational const & val, unsigned bv_size, bool is_signed) const { - rational r = mod(val, power_of_two(bv_size)); +rational bv_recognizers::norm(rational const & val, unsigned bv_size, bool is_signed) const { + rational r = mod(val, rational::power_of_two(bv_size)); SASSERT(!r.is_neg()); if (is_signed) { - if (r >= power_of_two(bv_size - 1)) { - r -= power_of_two(bv_size); + if (r >= rational::power_of_two(bv_size - 1)) { + r -= rational::power_of_two(bv_size); } - if (r < -power_of_two(bv_size - 1)) { - r += power_of_two(bv_size); + if (r < -rational::power_of_two(bv_size - 1)) { + r += rational::power_of_two(bv_size); } } return r; } -bool bv_util::has_sign_bit(rational const & n, unsigned bv_size) const { +bool bv_recognizers::has_sign_bit(rational const & n, unsigned bv_size) const { SASSERT(bv_size > 0); rational m = norm(n, bv_size, false); - rational p = power_of_two(bv_size - 1); + rational p = rational::power_of_two(bv_size - 1); return m >= p; } -bool bv_util::is_bv_sort(sort const * s) const { +bool bv_recognizers::is_bv_sort(sort const * s) const { return (s->get_family_id() == get_fid() && s->get_decl_kind() == BV_SORT && s->get_num_parameters() == 1); } +bool bv_recognizers::is_numeral(expr const * n, rational & val, unsigned & bv_size) const { + if (!is_app_of(n, get_fid(), OP_BV_NUM)) { + return false; + } + func_decl * decl = to_app(n)->get_decl(); + val = decl->get_parameter(0).get_rational(); + bv_size = decl->get_parameter(1).get_int(); + return true; +} + +bool bv_recognizers::is_allone(expr const * e) const { + rational r; + unsigned bv_size; + if (!is_numeral(e, r, bv_size)) { + return false; + } + bool result = (r == rational::power_of_two(bv_size) - rational(1)); + TRACE("is_allone", tout << r << " " << result << "\n";); + return result; +} + +bool bv_recognizers::is_zero(expr const * n) const { + if (!is_app_of(n, get_fid(), OP_BV_NUM)) { + return false; + } + func_decl * decl = to_app(n)->get_decl(); + return decl->get_parameter(0).get_rational().is_zero(); +} + +bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) { + if (!is_extract(e)) return false; + low = get_extract_low(e); + high = get_extract_high(e); + b = to_app(e)->get_arg(0); + return true; +} + +bool bv_recognizers::is_bv2int(expr const* e, expr*& r) { + if (!is_bv2int(e)) return false; + r = to_app(e)->get_arg(0); + return true; +} + +bool bv_recognizers::mult_inverse(rational const & n, unsigned bv_size, rational & result) { + if (n.is_one()) { + result = n; + return true; + } + + if (!mod(n, rational(2)).is_one()) { + return false; + } + + rational g; + rational x; + rational y; + g = gcd(n, rational::power_of_two(bv_size), x, y); + if (x.is_neg()) { + x = mod(x, rational::power_of_two(bv_size)); + } + SASSERT(x.is_pos()); + SASSERT(mod(x * n, rational::power_of_two(bv_size)).is_one()); + result = x; + return true; +} + +bv_util::bv_util(ast_manager & m): + bv_recognizers(m.get_family_id(symbol("bv"))), + m_manager(m) { + SASSERT(m.has_plugin(symbol("bv"))); + m_plugin = static_cast(m.get_plugin(m.get_family_id("bv"))); +} + app * bv_util::mk_numeral(rational const & val, sort* s) { if (!is_bv_sort(s)) { return 0; @@ -774,65 +821,11 @@ app * bv_util::mk_numeral(rational const & val, unsigned bv_size) { return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0); } -bool bv_util::is_numeral(expr const * n, rational & val, unsigned & bv_size) const { - if (!is_app_of(n, get_fid(), OP_BV_NUM)) { - return false; - } - func_decl * decl = to_app(n)->get_decl(); - val = decl->get_parameter(0).get_rational(); - bv_size = decl->get_parameter(1).get_int(); - return true; -} - - -bool bv_util::is_allone(expr const * e) const { - rational r; - unsigned bv_size; - if (!is_numeral(e, r, bv_size)) { - return false; - } - bool result = (r == power_of_two(bv_size) - rational(1)); - TRACE("is_allone", tout << r << " " << result << "\n";); - return result; -} - -bool bv_util::is_zero(expr const * n) const { - if (!is_app_of(n, get_fid(), OP_BV_NUM)) { - return false; - } - func_decl * decl = to_app(n)->get_decl(); - return decl->get_parameter(0).get_rational().is_zero(); -} - sort * bv_util::mk_sort(unsigned bv_size) { parameter p[1] = { parameter(bv_size) }; return m_manager.mk_sort(get_fid(), BV_SORT, 1, p); } - -bool bv_util::mult_inverse(rational const & n, unsigned bv_size, rational & result) { - if (n.is_one()) { - result = n; - return true; - } - - if (!mod(n, rational(2)).is_one()) { - return false; - } - - rational g; - rational x; - rational y; - g = gcd(n, power_of_two(bv_size), x, y); - if (x.is_neg()) { - x = mod(x, power_of_two(bv_size)); - } - SASSERT(x.is_pos()); - SASSERT(mod(x * n, power_of_two(bv_size)).is_one()); - result = x; - return true; -} - app * bv_util::mk_bv2int(expr* e) { sort* s = m_manager.mk_sort(m_manager.get_family_id("arith"), INT_SORT); parameter p(s); diff --git a/src/ast/bv_decl_plugin.h b/src/ast/bv_decl_plugin.h index 34f2baf6b..8ea90f844 100644 --- a/src/ast/bv_decl_plugin.h +++ b/src/ast/bv_decl_plugin.h @@ -127,9 +127,6 @@ inline func_decl * get_div0_decl(ast_manager & m, func_decl * decl) { class bv_decl_plugin : public decl_plugin { protected: - vector m_powers; - void mk_table_upto(unsigned n); - symbol m_bv_sym; symbol m_concat_sym; symbol m_sign_extend_sym; @@ -245,8 +242,6 @@ protected: public: bv_decl_plugin(); - rational power_of_two(unsigned n) const; - virtual ~bv_decl_plugin() {} virtual void finalize(); @@ -273,7 +268,70 @@ public: virtual expr * get_some_value(sort * s); }; -class bv_util { +class bv_recognizers { + family_id m_afid; +public: + bv_recognizers(family_id fid):m_afid(fid) {} + + family_id get_fid() const { return m_afid; } + family_id get_family_id() const { return get_fid(); } + + bool is_numeral(expr const * n, rational & val, unsigned & bv_size) const; + bool is_numeral(expr const * n) const { return is_app_of(n, get_fid(), OP_BV_NUM); } + bool is_allone(expr const * e) const; + bool is_zero(expr const * e) const; + bool is_bv_sort(sort const * s) const; + bool is_bv(expr const* e) const { return is_bv_sort(get_sort(e)); } + + bool is_concat(expr const * e) const { return is_app_of(e, get_fid(), OP_CONCAT); } + bool is_extract(func_decl const * f) const { return is_decl_of(f, get_fid(), OP_EXTRACT); } + bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); } + unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); } + unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); } + unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); } + unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); } + bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b); + bool is_bv2int(expr const * e, expr * & r); + bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); } + bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); } + bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); } + bool is_bv_neg(expr const * e) const { return is_app_of(e, get_fid(), OP_BNEG); } + bool is_bv_sdiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BSDIV); } + bool is_bv_udiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BUDIV); } + bool is_bv_srem(expr const * e) const { return is_app_of(e, get_fid(), OP_BSREM); } + bool is_bv_urem(expr const * e) const { return is_app_of(e, get_fid(), OP_BUREM); } + bool is_bv_smod(expr const * e) const { return is_app_of(e, get_fid(), OP_BSMOD); } + bool is_bv_and(expr const * e) const { return is_app_of(e, get_fid(), OP_BAND); } + bool is_bv_or(expr const * e) const { return is_app_of(e, get_fid(), OP_BOR); } + bool is_bv_xor(expr const * e) const { return is_app_of(e, get_fid(), OP_BXOR); } + bool is_bv_nand(expr const * e) const { return is_app_of(e, get_fid(), OP_BNAND); } + bool is_bv_nor(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOR); } + bool is_bv_not(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOT); } + bool is_bv_ule(expr const * e) const { return is_app_of(e, get_fid(), OP_ULEQ); } + bool is_bv_sle(expr const * e) const { return is_app_of(e, get_fid(), OP_SLEQ); } + bool is_bit2bool(expr const * e) const { return is_app_of(e, get_fid(), OP_BIT2BOOL); } + bool is_bv2int(expr const* e) const { return is_app_of(e, get_fid(), OP_BV2INT); } + bool is_int2bv(expr const* e) const { return is_app_of(e, get_fid(), OP_INT2BV); } + bool is_mkbv(expr const * e) const { return is_app_of(e, get_fid(), OP_MKBV); } + bool is_bv_ashr(expr const * e) const { return is_app_of(e, get_fid(), OP_BASHR); } + bool is_bv_lshr(expr const * e) const { return is_app_of(e, get_fid(), OP_BLSHR); } + bool is_bv_shl(expr const * e) const { return is_app_of(e, get_fid(), OP_BSHL); } + bool is_sign_ext(expr const * e) const { return is_app_of(e, get_fid(), OP_SIGN_EXT); } + + MATCH_BINARY(is_bv_add); + MATCH_BINARY(is_bv_mul); + MATCH_BINARY(is_bv_sle); + MATCH_BINARY(is_bv_ule); + MATCH_BINARY(is_bv_shl); + + rational norm(rational const & val, unsigned bv_size, bool is_signed) const ; + rational norm(rational const & val, unsigned bv_size) const { return norm(val, bv_size, false); } + bool has_sign_bit(rational const & n, unsigned bv_size) const; + bool mult_inverse(rational const & n, unsigned bv_size, rational & result); + +}; + +class bv_util : public bv_recognizers { ast_manager & m_manager; bv_decl_plugin * m_plugin; @@ -282,29 +340,10 @@ public: ast_manager & get_manager() const { return m_manager; } - family_id get_fid() const { return m_plugin->get_family_id(); } - - family_id get_family_id() const { return get_fid(); } - - rational power_of_two(unsigned n) const { return m_plugin->power_of_two(n); } - - rational norm(rational const & val, unsigned bv_size, bool is_signed) const ; - rational norm(rational const & val, unsigned bv_size) const { return norm(val, bv_size, false); } - bool has_sign_bit(rational const & n, unsigned bv_size) const; app * mk_numeral(rational const & val, sort* s); app * mk_numeral(rational const & val, unsigned bv_size); app * mk_numeral(uint64 u, unsigned bv_size) { return mk_numeral(rational(u, rational::ui64()), bv_size); } sort * mk_sort(unsigned bv_size); - bool is_numeral(expr const * n, rational & val, unsigned & bv_size) const; - bool is_numeral(expr const * n) const { - return is_app_of(n, get_fid(), OP_BV_NUM); - } - bool is_allone(expr const * e) const; - bool is_zero(expr const * e) const; - bool is_bv_sort(sort const * s) const; - bool is_bv(expr const* e) const { - return is_bv_sort(m_manager.get_sort(e)); - } unsigned get_bv_size(sort const * s) const { SASSERT(is_bv_sort(s)); @@ -348,59 +387,6 @@ public: app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); } app * mk_bv(unsigned n, expr* const* es) { return m_manager.mk_app(get_fid(), OP_MKBV, n, es); } - - bool is_concat(expr const * e) const { return is_app_of(e, get_fid(), OP_CONCAT); } - bool is_extract(func_decl const * f) const { return is_decl_of(f, get_fid(), OP_EXTRACT); } - bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); } - unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); } - unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); } - unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); } - unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); } - bool is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) { - if (!is_extract(e)) return false; - low = get_extract_low(e); - high = get_extract_high(e); - b = to_app(e)->get_arg(0); - return true; - } - bool is_bv2int(expr const* e, expr*& r) { - if (!is_bv2int(e)) return false; - r = to_app(e)->get_arg(0); - return true; - } - bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); } - bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); } - bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); } - bool is_bv_neg(expr const * e) const { return is_app_of(e, get_fid(), OP_BNEG); } - bool is_bv_sdiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BSDIV); } - bool is_bv_udiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BUDIV); } - bool is_bv_srem(expr const * e) const { return is_app_of(e, get_fid(), OP_BSREM); } - bool is_bv_urem(expr const * e) const { return is_app_of(e, get_fid(), OP_BUREM); } - bool is_bv_smod(expr const * e) const { return is_app_of(e, get_fid(), OP_BSMOD); } - bool is_bv_and(expr const * e) const { return is_app_of(e, get_fid(), OP_BAND); } - bool is_bv_or(expr const * e) const { return is_app_of(e, get_fid(), OP_BOR); } - bool is_bv_xor(expr const * e) const { return is_app_of(e, get_fid(), OP_BXOR); } - bool is_bv_nand(expr const * e) const { return is_app_of(e, get_fid(), OP_BNAND); } - bool is_bv_nor(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOR); } - bool is_bv_not(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOT); } - bool is_bv_ule(expr const * e) const { return is_app_of(e, get_fid(), OP_ULEQ); } - bool is_bv_sle(expr const * e) const { return is_app_of(e, get_fid(), OP_SLEQ); } - bool is_bit2bool(expr const * e) const { return is_app_of(e, get_fid(), OP_BIT2BOOL); } - bool is_bv2int(expr const* e) const { return is_app_of(e, get_fid(), OP_BV2INT); } - bool is_int2bv(expr const* e) const { return is_app_of(e, get_fid(), OP_INT2BV); } - bool is_mkbv(expr const * e) const { return is_app_of(e, get_fid(), OP_MKBV); } - bool is_bv_ashr(expr const * e) const { return is_app_of(e, get_fid(), OP_BASHR); } - bool is_bv_lshr(expr const * e) const { return is_app_of(e, get_fid(), OP_BLSHR); } - bool is_bv_shl(expr const * e) const { return is_app_of(e, get_fid(), OP_BSHL); } - bool is_sign_ext(expr const * e) const { return is_app_of(e, get_fid(), OP_SIGN_EXT); } - - MATCH_BINARY(is_bv_add); - MATCH_BINARY(is_bv_mul); - MATCH_BINARY(is_bv_sle); - MATCH_BINARY(is_bv_ule); - MATCH_BINARY(is_bv_shl); - - bool mult_inverse(rational const & n, unsigned bv_size, rational & result); }; #endif /* _BV_DECL_PLUGIN_H_ */ diff --git a/src/ast/rewriter/bit_blaster/bit_blaster.h b/src/ast/rewriter/bit_blaster/bit_blaster.h index 42444aebc..7b317c6cb 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster.h +++ b/src/ast/rewriter/bit_blaster/bit_blaster.h @@ -36,7 +36,7 @@ public: bit_blaster_cfg(bv_util & u, bit_blaster_params const & p, basic_simplifier_plugin & _s); ast_manager & m() const { return m_util.get_manager(); } - numeral power(unsigned n) const { return m_util.power_of_two(n); } + numeral power(unsigned n) const { return rational::power_of_two(n); } void mk_xor(expr * a, expr * b, expr_ref & r) { s.mk_xor(a, b, r); } void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r); void mk_carry(expr * a, expr * b, expr * c, expr_ref & r); diff --git a/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp b/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp index 1fd83e91f..80d319377 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp +++ b/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp @@ -32,7 +32,7 @@ struct blaster_cfg { blaster_cfg(bool_rewriter & r, bv_util & u):m_rewriter(r), m_util(u) {} ast_manager & m() const { return m_util.get_manager(); } - numeral power(unsigned n) const { return m_util.power_of_two(n); } + numeral power(unsigned n) const { return rational::power_of_two(n); } void mk_xor(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_xor(a, b, r); } void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r) { expr_ref tmp(m()); diff --git a/src/ast/rewriter/bv_rewriter.cpp b/src/ast/rewriter/bv_rewriter.cpp index 5fd562676..f8ff27337 100644 --- a/src/ast/rewriter/bv_rewriter.cpp +++ b/src/ast/rewriter/bv_rewriter.cpp @@ -283,12 +283,12 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref if (is_num1 || is_num2) { if (is_signed) { - lower = - m_util.power_of_two(sz - 1); - upper = m_util.power_of_two(sz - 1) - numeral(1); + lower = - rational::power_of_two(sz - 1); + upper = rational::power_of_two(sz - 1) - numeral(1); } else { lower = numeral(0); - upper = m_util.power_of_two(sz) - numeral(1); + upper = rational::power_of_two(sz) - numeral(1); } } @@ -387,14 +387,14 @@ br_status bv_rewriter::mk_extract(unsigned high, unsigned low, expr * arg, expr_ if (is_numeral(arg, v, sz)) { sz = high - low + 1; if (v.is_neg()) - mod(v, m_util.power_of_two(sz), v); + mod(v, rational::power_of_two(sz), v); if (v.is_uint64()) { uint64 u = v.get_uint64(); uint64 e = shift_right(u, low) & (shift_left(1ull, sz) - 1ull); result = mk_numeral(numeral(e, numeral::ui64()), sz); return BR_DONE; } - div(v, m_util.power_of_two(low), v); + div(v, rational::power_of_two(low), v); result = mk_numeral(v, sz); return BR_DONE; } @@ -519,7 +519,7 @@ br_status bv_rewriter::mk_bv_shl(expr * arg1, expr * arg2, expr_ref & result) { SASSERT(r2 < numeral(bv_size)); SASSERT(r2.is_unsigned()); - r1 = m_util.norm(r1 * m_util.power_of_two(r2.get_unsigned()), bv_size); + r1 = m_util.norm(r1 * rational::power_of_two(r2.get_unsigned()), bv_size); result = mk_numeral(r1, bv_size); return BR_DONE; } @@ -567,7 +567,7 @@ br_status bv_rewriter::mk_bv_lshr(expr * arg1, expr * arg2, expr_ref & result) { SASSERT(r2.is_unsigned()); unsigned sh = r2.get_unsigned(); - div(r1, m_util.power_of_two(sh), r1); + div(r1, rational::power_of_two(sh), r1); result = mk_numeral(r1, bv_size); return BR_DONE; } @@ -626,7 +626,7 @@ br_status bv_rewriter::mk_bv_ashr(expr * arg1, expr * arg2, expr_ref & result) { if (is_num1 && is_num2 && numeral(bv_size) <= r2) { if (m_util.has_sign_bit(r1, bv_size)) - result = mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size); + result = mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size); else result = mk_numeral(0, bv_size); return BR_DONE; @@ -635,7 +635,7 @@ br_status bv_rewriter::mk_bv_ashr(expr * arg1, expr * arg2, expr_ref & result) { if (is_num1 && is_num2) { SASSERT(r2 < numeral(bv_size)); bool sign = m_util.has_sign_bit(r1, bv_size); - div(r1, m_util.power_of_two(r2.get_unsigned()), r1); + div(r1, rational::power_of_two(r2.get_unsigned()), r1); if (sign) { // pad ones. numeral p(1); @@ -697,7 +697,7 @@ br_status bv_rewriter::mk_bv_sdiv_core(expr * arg1, expr * arg2, bool hi_div0, e // The "hardware interpretation" for (bvsdiv x 0) is (ite (bvslt x #x0000) #x0001 #xffff) result = m().mk_ite(m().mk_app(get_fid(), OP_SLT, arg1, mk_numeral(0, bv_size)), mk_numeral(1, bv_size), - mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size)); + mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size)); return BR_REWRITE2; } } @@ -746,7 +746,7 @@ br_status bv_rewriter::mk_bv_udiv_core(expr * arg1, expr * arg2, bool hi_div0, e } else { // The "hardware interpretation" for (bvudiv x 0) is #xffff - result = mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size); + result = mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size); return BR_DONE; } @@ -845,7 +845,7 @@ bool bv_rewriter::is_minus_one_core(expr * arg) const { numeral r; unsigned bv_size; if (is_numeral(arg, r, bv_size)) { - return r == (m_util.power_of_two(bv_size) - numeral(1)); + return r == (rational::power_of_two(bv_size) - numeral(1)); } return false; } @@ -924,7 +924,7 @@ br_status bv_rewriter::mk_bv_urem_core(expr * arg1, expr * arg2, bool hi_div0, e if (is_x_minus_one(arg1, x) && x == arg2) { bv_size = get_bv_size(arg1); expr * x_minus_1 = arg1; - expr * minus_one = mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size); + expr * minus_one = mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size); result = m().mk_ite(m().mk_eq(x, mk_numeral(0, bv_size)), m().mk_app(get_fid(), OP_BUREM0, minus_one), x_minus_1); @@ -1068,7 +1068,7 @@ br_status bv_rewriter::mk_concat(unsigned num_args, expr * const * args, expr_re if (i > 0) prev = new_args.back(); if (is_numeral(arg, v1, sz1) && prev != 0 && is_numeral(prev, v2, sz2)) { - v2 *= m_util.power_of_two(sz1); + v2 *= rational::power_of_two(sz1); v2 += v1; new_args.pop_back(); new_args.push_back(mk_numeral(v2, sz1+sz2)); @@ -1137,7 +1137,7 @@ br_status bv_rewriter::mk_sign_extend(unsigned n, expr * arg, expr_ref & result) if (is_numeral(arg, r, bv_size)) { unsigned result_bv_size = bv_size + n; r = m_util.norm(r, bv_size, true); - mod(r, m_util.power_of_two(result_bv_size), r); + mod(r, rational::power_of_two(result_bv_size), r); result = mk_numeral(r, result_bv_size); return BR_DONE; } @@ -1213,7 +1213,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re if (m_util.is_bv_not(arg)) { expr * atom = to_app(arg)->get_arg(0); if (pos_args.is_marked(atom)) { - result = mk_numeral(m_util.power_of_two(sz) - numeral(1), sz); + result = mk_numeral(rational::power_of_two(sz) - numeral(1), sz); return BR_DONE; } else if (neg_args.is_marked(atom)) { @@ -1229,7 +1229,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re continue; } else if (neg_args.is_marked(arg)) { - result = mk_numeral(m_util.power_of_two(sz) - numeral(1), sz); + result = mk_numeral(rational::power_of_two(sz) - numeral(1), sz); return BR_DONE; } pos_args.mark(arg, true); @@ -1237,7 +1237,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re } } - if (v1 == m_util.power_of_two(sz) - numeral(1)) { + if (v1 == rational::power_of_two(sz) - numeral(1)) { result = mk_numeral(v1, sz); return BR_DONE; } @@ -1294,7 +1294,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re } if (i != low) { unsigned num_sz = i - low; - exs.push_back(m_util.mk_numeral(m_util.power_of_two(num_sz) - numeral(1), num_sz)); + exs.push_back(m_util.mk_numeral(rational::power_of_two(num_sz) - numeral(1), num_sz)); low = i; } while (i < sz && mod(v1, two).is_zero()) { @@ -1385,7 +1385,7 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r else if (pos_args.is_marked(atom)) { pos_args.mark(atom, false); merged = true; - v1 = bitwise_xor(v1, m_util.power_of_two(sz) - numeral(1)); + v1 = bitwise_xor(v1, rational::power_of_two(sz) - numeral(1)); } else { neg_args.mark(atom, true); @@ -1399,7 +1399,7 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r else if (neg_args.is_marked(arg)) { neg_args.mark(arg, false); merged = true; - v1 = bitwise_xor(v1, m_util.power_of_two(sz) - numeral(1)); + v1 = bitwise_xor(v1, rational::power_of_two(sz) - numeral(1)); } else { pos_args.mark(arg, true); @@ -1455,7 +1455,7 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r return BR_REWRITE3; } - if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (m_util.power_of_two(sz) - numeral(1))))) + if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1))))) return BR_FAILED; ptr_buffer new_args; @@ -1611,7 +1611,7 @@ br_status bv_rewriter::mk_bv_redand(expr * arg, expr_ref & result) { numeral r; unsigned bv_size; if (is_numeral(arg, r, bv_size)) { - result = (r == m_util.power_of_two(bv_size) - numeral(1)) ? mk_numeral(1, 1) : mk_numeral(0, 1); + result = (r == rational::power_of_two(bv_size) - numeral(1)) ? mk_numeral(1, 1) : mk_numeral(0, 1); return BR_DONE; } return BR_FAILED; @@ -1707,7 +1707,7 @@ bool bv_rewriter::is_zero_bit(expr * x, unsigned idx) { if (is_numeral(x, val, bv_size)) { if (val.is_zero()) return true; - div(val, m_util.power_of_two(idx), val); + div(val, rational::power_of_two(idx), val); return (val % numeral(2)).is_zero(); } if (m_util.is_concat(x)) { diff --git a/src/ast/simplifier/bv_simplifier_plugin.cpp b/src/ast/simplifier/bv_simplifier_plugin.cpp index 2da1f3bab..3ef55baba 100644 --- a/src/ast/simplifier/bv_simplifier_plugin.cpp +++ b/src/ast/simplifier/bv_simplifier_plugin.cpp @@ -76,9 +76,9 @@ app * bv_simplifier_plugin::mk_numeral(numeral const & n) { } app * bv_simplifier_plugin::mk_numeral(numeral const& n, unsigned bv_size) { - numeral r = mod(n, m_util.power_of_two(bv_size)); + numeral r = mod(n, rational::power_of_two(bv_size)); SASSERT(!r.is_neg()); - SASSERT(r < m_util.power_of_two(bv_size)); + SASSERT(r < rational::power_of_two(bv_size)); return m_util.mk_numeral(r, bv_size); } @@ -225,7 +225,7 @@ inline uint64 bv_simplifier_plugin::to_uint64(const numeral & n, unsigned bv_siz SASSERT(bv_size <= 64); numeral tmp = n; if (tmp.is_neg()) { - tmp = mod(tmp, m_util.power_of_two(bv_size)); + tmp = mod(tmp, rational::power_of_two(bv_size)); } SASSERT(tmp.is_nonneg()); SASSERT(tmp.is_uint64()); @@ -235,7 +235,7 @@ inline uint64 bv_simplifier_plugin::to_uint64(const numeral & n, unsigned bv_siz #define MK_BV_OP(_oper_,_binop_) \ rational bv_simplifier_plugin::mk_bv_ ## _oper_(numeral const& a0, numeral const& b0, unsigned sz) { \ rational r(0), a(a0), b(b0); \ - numeral p64 = m_util.power_of_two(64); \ + numeral p64 = rational::power_of_two(64); \ numeral mul(1); \ while (sz > 0) { \ numeral a1 = a % p64; \ @@ -260,7 +260,7 @@ MK_BV_OP(xor,^) rational bv_simplifier_plugin::mk_bv_not(numeral const& a0, unsigned sz) { rational r(0), a(a0), mul(1); - numeral p64 = m_util.power_of_two(64); + numeral p64 = rational::power_of_two(64); while (sz > 0) { numeral a1 = a % p64; uint64 u = ~a1.get_uint64(); @@ -320,12 +320,12 @@ void bv_simplifier_plugin::mk_leq_core(bool is_signed, expr * arg1, expr * arg2, if (is_num1 || is_num2) { if (is_signed) { - lower = - m_util.power_of_two(bv_size - 1); - upper = m_util.power_of_two(bv_size - 1) - numeral(1); + lower = - rational::power_of_two(bv_size - 1); + upper = rational::power_of_two(bv_size - 1) - numeral(1); } else { lower = numeral(0); - upper = m_util.power_of_two(bv_size) - numeral(1); + upper = rational::power_of_two(bv_size) - numeral(1); } } @@ -509,7 +509,7 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar if (m_util.is_numeral(a, r, num_bits)) { if (r.is_neg()) { - r = mod(r, m_util.power_of_two(sz)); + r = mod(r, rational::power_of_two(sz)); } SASSERT(r.is_nonneg()); if (r.is_uint64()) { @@ -520,7 +520,7 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar result = mk_numeral(numeral(e, numeral::ui64()), sz); return true; } - result = mk_numeral(div(r, m_util.power_of_two(low)), sz); + result = mk_numeral(div(r, rational::power_of_two(low)), sz); return true; } // (extract[high:low] (extract[high2:low2] x)) == (extract[high+low2 : low+low2] x) @@ -902,7 +902,7 @@ void bv_simplifier_plugin::mk_concat(unsigned num_args, expr * const * args, exp --i; expr * arg = args[i]; if (is_numeral(arg, arg_val)) { - arg_val *= m_util.power_of_two(shift); + arg_val *= rational::power_of_two(shift); val += arg_val; shift += get_bv_size(arg); TRACE("bv_simplifier_plugin", @@ -1203,7 +1203,7 @@ bool bv_simplifier_plugin::is_minus_one_core(expr * arg) const { unsigned bv_size; if (m_util.is_numeral(arg, r, bv_size)) { numeral minus_one(-1); - minus_one = mod(minus_one, m_util.power_of_two(bv_size)); + minus_one = mod(minus_one, rational::power_of_two(bv_size)); return r == minus_one; } return false; @@ -1295,7 +1295,7 @@ void bv_simplifier_plugin::mk_sign_extend(unsigned n, expr * arg, expr_ref & res if (m_util.is_numeral(arg, r, bv_size)) { unsigned result_bv_size = bv_size + n; r = norm(r, bv_size, true); - r = mod(r, m_util.power_of_two(result_bv_size)); + r = mod(r, rational::power_of_two(result_bv_size)); result = mk_numeral(r, result_bv_size); TRACE("mk_sign_extend", tout << "n: " << n << "\n"; ast_ll_pp(tout, m_manager, arg); tout << "====>\n"; @@ -1373,7 +1373,7 @@ void bv_simplifier_plugin::mk_bv_shl(expr * arg1, expr * arg2, expr_ref & result else if (is_num1 && is_num2) { SASSERT(r2 < rational(bv_size)); SASSERT(r2.is_unsigned()); - result = mk_numeral(r1 * m_util.power_of_two(r2.get_unsigned()), bv_size); + result = mk_numeral(r1 * rational::power_of_two(r2.get_unsigned()), bv_size); } // @@ -1423,7 +1423,7 @@ void bv_simplifier_plugin::mk_bv_lshr(expr * arg1, expr * arg2, expr_ref & resul else if (is_num1 && is_num2) { SASSERT(r2.is_unsigned()); unsigned sh = r2.get_unsigned(); - r1 = div(r1, m_util.power_of_two(sh)); + r1 = div(r1, rational::power_of_two(sh)); result = mk_numeral(r1, bv_size); } // @@ -1804,8 +1804,8 @@ void bv_simplifier_plugin::mk_bv_rotate_left_core(unsigned shift, numeral r, uns result = mk_numeral(r, bv_size); } else { - rational r1 = div(r, m_util.power_of_two(bv_size - shift)); // shift right - rational r2 = (r * m_util.power_of_two(shift)) % m_util.power_of_two(bv_size); // shift left + rational r1 = div(r, rational::power_of_two(bv_size - shift)); // shift right + rational r2 = (r * rational::power_of_two(shift)) % rational::power_of_two(bv_size); // shift left result = mk_numeral(r1 + r2, bv_size); } } @@ -1831,8 +1831,8 @@ void bv_simplifier_plugin::mk_bv_rotate_right_core(unsigned shift, numeral r, un result = mk_numeral(r, bv_size); } else { - rational r1 = div(r, m_util.power_of_two(shift)); // shift right - rational r2 = (r * m_util.power_of_two(bv_size - shift)) % m_util.power_of_two(bv_size); // shift left + rational r1 = div(r, rational::power_of_two(shift)); // shift right + rational r2 = (r * rational::power_of_two(bv_size - shift)) % rational::power_of_two(bv_size); // shift left result = mk_numeral(r1 + r2, bv_size); } } @@ -1935,7 +1935,7 @@ void bv_simplifier_plugin::mk_bv_ashr(expr* arg1, expr* arg2, expr_ref& result) else if (is_num1 && is_num2) { SASSERT(r2 < rational(bv_size)); bool sign = has_sign_bit(r1, bv_size); - r1 = div(r1, m_util.power_of_two(r2.get_unsigned())); + r1 = div(r1, rational::power_of_two(r2.get_unsigned())); if (sign) { // pad ones. rational p(1); diff --git a/src/ast/simplifier/bv_simplifier_plugin.h b/src/ast/simplifier/bv_simplifier_plugin.h index 7f66566b6..36e773de0 100644 --- a/src/ast/simplifier/bv_simplifier_plugin.h +++ b/src/ast/simplifier/bv_simplifier_plugin.h @@ -172,7 +172,7 @@ public: app * mk_numeral(rational const & n, unsigned bv_size); app * mk_numeral(uint64 n, unsigned bv_size) { return mk_numeral(numeral(n, numeral::ui64()), bv_size); } app* mk_bv0(unsigned bv_size) { return m_util.mk_numeral(numeral(0), bv_size); } - rational mk_allone(unsigned bv_size) { return m_util.power_of_two(bv_size) - numeral(1); } + rational mk_allone(unsigned bv_size) { return rational::power_of_two(bv_size) - numeral(1); } bool is_minus_one_core(expr * arg) const; bool is_x_minus_one(expr * arg, expr * & x); void mk_int2bv(expr * arg, sort* range, expr_ref & result); diff --git a/src/tactic/arith/bv2int_rewriter.cpp b/src/tactic/arith/bv2int_rewriter.cpp index 0965f36f2..872981283 100644 --- a/src/tactic/arith/bv2int_rewriter.cpp +++ b/src/tactic/arith/bv2int_rewriter.cpp @@ -544,7 +544,7 @@ bool bv2int_rewriter::is_sbv2int(expr* n, expr_ref& s) { m_bv.is_extract(e2, lo1, hi1, e3) && lo1 == 0 && hi1 == hi-1 && m_arith.is_numeral(t2, k, is_int) && is_int && - k == m_bv.power_of_two(hi) + k == rational::power_of_two(hi) ) { s = e3; return true; diff --git a/src/tactic/arith/nla2bv_tactic.cpp b/src/tactic/arith/nla2bv_tactic.cpp index 188ea7d70..bd5af58f2 100644 --- a/src/tactic/arith/nla2bv_tactic.cpp +++ b/src/tactic/arith/nla2bv_tactic.cpp @@ -253,7 +253,7 @@ class nla2bv_tactic : public tactic { s_bv = m_arith.mk_sub(m_arith.mk_numeral(*up, true), s_bv); } else { - s_bv = m_arith.mk_sub(s_bv, m_arith.mk_numeral(m_bv.power_of_two(num_bits-1), true)); + s_bv = m_arith.mk_sub(s_bv, m_arith.mk_numeral(rational::power_of_two(num_bits-1), true)); } m_trail.push_back(s_bv); diff --git a/src/tactic/arith/pb2bv_tactic.cpp b/src/tactic/arith/pb2bv_tactic.cpp index 8790ca5a7..83a949579 100644 --- a/src/tactic/arith/pb2bv_tactic.cpp +++ b/src/tactic/arith/pb2bv_tactic.cpp @@ -583,7 +583,7 @@ private: return false; // size must be even // I implemented only the easy (and very common) case, where a_i = 2^{n-i-1} and c = 2^n - 1 unsigned n = sz/2; - if (c != m_bv_util.power_of_two(n) - numeral(1)) + if (c != rational::power_of_two(n) - numeral(1)) return false; for (unsigned i = 0; i < n; i++) { monomial const & m1 = p[i*2]; @@ -592,7 +592,7 @@ private: return false; if (m1.m_a != m2.m_a) return false; - if (m1.m_a != m_bv_util.power_of_two(n - i - 1)) + if (m1.m_a != rational::power_of_two(n - i - 1)) return false; } return true; diff --git a/src/tactic/core/elim_uncnstr_tactic.cpp b/src/tactic/core/elim_uncnstr_tactic.cpp index d1dca296a..00e14a41f 100644 --- a/src/tactic/core/elim_uncnstr_tactic.cpp +++ b/src/tactic/core/elim_uncnstr_tactic.cpp @@ -647,9 +647,9 @@ class elim_uncnstr_tactic : public tactic { unsigned bv_sz = m_bv_util.get_bv_size(arg1); rational MAX; if (is_signed) - MAX = m_bv_util.power_of_two(bv_sz - 1) - rational(1); + MAX = rational::power_of_two(bv_sz - 1) - rational(1); else - MAX = m_bv_util.power_of_two(bv_sz) - rational(1); + MAX = rational::power_of_two(bv_sz) - rational(1); app * u; bool is_new = mk_fresh_uncnstr_var_for(f, arg1, arg2, u); app * r = m().mk_or(u, m().mk_eq(t, m_bv_util.mk_numeral(MAX, bv_sz))); @@ -666,7 +666,7 @@ class elim_uncnstr_tactic : public tactic { unsigned bv_sz = m_bv_util.get_bv_size(arg1); rational MIN; if (is_signed) - MIN = -m_bv_util.power_of_two(bv_sz - 1); + MIN = -rational::power_of_two(bv_sz - 1); else MIN = rational(0); app * u; diff --git a/src/util/rational.cpp b/src/util/rational.cpp index 0a91bd8da..122db7217 100644 --- a/src/util/rational.cpp +++ b/src/util/rational.cpp @@ -27,6 +27,31 @@ synch_mpq_manager * rational::g_mpq_manager = 0; rational rational::m_zero(0); rational rational::m_one(1); rational rational::m_minus_one(-1); +vector rational::m_powers_of_two; + +void mk_power_up_to(vector & pws, unsigned n) { + if (pws.empty()) { + pws.push_back(rational(1)); + } + unsigned sz = pws.size(); + rational curr = pws[sz - 1]; + rational two(2); + for (unsigned i = sz; i <= n; i++) { + curr *= two; + pws.push_back(curr); + } +} + +rational rational::power_of_two(unsigned k) { + rational result; + #pragma omp critical (powers_of_two) + { + if (k >= m_powers_of_two.size()) + mk_power_up_to(m_powers_of_two, k+1); + result = m_powers_of_two[k]; + } + return result; +} void rational::initialize() { if (!g_mpq_manager) { @@ -35,6 +60,7 @@ void rational::initialize() { } void rational::finalize() { + m_powers_of_two.finalize(); dealloc(g_mpq_manager); g_mpq_manager = 0; } diff --git a/src/util/rational.h b/src/util/rational.h index f0406f30a..fc03228bf 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -26,14 +26,13 @@ class rational { static rational m_zero; static rational m_one; static rational m_minus_one; - + static vector m_powers_of_two; static synch_mpq_manager * g_mpq_manager; - + static synch_mpq_manager & m() { return *g_mpq_manager; } public: static void initialize(); - static void finalize(); /* ADD_INITIALIZER('rational::initialize();') @@ -272,6 +271,8 @@ public: return result; } + static rational power_of_two(unsigned k); + bool is_power_of_two(unsigned & shift) { return m().is_power_of_two(m_val, shift); } From 3ddb1a85f1c7f166570bfbc3499d9a396db6a817 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 18 Dec 2012 15:00:16 -0800 Subject: [PATCH 47/57] Add basic_recognizers and array_recognizers Signed-off-by: Leonardo de Moura --- src/ast/array_decl_plugin.cpp | 10 ++++++++ src/ast/array_decl_plugin.h | 23 +++++++++++------ src/ast/ast.cpp | 10 ++++++++ src/ast/ast.h | 47 +++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/ast/array_decl_plugin.cpp b/src/ast/array_decl_plugin.cpp index 23d5145ea..be7bc6e2f 100644 --- a/src/ast/array_decl_plugin.cpp +++ b/src/ast/array_decl_plugin.cpp @@ -542,6 +542,16 @@ bool array_decl_plugin::is_fully_interp(sort const * s) const { return m_manager->is_fully_interp(get_array_range(s)); } +func_decl * array_recognizers::get_as_array_func_decl(app * n) const { + SASSERT(is_as_array(n)); + return to_func_decl(n->get_decl()->get_parameter(0).get_ast()); +} + +array_util::array_util(ast_manager& m): + array_recognizers(m.get_family_id("array")), + m_manager(m) { +} + bool array_util::is_as_array_tree(expr * n) { ptr_buffer todo; todo.push_back(n); diff --git a/src/ast/array_decl_plugin.h b/src/ast/array_decl_plugin.h index 68c473560..2184b0088 100644 --- a/src/ast/array_decl_plugin.h +++ b/src/ast/array_decl_plugin.h @@ -129,27 +129,34 @@ class array_decl_plugin : public decl_plugin { virtual bool is_fully_interp(sort const * s) const; }; -class array_util { - ast_manager & m_manager; - family_id m_fid; +class array_recognizers { +protected: + family_id m_fid; public: - array_util(ast_manager& m): m_manager(m), m_fid(m.get_family_id("array")) {} - ast_manager & get_manager() const { return m_manager; } + array_recognizers(family_id fid):m_fid(fid) {} family_id get_family_id() const { return m_fid; } bool is_array(sort* s) const { return is_sort_of(s, m_fid, ARRAY_SORT);} - bool is_array(expr* n) const { return is_array(m_manager.get_sort(n)); } + bool is_array(expr* n) const { return is_array(get_sort(n)); } bool is_select(expr* n) const { return is_app_of(n, m_fid, OP_SELECT); } bool is_store(expr* n) const { return is_app_of(n, m_fid, OP_STORE); } bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); } bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); } bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); } - bool is_as_array_tree(expr * n); bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); } bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); } bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); } bool is_map(func_decl* f) const { return is_decl_of(f, m_fid, OP_ARRAY_MAP); } bool is_as_array(func_decl* f) const { return is_decl_of(f, m_fid, OP_AS_ARRAY); } - func_decl * get_as_array_func_decl(app * n) const { SASSERT(is_as_array(n)); return to_func_decl(n->get_decl()->get_parameter(0).get_ast()); } + func_decl * get_as_array_func_decl(app * n) const; +}; + +class array_util : public array_recognizers { + ast_manager & m_manager; +public: + array_util(ast_manager& m); + ast_manager & get_manager() const { return m_manager; } + + bool is_as_array_tree(expr * n); app * mk_store(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_fid, OP_STORE, 0, 0, num_args, args); diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 94637bbdd..690c89229 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1073,6 +1073,16 @@ expr * basic_decl_plugin::get_some_value(sort * s) { return 0; } +bool basic_recognizers::is_ite(expr const * n, expr * & t1, expr * & t2, expr * & t3) const { + if (is_ite(n)) { + t1 = to_app(n)->get_arg(0); + t2 = to_app(n)->get_arg(1); + t3 = to_app(n)->get_arg(2); + return true; + } + return false; +} + // ----------------------------------- // // label_decl_plugin diff --git a/src/ast/ast.h b/src/ast/ast.h index f899ed241..09784b301 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1289,6 +1289,53 @@ inline bool has_labels(expr const * n) { sort * get_sort(expr const * n); +class basic_recognizers { + family_id m_fid; +public: + basic_recognizers(family_id fid):m_fid(fid) {} + bool is_bool(sort const * s) const { return is_sort_of(s, m_fid, BOOL_SORT); } + bool is_bool(expr const * n) const { return is_bool(get_sort(n)); } + bool is_or(expr const * n) const { return is_app_of(n, m_fid, OP_OR); } + bool is_implies(expr const * n) const { return is_app_of(n, m_fid, OP_IMPLIES); } + bool is_and(expr const * n) const { return is_app_of(n, m_fid, OP_AND); } + bool is_not(expr const * n) const { return is_app_of(n, m_fid, OP_NOT); } + bool is_eq(expr const * n) const { return is_app_of(n, m_fid, OP_EQ); } + bool is_oeq(expr const * n) const { return is_app_of(n, m_fid, OP_OEQ); } + bool is_distinct(expr const * n) const { return is_app_of(n, m_fid, OP_DISTINCT); } + bool is_iff(expr const * n) const { return is_app_of(n, m_fid, OP_IFF); } + bool is_xor(expr const * n) const { return is_app_of(n, m_fid, OP_XOR); } + bool is_ite(expr const * n) const { return is_app_of(n, m_fid, OP_ITE); } + bool is_term_ite(expr const * n) const { return is_ite(n) && !is_bool(n); } + bool is_true(expr const * n) const { return is_app_of(n, m_fid, OP_TRUE); } + bool is_false(expr const * n) const { return is_app_of(n, m_fid, OP_FALSE); } + bool is_complement_core(expr const * n1, expr const * n2) const { + return (is_true(n1) && is_false(n2)) || (is_not(n1) && to_app(n1)->get_arg(0) == n2); + } + bool is_complement(expr const * n1, expr const * n2) const { return is_complement_core(n1, n2) || is_complement_core(n2, n1); } + bool is_or(func_decl const * d) const { return is_decl_of(d, m_fid, OP_OR); } + bool is_implies(func_decl const * d) const { return is_decl_of(d, m_fid, OP_IMPLIES); } + bool is_and(func_decl const * d) const { return is_decl_of(d, m_fid, OP_AND); } + bool is_not(func_decl const * d) const { return is_decl_of(d, m_fid, OP_NOT); } + bool is_eq(func_decl const * d) const { return is_decl_of(d, m_fid, OP_EQ); } + bool is_iff(func_decl const * d) const { return is_decl_of(d, m_fid, OP_IFF); } + bool is_xor(func_decl const * d) const { return is_decl_of(d, m_fid, OP_XOR); } + bool is_ite(func_decl const * d) const { return is_decl_of(d, m_fid, OP_ITE); } + bool is_term_ite(func_decl const * d) const { return is_ite(d) && !is_bool(d->get_range()); } + bool is_distinct(func_decl const * d) const { return is_decl_of(d, m_fid, OP_DISTINCT); } + + MATCH_UNARY(is_not); + MATCH_BINARY(is_eq); + MATCH_BINARY(is_iff); + MATCH_BINARY(is_implies); + MATCH_BINARY(is_and); + MATCH_BINARY(is_or); + MATCH_BINARY(is_xor); + MATCH_TERNARY(is_and); + MATCH_TERNARY(is_or); + + bool is_ite(expr const * n, expr * & t1, expr * & t2, expr * & t3) const; +}; + // ----------------------------------- // // Get Some Value functor From d92efeb0c515eb03bb862d47f67774f4253d2925 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 18 Dec 2012 17:14:25 -0800 Subject: [PATCH 48/57] Make ast_manager::get_family_id(symbol const &) side-effect free. The version with side-effects is now called ast_manager::mk_family_id Signed-off-by: Leonardo de Moura --- src/api/api_context.cpp | 10 ++++----- src/ast/arith_decl_plugin.cpp | 2 +- src/ast/array_decl_plugin.cpp | 2 +- src/ast/ast.cpp | 28 +++++++++++++++--------- src/ast/ast.h | 24 +++++++++++++++----- src/ast/ast_smt_pp.cpp | 12 +++++----- src/ast/bv_decl_plugin.cpp | 8 +++---- src/ast/datatype_decl_plugin.cpp | 2 +- src/ast/decl_collector.cpp | 2 +- src/ast/dl_decl_plugin.cpp | 2 +- src/ast/float_decl_plugin.cpp | 6 ++--- src/ast/format.cpp | 2 +- src/ast/macros/macro_util.cpp | 4 ++-- src/ast/pattern/pattern_inference.cpp | 2 +- src/ast/pattern/pattern_inference.h | 2 +- src/ast/proof_checker/proof_checker.cpp | 2 +- src/ast/reg_decl_plugins.cpp | 14 ++++++------ src/ast/simplifier/bv_elim.cpp | 2 +- src/ast/simplifier/simplifier_plugin.h | 2 +- src/ast/static_features.cpp | 4 ++-- src/cmd_context/basic_cmds.cpp | 2 +- src/cmd_context/cmd_context.cpp | 2 +- src/cmd_context/pdecl.cpp | 2 +- src/muz_qe/dl_bmc_engine.cpp | 2 +- src/muz_qe/dl_cmds.cpp | 2 +- src/muz_qe/dl_rule.cpp | 2 +- src/muz_qe/proof_utils.cpp | 2 +- src/muz_qe/qe_arith_plugin.cpp | 4 ++-- src/muz_qe/qe_array_plugin.cpp | 2 +- src/muz_qe/qe_bv_plugin.cpp | 2 +- src/muz_qe/qe_datatype_plugin.cpp | 2 +- src/muz_qe/qe_dl_plugin.cpp | 2 +- src/parsers/smt/smtparser.cpp | 12 +++++----- src/parsers/util/pattern_validation.h | 3 +-- src/smt/proto_model/array_factory.cpp | 2 +- src/smt/proto_model/datatype_factory.cpp | 2 +- src/smt/proto_model/numeral_factory.cpp | 4 ++-- src/smt/proto_model/proto_model.cpp | 2 +- src/smt/proto_model/value_factory.cpp | 2 +- src/smt/smt_model_finder.cpp | 4 ++-- src/smt/smt_setup.cpp | 6 ++--- src/smt/theory_arith_core.h | 2 +- src/smt/theory_array_base.cpp | 2 +- src/smt/theory_bv.cpp | 2 +- src/smt/theory_datatype.cpp | 2 +- src/smt/theory_dense_diff_logic_def.h | 2 +- src/smt/theory_diff_logic.h | 2 +- src/smt/theory_dl.cpp | 4 ++-- src/smt/theory_seq_empty.h | 2 +- src/smt/user_plugin/user_smt_theory.cpp | 2 +- src/tactic/fpa/fpa2bv_converter.cpp | 2 +- src/tactic/probe.cpp | 2 +- src/test/bv_simplifier_plugin.cpp | 4 ++-- src/test/expr_rand.cpp | 4 ++-- src/test/fuzzing/expr_rand.cpp | 6 ++--- src/test/model_retrieval.cpp | 2 +- 56 files changed, 127 insertions(+), 108 deletions(-) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 7dc8d1a12..9ebc771f0 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -106,11 +106,11 @@ namespace api { m_error_handler = &default_error_handler; m_basic_fid = m().get_basic_family_id(); - m_arith_fid = m().get_family_id("arith"); - m_bv_fid = m().get_family_id("bv"); - m_array_fid = m().get_family_id("array"); - m_dt_fid = m().get_family_id("datatype"); - m_datalog_fid = m().get_family_id("datalog_relation"); + 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_dt_plugin = static_cast(m().get_plugin(m_dt_fid)); if (!m_user_ref_count) { diff --git a/src/ast/arith_decl_plugin.cpp b/src/ast/arith_decl_plugin.cpp index 093f6b346..f2dccf065 100644 --- a/src/ast/arith_decl_plugin.cpp +++ b/src/ast/arith_decl_plugin.cpp @@ -583,7 +583,7 @@ bool arith_recognizers::is_numeral(expr const * n, rational & val, bool & is_int } arith_util::arith_util(ast_manager & m): - arith_recognizers(m.get_family_id("arith")), + arith_recognizers(m.mk_family_id("arith")), m_manager(m), m_plugin(0) { } diff --git a/src/ast/array_decl_plugin.cpp b/src/ast/array_decl_plugin.cpp index be7bc6e2f..857cec105 100644 --- a/src/ast/array_decl_plugin.cpp +++ b/src/ast/array_decl_plugin.cpp @@ -548,7 +548,7 @@ func_decl * array_recognizers::get_as_array_func_decl(app * n) const { } array_util::array_util(ast_manager& m): - array_recognizers(m.get_family_id("array")), + array_recognizers(m.mk_family_id("array")), m_manager(m) { } diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 690c89229..486aa9646 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -137,7 +137,7 @@ void display_parameters(std::ostream & out, unsigned n, parameter const * p) { // // ----------------------------------- -family_id family_manager::get_family_id(symbol const & s) { +family_id family_manager::mk_family_id(symbol const & s) { family_id r; if (m_families.find(s, r)) { return r; @@ -149,7 +149,15 @@ family_id family_manager::get_family_id(symbol const & s) { return r; } -bool family_manager::has_family(symbol const & s) { +family_id family_manager::get_family_id(symbol const & s) const { + family_id r; + if (m_families.find(s, r)) + return r; + else + return null_family_id; +} + +bool family_manager::has_family(symbol const & s) const { return m_families.contains(s); } @@ -1297,12 +1305,12 @@ void ast_manager::init() { m_expr_id_gen.reset(0); m_decl_id_gen.reset(c_first_decl_id); m_some_value_proc = 0; - m_basic_family_id = get_family_id("basic"); - m_label_family_id = get_family_id("label"); - m_pattern_family_id = get_family_id("pattern"); - m_model_value_family_id = get_family_id("model-value"); - m_user_sort_family_id = get_family_id("user-sort"); - m_arith_family_id = get_family_id("arith"); + m_basic_family_id = mk_family_id("basic"); + m_label_family_id = mk_family_id("label"); + m_pattern_family_id = mk_family_id("pattern"); + m_model_value_family_id = mk_family_id("model-value"); + m_user_sort_family_id = mk_family_id("user-sort"); + m_arith_family_id = mk_family_id("arith"); basic_decl_plugin * plugin = alloc(basic_decl_plugin); register_plugin(m_basic_family_id, plugin); m_bool_sort = plugin->mk_bool_sort(); @@ -1435,7 +1443,7 @@ void ast_manager::copy_families_plugins(ast_manager const & from) { << ", target has_family: " << m_family_manager.has_family(fid) << "\n"; if (m_family_manager.has_family(fid)) tout << get_family_id(fid_name) << "\n";); if (!m_family_manager.has_family(fid)) { - family_id new_fid = get_family_id(fid_name); + family_id new_fid = mk_family_id(fid_name); TRACE("copy_families_plugins", tout << "new target fid created: " << new_fid << " fid_name: " << fid_name << "\n";); } TRACE("copy_families_plugins", tout << "target fid: " << get_family_id(fid_name) << "\n";); @@ -1472,7 +1480,7 @@ void ast_manager::set_next_expr_id(unsigned id) { unsigned ast_manager::get_node_size(ast const * n) { return ::get_node_size(n); } void ast_manager::register_plugin(symbol const & s, decl_plugin * plugin) { - family_id id = m_family_manager.get_family_id(s); + family_id id = m_family_manager.mk_family_id(s); SASSERT(is_format_manager() || s != symbol("format")); register_plugin(id, plugin); } diff --git a/src/ast/ast.h b/src/ast/ast.h index 09784b301..3f03b86b9 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -188,10 +188,20 @@ class family_manager { svector m_names; public: family_manager():m_next_id(0) {} + + /** + \brief Return the family_id for s, a new id is created if !has_family(s) + + If has_family(s), then this method is equivalent to get_family_id(s) + */ + family_id mk_family_id(symbol const & s); + + /** + \brief Return the family_id for s, return null_family_id if s was not registered in the manager. + */ + family_id get_family_id(symbol const & s) const; - family_id get_family_id(symbol const & s); - - bool has_family(symbol const & s); + bool has_family(symbol const & s) const; void get_dom(svector& dom) const { m_families.get_dom(dom); } @@ -1483,8 +1493,10 @@ public: small_object_allocator & get_allocator() { return m_alloc; } - family_id get_family_id(symbol const & s) const { return const_cast(this)->m_family_manager.get_family_id(s); } - + family_id mk_family_id(symbol const & s) { return m_family_manager.mk_family_id(s); } + family_id mk_family_id(char const * s) { return mk_family_id(symbol(s)); } + + family_id get_family_id(symbol const & s) const { return m_family_manager.get_family_id(s); } family_id get_family_id(char const * s) const { return get_family_id(symbol(s)); } symbol const & get_family_name(family_id fid) const { return m_family_manager.get_name(fid); } @@ -1507,7 +1519,7 @@ public: bool has_plugin(family_id fid) const { return get_plugin(fid) != 0; } - bool has_plugin(symbol const & s) const { return has_plugin(get_family_id(s)); } + bool has_plugin(symbol const & s) const { return m_family_manager.has_family(s) && has_plugin(m_family_manager.get_family_id(s)); } void get_dom(svector & dom) const { m_family_manager.get_dom(dom); } diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index 78a1caf68..66b467b92 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -795,11 +795,11 @@ public: m_simplify_implies(simplify_implies) { m_basic_fid = m.get_basic_family_id(); - m_label_fid = m.get_family_id("label"); - m_bv_fid = m.get_family_id("bv"); - m_arith_fid = m.get_family_id("arith"); - m_array_fid = m.get_family_id("array"); - m_dt_fid = m.get_family_id("datatype"); + m_label_fid = m.mk_family_id("label"); + m_bv_fid = m.mk_family_id("bv"); + m_arith_fid = m.mk_family_id("arith"); + m_array_fid = m.mk_family_id("array"); + m_dt_fid = m.mk_family_id("datatype"); } void operator()(expr* n) { @@ -1009,7 +1009,7 @@ ast_smt_pp::ast_smt_pp(ast_manager& m): m_status("unknown"), m_category(), m_logic(), - m_dt_fid(m.get_family_id("datatype")), + m_dt_fid(m.mk_family_id("datatype")), m_is_declared(&m_is_declared_default), m_simplify_implies(true) {} diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index 434bdaa11..9c5bccbc6 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -59,7 +59,7 @@ void bv_decl_plugin::set_manager(ast_manager * m, family_id id) { m_xor3 = m_manager->mk_func_decl(symbol("xor3"), 3, d, b, func_decl_info(m_family_id, OP_XOR3)); m_manager->inc_ref(m_xor3); - m_int_sort = m_manager->mk_sort(m_manager->get_family_id("arith"), INT_SORT); + m_int_sort = m_manager->mk_sort(m_manager->mk_family_id("arith"), INT_SORT); SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before bv_decl_plugin. m_manager->inc_ref(m_int_sort); } @@ -801,10 +801,10 @@ bool bv_recognizers::mult_inverse(rational const & n, unsigned bv_size, rational } bv_util::bv_util(ast_manager & m): - bv_recognizers(m.get_family_id(symbol("bv"))), + bv_recognizers(m.mk_family_id(symbol("bv"))), m_manager(m) { SASSERT(m.has_plugin(symbol("bv"))); - m_plugin = static_cast(m.get_plugin(m.get_family_id("bv"))); + m_plugin = static_cast(m.get_plugin(m.mk_family_id("bv"))); } app * bv_util::mk_numeral(rational const & val, sort* s) { @@ -827,7 +827,7 @@ sort * bv_util::mk_sort(unsigned bv_size) { } app * bv_util::mk_bv2int(expr* e) { - sort* s = m_manager.mk_sort(m_manager.get_family_id("arith"), INT_SORT); + sort* s = m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT); parameter p(s); return m_manager.mk_app(get_fid(), OP_BV2INT, 1, &p, 1, &e); } diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index 5cf841b49..0714af28b 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -673,7 +673,7 @@ bool datatype_decl_plugin::is_value(app * e) const { datatype_util::datatype_util(ast_manager & m): m_manager(m), - m_family_id(m.get_family_id("datatype")), + m_family_id(m.mk_family_id("datatype")), m_asts(m) { } diff --git a/src/ast/decl_collector.cpp b/src/ast/decl_collector.cpp index a83bf6b99..b663a9df3 100644 --- a/src/ast/decl_collector.cpp +++ b/src/ast/decl_collector.cpp @@ -45,7 +45,7 @@ decl_collector::decl_collector(ast_manager & m, bool preds): m_manager(m), m_sep_preds(preds) { m_basic_fid = m_manager.get_basic_family_id(); - m_dt_fid = m_manager.get_family_id("datatype"); + m_dt_fid = m_manager.mk_family_id("datatype"); } void decl_collector::visit(ast* n) { diff --git a/src/ast/dl_decl_plugin.cpp b/src/ast/dl_decl_plugin.cpp index 5b73f944a..8ac19c11c 100644 --- a/src/ast/dl_decl_plugin.cpp +++ b/src/ast/dl_decl_plugin.cpp @@ -629,7 +629,7 @@ namespace datalog { m(m), m_arith(m), m_bv(m), - m_fid(m.get_family_id(symbol("datalog_relation"))) + m_fid(m.mk_family_id(symbol("datalog_relation"))) {} // create a constant belonging to a given finite domain. diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index dbe7d5232..7f6d7f764 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -31,7 +31,7 @@ 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->get_family_id("arith"); + family_id aid = m_manager->mk_family_id("arith"); m_real_sort = m_manager->mk_sort(aid, REAL_SORT); SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. m_manager->inc_ref(m_real_sort); @@ -42,7 +42,7 @@ void float_decl_plugin::set_manager(ast_manager * m, family_id id) { if (m_manager->has_plugin(symbol("bv"))) { // bv plugin is optional, so m_bv_plugin may be 0 - m_bv_fid = m_manager->get_family_id("bv"); + m_bv_fid = m_manager->mk_family_id("bv"); m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); } } @@ -512,7 +512,7 @@ bool float_decl_plugin::is_value(app * e) const { float_util::float_util(ast_manager & m): m_manager(m), - m_fid(m.get_family_id("float")), + m_fid(m.mk_family_id("float")), m_a_util(m) { m_plugin = static_cast(m.get_plugin(m_fid)); } diff --git a/src/ast/format.cpp b/src/ast/format.cpp index 68ba5ea9a..1a36ca8ae 100644 --- a/src/ast/format.cpp +++ b/src/ast/format.cpp @@ -103,7 +103,7 @@ namespace format_ns { symbol f("format"); if (!fm(m).has_plugin(f)) fm(m).register_plugin(f, alloc(format_decl_plugin)); - return fm(m).get_family_id(f); + return fm(m).mk_family_id(f); } static family_id fid(ast_manager & m) { diff --git a/src/ast/macros/macro_util.cpp b/src/ast/macros/macro_util.cpp index 86f30ed73..e9b9c831e 100644 --- a/src/ast/macros/macro_util.cpp +++ b/src/ast/macros/macro_util.cpp @@ -41,7 +41,7 @@ macro_util::macro_util(ast_manager & m, simplifier & s): arith_simplifier_plugin * macro_util::get_arith_simp() const { if (m_arith_simp == 0) { - const_cast(this)->m_arith_simp = static_cast(m_simplifier.get_plugin(m_manager.get_family_id("arith"))); + const_cast(this)->m_arith_simp = static_cast(m_simplifier.get_plugin(m_manager.mk_family_id("arith"))); } SASSERT(m_arith_simp != 0); return m_arith_simp; @@ -49,7 +49,7 @@ arith_simplifier_plugin * macro_util::get_arith_simp() const { bv_simplifier_plugin * macro_util::get_bv_simp() const { if (m_bv_simp == 0) { - const_cast(this)->m_bv_simp = static_cast(m_simplifier.get_plugin(m_manager.get_family_id("bv"))); + const_cast(this)->m_bv_simp = static_cast(m_simplifier.get_plugin(m_manager.mk_family_id("bv"))); } SASSERT(m_bv_simp != 0); return m_bv_simp; diff --git a/src/ast/pattern/pattern_inference.cpp b/src/ast/pattern/pattern_inference.cpp index 773b9a2f5..83362f5b3 100644 --- a/src/ast/pattern/pattern_inference.cpp +++ b/src/ast/pattern/pattern_inference.cpp @@ -91,7 +91,7 @@ pattern_inference::pattern_inference(ast_manager & m, pattern_inference_params & simplifier(m), m_params(params), m_bfid(m.get_basic_family_id()), - m_afid(m.get_family_id("arith")), + m_afid(m.mk_family_id("arith")), m_le(m), m_nested_arith_only(true), m_block_loop_patterns(params.m_pi_block_loop_patterns), diff --git a/src/ast/pattern/pattern_inference.h b/src/ast/pattern/pattern_inference.h index 1a179e794..97897835c 100644 --- a/src/ast/pattern/pattern_inference.h +++ b/src/ast/pattern/pattern_inference.h @@ -150,7 +150,7 @@ class pattern_inference : public simplifier { void save_candidate(expr * n, unsigned delta); void reset(); public: - collect(ast_manager & m, pattern_inference & o):m_manager(m), m_owner(o), m_afid(m.get_family_id("arith")) {} + collect(ast_manager & m, pattern_inference & o):m_manager(m), m_owner(o), m_afid(m.mk_family_id("arith")) {} void operator()(expr * n, unsigned num_bindings); }; diff --git a/src/ast/proof_checker/proof_checker.cpp b/src/ast/proof_checker/proof_checker.cpp index 240504048..85e0cc791 100644 --- a/src/ast/proof_checker/proof_checker.cpp +++ b/src/ast/proof_checker/proof_checker.cpp @@ -85,7 +85,7 @@ proof_checker::proof_checker(ast_manager& m) : m(m), m_todo(m), m_marked(), m_pi if (!m.has_plugin(fam_name)) { m.register_plugin(fam_name, alloc(hyp_decl_plugin)); } - m_hyp_fid = m.get_family_id(fam_name); + m_hyp_fid = m.mk_family_id(fam_name); // m_spc_fid = m.get_family_id("spc"); m_nil = m.mk_const(m_hyp_fid, OP_NIL); } diff --git a/src/ast/reg_decl_plugins.cpp b/src/ast/reg_decl_plugins.cpp index fd4d49789..ab1844e07 100644 --- a/src/ast/reg_decl_plugins.cpp +++ b/src/ast/reg_decl_plugins.cpp @@ -27,25 +27,25 @@ Revision History: #include"float_decl_plugin.h" void reg_decl_plugins(ast_manager & m) { - if (!m.get_plugin(m.get_family_id(symbol("arith")))) { + if (!m.get_plugin(m.mk_family_id(symbol("arith")))) { m.register_plugin(symbol("arith"), alloc(arith_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("bv")))) { + if (!m.get_plugin(m.mk_family_id(symbol("bv")))) { m.register_plugin(symbol("bv"), alloc(bv_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("array")))) { + if (!m.get_plugin(m.mk_family_id(symbol("array")))) { m.register_plugin(symbol("array"), alloc(array_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("datatype")))) { + if (!m.get_plugin(m.mk_family_id(symbol("datatype")))) { m.register_plugin(symbol("datatype"), alloc(datatype_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("datalog_relation")))) { + if (!m.get_plugin(m.mk_family_id(symbol("datalog_relation")))) { m.register_plugin(symbol("datalog_relation"), alloc(datalog::dl_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("seq")))) { + if (!m.get_plugin(m.mk_family_id(symbol("seq")))) { m.register_plugin(symbol("seq"), alloc(seq_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("float")))) { + if (!m.get_plugin(m.mk_family_id(symbol("float")))) { m.register_plugin(symbol("float"), alloc(float_decl_plugin)); } } diff --git a/src/ast/simplifier/bv_elim.cpp b/src/ast/simplifier/bv_elim.cpp index 3238d13e7..5c19a245e 100644 --- a/src/ast/simplifier/bv_elim.cpp +++ b/src/ast/simplifier/bv_elim.cpp @@ -15,7 +15,7 @@ void bv_elim::elim(quantifier* q, quantifier_ref& r) { expr_ref new_body(m_manager); expr* old_body = q->get_expr(); unsigned num_decls = q->get_num_decls(); - family_id bfid = m_manager.get_family_id("bv"); + family_id bfid = m_manager.mk_family_id("bv"); // // Traverse sequence of bound variables to eliminate diff --git a/src/ast/simplifier/simplifier_plugin.h b/src/ast/simplifier/simplifier_plugin.h index d95547a69..8e176ea6e 100644 --- a/src/ast/simplifier/simplifier_plugin.h +++ b/src/ast/simplifier/simplifier_plugin.h @@ -37,7 +37,7 @@ protected: void set_reduce_invoked() { m_reduce_invoked = true; } public: - simplifier_plugin(symbol const & fname, ast_manager & m):m_manager(m), m_fid(m.get_family_id(fname)), m_presimp(false), m_reduce_invoked(false) {} + simplifier_plugin(symbol const & fname, ast_manager & m):m_manager(m), m_fid(m.mk_family_id(fname)), m_presimp(false), m_reduce_invoked(false) {} bool reduce_invoked() const { return m_reduce_invoked; } diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index 234626365..f40eb2c75 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -23,8 +23,8 @@ static_features::static_features(ast_manager & m): m_manager(m), m_autil(m), m_bfid(m.get_basic_family_id()), - m_afid(m.get_family_id("arith")), - m_lfid(m.get_family_id("label")), + m_afid(m.mk_family_id("arith")), + m_lfid(m.mk_family_id("label")), m_label_sym("label"), m_pattern_sym("pattern"), m_expr_list_sym("expr-list") { diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 8f65485ae..c1be7a69b 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -643,7 +643,7 @@ public: family_id get_array_fid(cmd_context & ctx) { if (m_array_fid == null_family_id) { - m_array_fid = ctx.m().get_family_id("array"); + m_array_fid = ctx.m().mk_family_id("array"); } return m_array_fid; } diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 3f32c77d3..043dc45e6 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -1386,7 +1386,7 @@ void cmd_context::set_diagnostic_stream(char const * name) { struct contains_array_op_proc { struct found {}; family_id m_array_fid; - contains_array_op_proc(ast_manager & m):m_array_fid(m.get_family_id("array")) {} + contains_array_op_proc(ast_manager & m):m_array_fid(m.mk_family_id("array")) {} void operator()(var * n) {} void operator()(app * n) { if (n->get_family_id() != m_array_fid) diff --git a/src/cmd_context/pdecl.cpp b/src/cmd_context/pdecl.cpp index 6b55d4072..bafd76f0b 100644 --- a/src/cmd_context/pdecl.cpp +++ b/src/cmd_context/pdecl.cpp @@ -765,7 +765,7 @@ pdecl_manager::pdecl_manager(ast_manager & m): m_allocator(m.get_allocator()), m_new_dt_eh(0) { m_list = 0; - m_datatype_fid = m.get_family_id("datatype"); + m_datatype_fid = m.mk_family_id("datatype"); } pdecl_manager::~pdecl_manager() { diff --git a/src/muz_qe/dl_bmc_engine.cpp b/src/muz_qe/dl_bmc_engine.cpp index b5ffa808a..c7e53e581 100644 --- a/src/muz_qe/dl_bmc_engine.cpp +++ b/src/muz_qe/dl_bmc_engine.cpp @@ -963,7 +963,7 @@ namespace datalog { sort_ref_vector new_sorts(m); - family_id dfid = m.get_family_id("datatype"); + family_id dfid = m.mk_family_id("datatype"); datatype_decl_plugin* dtp = static_cast(m.get_plugin(dfid)); VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); diff --git a/src/muz_qe/dl_cmds.cpp b/src/muz_qe/dl_cmds.cpp index bf9c24203..c88e7346e 100644 --- a/src/muz_qe/dl_cmds.cpp +++ b/src/muz_qe/dl_cmds.cpp @@ -75,7 +75,7 @@ struct dl_context { if (!m_decl_plugin) { symbol name("datalog_relation"); if (m.has_plugin(name)) { - m_decl_plugin = static_cast(m_cmd.m().get_plugin(m.get_family_id(name))); + m_decl_plugin = static_cast(m_cmd.m().get_plugin(m.mk_family_id(name))); } else { m_decl_plugin = alloc(datalog::dl_decl_plugin); diff --git a/src/muz_qe/dl_rule.cpp b/src/muz_qe/dl_rule.cpp index bd7131fea..d34f8a67f 100644 --- a/src/muz_qe/dl_rule.cpp +++ b/src/muz_qe/dl_rule.cpp @@ -74,7 +74,7 @@ namespace datalog { class remove_label_cfg : public default_rewriter_cfg { family_id m_label_fid; public: - remove_label_cfg(ast_manager& m): m_label_fid(m.get_family_id("label")) {} + remove_label_cfg(ast_manager& m): m_label_fid(m.get_label_family_id()) {} virtual ~remove_label_cfg() {} br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, diff --git a/src/muz_qe/proof_utils.cpp b/src/muz_qe/proof_utils.cpp index 1e837b578..e5a3ea437 100644 --- a/src/muz_qe/proof_utils.cpp +++ b/src/muz_qe/proof_utils.cpp @@ -450,7 +450,7 @@ static void permute_unit_resolution(expr_ref_vector& refs, obj_map parameter const* params = thLemma->get_decl()->get_parameters(); unsigned num_params = thLemma->get_decl()->get_num_parameters(); SASSERT(params[0].is_symbol()); - family_id tid = m.get_family_id(params[0].get_symbol()); + family_id tid = m.mk_family_id(params[0].get_symbol()); SASSERT(tid != null_family_id); prNew = m.mk_th_lemma(tid, m.get_fact(pr), premises.size(), premises.c_ptr(), num_params-1, params+1); diff --git a/src/muz_qe/qe_arith_plugin.cpp b/src/muz_qe/qe_arith_plugin.cpp index 69c036639..4e158229b 100644 --- a/src/muz_qe/qe_arith_plugin.cpp +++ b/src/muz_qe/qe_arith_plugin.cpp @@ -1512,7 +1512,7 @@ public: public: arith_plugin(i_solver_context& ctx, ast_manager& m, smt_params& p): - qe_solver_plugin(m, m.get_family_id("arith"), ctx), + qe_solver_plugin(m, m.mk_family_id("arith"), ctx), m_util(m, p, ctx), m_trail(m) {} @@ -2403,7 +2403,7 @@ public: bool m_produce_models; public: nlarith_plugin(i_solver_context& ctx, ast_manager& m, bool produce_models) : - qe_solver_plugin(m, m.get_family_id("arith"), ctx), + qe_solver_plugin(m, m.mk_family_id("arith"), ctx), m_rewriter(m), m_util(m), m_replacer(mk_default_expr_replacer(m)), diff --git a/src/muz_qe/qe_array_plugin.cpp b/src/muz_qe/qe_array_plugin.cpp index c013f93f4..106a42338 100644 --- a/src/muz_qe/qe_array_plugin.cpp +++ b/src/muz_qe/qe_array_plugin.cpp @@ -16,7 +16,7 @@ namespace qe { public: array_plugin(i_solver_context& ctx, ast_manager& m) : - qe_solver_plugin(m, m.get_family_id("array"), ctx), + qe_solver_plugin(m, m.mk_family_id("array"), ctx), m_replace(mk_default_expr_replacer(m)) { } diff --git a/src/muz_qe/qe_bv_plugin.cpp b/src/muz_qe/qe_bv_plugin.cpp index 8712061d6..cae567111 100644 --- a/src/muz_qe/qe_bv_plugin.cpp +++ b/src/muz_qe/qe_bv_plugin.cpp @@ -32,7 +32,7 @@ namespace qe { bv_util m_bv; public: bv_plugin(i_solver_context& ctx, ast_manager& m): - qe_solver_plugin(m, m.get_family_id("bv"), ctx), + qe_solver_plugin(m, m.mk_family_id("bv"), ctx), m_replace(mk_default_expr_replacer(m)), m_bv(m) {} diff --git a/src/muz_qe/qe_datatype_plugin.cpp b/src/muz_qe/qe_datatype_plugin.cpp index 3978a9ba4..0b51f26af 100644 --- a/src/muz_qe/qe_datatype_plugin.cpp +++ b/src/muz_qe/qe_datatype_plugin.cpp @@ -422,7 +422,7 @@ namespace qe { public: datatype_plugin(i_solver_context& ctx, ast_manager& m) : - qe_solver_plugin(m, m.get_family_id("datatype"), ctx), + qe_solver_plugin(m, m.mk_family_id("datatype"), ctx), m_datatype_util(m), m_replace(mk_default_expr_replacer(m)), m_trail(m) diff --git a/src/muz_qe/qe_dl_plugin.cpp b/src/muz_qe/qe_dl_plugin.cpp index 23f43759d..15e972e88 100644 --- a/src/muz_qe/qe_dl_plugin.cpp +++ b/src/muz_qe/qe_dl_plugin.cpp @@ -45,7 +45,7 @@ namespace qe { public: dl_plugin(i_solver_context& ctx, ast_manager& m) : - qe_solver_plugin(m, m.get_family_id("datalog_relation"), ctx), + qe_solver_plugin(m, m.mk_family_id("datalog_relation"), ctx), m_replace(mk_default_expr_replacer(m)), m_util(m), m_trail(m) diff --git a/src/parsers/smt/smtparser.cpp b/src/parsers/smt/smtparser.cpp index d3b2feeb7..c1ebd251b 100644 --- a/src/parsers/smt/smtparser.cpp +++ b/src/parsers/smt/smtparser.cpp @@ -483,13 +483,13 @@ public: class array_sort : public builtin_sort_builder { public: array_sort(ast_manager& m) : - builtin_sort_builder(m, m.get_family_id("array"), ARRAY_SORT) {} + builtin_sort_builder(m, m.mk_family_id("array"), ARRAY_SORT) {} }; class bv_sort : public builtin_sort_builder { public: bv_sort(ast_manager& m) : - builtin_sort_builder(m, m.get_family_id("bv"), BV_SORT) {} + builtin_sort_builder(m, m.mk_family_id("bv"), BV_SORT) {} }; class user_sort : public sort_builder { @@ -538,7 +538,7 @@ class smtparser : public parser { public: add_plugins(ast_manager& m) { #define REGISTER_PLUGIN(NAME, MK) { \ - family_id fid = m.get_family_id(symbol(NAME)); \ + family_id fid = m.mk_family_id(symbol(NAME)); \ if (!m.has_plugin(fid)) { \ m.register_plugin(fid, MK); \ } \ @@ -681,7 +681,7 @@ public: smtlib::symtable* table = m_benchmark.get_symtable(); symbol arith("arith"); - family_id afid = m_manager.get_family_id(arith); + family_id afid = m_manager.mk_family_id(arith); m_arith_fid = afid; add_builtin_type("Int", afid, INT_SORT); @@ -694,7 +694,7 @@ public: add_builtins(afid); symbol bv("bv"); - family_id bfid = m_manager.get_family_id(bv); + family_id bfid = m_manager.mk_family_id(bv); m_bv_fid = bfid; add_builtins(bfid); @@ -702,7 +702,7 @@ public: add_builtin_type("BitVec", bfid, BV_SORT); symbol array("array"); - afid = m_manager.get_family_id(array); + afid = m_manager.mk_family_id(array); m_array_fid = afid; add_builtins(afid); diff --git a/src/parsers/util/pattern_validation.h b/src/parsers/util/pattern_validation.h index d78502a8f..99024097e 100644 --- a/src/parsers/util/pattern_validation.h +++ b/src/parsers/util/pattern_validation.h @@ -32,11 +32,10 @@ class pattern_validator { public: pattern_validator(ast_manager const & m): m_bfid(m.get_basic_family_id()), - m_lfid(m.get_family_id("label")) { + m_lfid(m.get_label_family_id()) { } bool operator()(unsigned num_bindings, unsigned num_new_bindings, expr * n); - bool operator()(unsigned num_new_bindings, expr * n) { return operator()(UINT_MAX, num_new_bindings, n); } }; diff --git a/src/smt/proto_model/array_factory.cpp b/src/smt/proto_model/array_factory.cpp index b91857e40..a929f6d9a 100644 --- a/src/smt/proto_model/array_factory.cpp +++ b/src/smt/proto_model/array_factory.cpp @@ -34,7 +34,7 @@ func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s) { } array_factory::array_factory(ast_manager & m, proto_model & md): - struct_factory(m, m.get_family_id("array"), md) { + struct_factory(m, m.mk_family_id("array"), md) { } /** diff --git a/src/smt/proto_model/datatype_factory.cpp b/src/smt/proto_model/datatype_factory.cpp index 0ea610869..5be802714 100644 --- a/src/smt/proto_model/datatype_factory.cpp +++ b/src/smt/proto_model/datatype_factory.cpp @@ -22,7 +22,7 @@ Revision History: #include"ast_ll_pp.h" datatype_factory::datatype_factory(ast_manager & m, proto_model & md): - struct_factory(m, m.get_family_id("datatype"), md), + struct_factory(m, m.mk_family_id("datatype"), md), m_util(m) { } diff --git a/src/smt/proto_model/numeral_factory.cpp b/src/smt/proto_model/numeral_factory.cpp index 9653322e3..a67b6c075 100644 --- a/src/smt/proto_model/numeral_factory.cpp +++ b/src/smt/proto_model/numeral_factory.cpp @@ -24,7 +24,7 @@ app * arith_factory::mk_value_core(rational const & val, sort * s) { } arith_factory::arith_factory(ast_manager & m): - numeral_factory(m, m.get_family_id("arith")), + numeral_factory(m, m.mk_family_id("arith")), m_util(m) { } @@ -36,7 +36,7 @@ app * arith_factory::mk_value(rational const & val, bool is_int) { } bv_factory::bv_factory(ast_manager & m): - numeral_factory(m, m.get_family_id("bv")), + numeral_factory(m, m.mk_family_id("bv")), m_util(m) { } diff --git a/src/smt/proto_model/proto_model.cpp b/src/smt/proto_model/proto_model.cpp index 92110bc1a..d7a06f14f 100644 --- a/src/smt/proto_model/proto_model.cpp +++ b/src/smt/proto_model/proto_model.cpp @@ -31,7 +31,7 @@ proto_model::proto_model(ast_manager & m, simplifier & s, params_ref const & p): model_core(m), m_asts(m), m_simplifier(s), - m_afid(m.get_family_id(symbol("array"))) { + m_afid(m.mk_family_id(symbol("array"))) { register_factory(alloc(basic_factory, m)); m_user_sort_factory = alloc(user_sort_factory, m); register_factory(m_user_sort_factory); diff --git a/src/smt/proto_model/value_factory.cpp b/src/smt/proto_model/value_factory.cpp index 0b2aded9e..93294d898 100644 --- a/src/smt/proto_model/value_factory.cpp +++ b/src/smt/proto_model/value_factory.cpp @@ -51,7 +51,7 @@ expr * basic_factory::get_fresh_value(sort * s) { } user_sort_factory::user_sort_factory(ast_manager & m): - simple_factory(m, m.get_family_id("user-sort")) { + simple_factory(m, m.mk_family_id("user-sort")) { } void user_sort_factory::freeze_universe(sort * s) { diff --git a/src/smt/smt_model_finder.cpp b/src/smt/smt_model_finder.cpp index 619a7d60c..e69b7a1b6 100644 --- a/src/smt/smt_model_finder.cpp +++ b/src/smt/smt_model_finder.cpp @@ -454,8 +454,8 @@ namespace smt { m_model(0), m_eval_cache_range(m), m_new_constraints(0) { - m_asimp = static_cast(s.get_plugin(m.get_family_id("arith"))); - m_bvsimp = static_cast(s.get_plugin(m.get_family_id("bv"))); + m_asimp = static_cast(s.get_plugin(m.mk_family_id("arith"))); + m_bvsimp = static_cast(s.get_plugin(m.mk_family_id("bv"))); } ~auf_solver() { diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index f0dc1f5a6..96673e67e 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -692,7 +692,7 @@ namespace smt { void setup::setup_arith() { switch(m_params.m_arith_mode) { case AS_NO_ARITH: - m_context.register_plugin(alloc(smt::theory_dummy, m_manager.get_family_id("arith"), "no arithmetic")); + m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("arith"), "no arithmetic")); break; case AS_DIFF_LOGIC: if (m_params.m_arith_fixnum) { @@ -734,7 +734,7 @@ namespace smt { void setup::setup_bv() { switch(m_params.m_bv_mode) { case BS_NO_BV: - m_context.register_plugin(alloc(smt::theory_dummy, m_manager.get_family_id("bv"), "no bit-vector")); + m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("bv"), "no bit-vector")); break; case BS_BLASTER: m_context.register_plugin(alloc(smt::theory_bv, m_manager, m_params, m_params)); @@ -745,7 +745,7 @@ namespace smt { void setup::setup_arrays() { switch(m_params.m_array_mode) { case AR_NO_ARRAY: - m_context.register_plugin(alloc(smt::theory_dummy, m_manager.get_family_id("array"), "no array")); + m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("array"), "no array")); break; case AR_SIMPLE: m_context.register_plugin(alloc(smt::theory_array, m_manager, m_params)); diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index b774fb3d9..fafe73a79 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1294,7 +1294,7 @@ namespace smt { template theory_arith::theory_arith(ast_manager & m, theory_arith_params & params): - theory(m.get_family_id("arith")), + theory(m.mk_family_id("arith")), m_params(params), m_util(m), m_arith_eq_solver(m), diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index ca6449d1d..c2c50567f 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -27,7 +27,7 @@ Revision History: namespace smt { theory_array_base::theory_array_base(ast_manager & m): - theory(m.get_family_id("array")), + theory(m.mk_family_id("array")), m_found_unsupported_op(false) { } diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index e425071d2..559ce155b 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -1239,7 +1239,7 @@ namespace smt { } theory_bv::theory_bv(ast_manager & m, theory_bv_params const & params, bit_blaster_params const & bb_params): - theory(m.get_family_id("bv")), + theory(m.mk_family_id("bv")), m_params(params), m_util(m), m_autil(m), diff --git a/src/smt/theory_datatype.cpp b/src/smt/theory_datatype.cpp index 65abfe238..8c6543eff 100644 --- a/src/smt/theory_datatype.cpp +++ b/src/smt/theory_datatype.cpp @@ -454,7 +454,7 @@ namespace smt { } theory_datatype::theory_datatype(ast_manager & m, theory_datatype_params & p): - theory(m.get_family_id("datatype")), + theory(m.mk_family_id("datatype")), m_params(p), m_util(m), m_find(*this), diff --git a/src/smt/theory_dense_diff_logic_def.h b/src/smt/theory_dense_diff_logic_def.h index 4d50bd8bf..21f1262ac 100644 --- a/src/smt/theory_dense_diff_logic_def.h +++ b/src/smt/theory_dense_diff_logic_def.h @@ -28,7 +28,7 @@ namespace smt { template theory_dense_diff_logic::theory_dense_diff_logic(ast_manager & m, theory_arith_params & p): - theory(m.get_family_id("arith")), + theory(m.mk_family_id("arith")), m_params(p), m_autil(m), m_arith_eq_adapter(*this, p, m_autil), diff --git a/src/smt/theory_diff_logic.h b/src/smt/theory_diff_logic.h index 264ab9b2d..4140f683c 100644 --- a/src/smt/theory_diff_logic.h +++ b/src/smt/theory_diff_logic.h @@ -306,7 +306,7 @@ namespace smt { public: theory_diff_logic(ast_manager& m, smt_params & params): - theory(m.get_family_id("arith")), + theory(m.mk_family_id("arith")), m_params(params), m_util(m), m_arith_eq_adapter(*this, params, m_util), diff --git a/src/smt/theory_dl.cpp b/src/smt/theory_dl.cpp index 402ab856c..758f78c2c 100644 --- a/src/smt/theory_dl.cpp +++ b/src/smt/theory_dl.cpp @@ -88,7 +88,7 @@ namespace smt { m_th.get_rep(s, r, v); app_ref rep_of(m_th.m()); rep_of = m_th.m().mk_app(r, m_node->get_owner()); - theory_id bv_id = m_th.m().get_family_id("bv"); + theory_id bv_id = m_th.m().mk_family_id("bv"); theory_bv* th_bv = dynamic_cast(ctx.get_theory(bv_id)); SASSERT(th_bv); rational val; @@ -106,7 +106,7 @@ namespace smt { public: theory_dl(ast_manager& m): - theory(m.get_family_id("datalog_relation")), + theory(m.mk_family_id("datalog_relation")), m_util(m), m_bv(m), m_trail(m) diff --git a/src/smt/theory_seq_empty.h b/src/smt/theory_seq_empty.h index ef3924603..d5468df28 100644 --- a/src/smt/theory_seq_empty.h +++ b/src/smt/theory_seq_empty.h @@ -32,7 +32,7 @@ namespace smt { virtual theory* mk_fresh(context*) { return alloc(theory_seq_empty, get_manager()); } virtual char const * get_name() const { return "seq-empty"; } public: - theory_seq_empty(ast_manager& m):theory(m.get_family_id("seq")), m_used(false) {} + theory_seq_empty(ast_manager& m):theory(m.mk_family_id("seq")), m_used(false) {} }; }; diff --git a/src/smt/user_plugin/user_smt_theory.cpp b/src/smt/user_plugin/user_smt_theory.cpp index ab4cc62c4..a2d1e4f37 100644 --- a/src/smt/user_plugin/user_smt_theory.cpp +++ b/src/smt/user_plugin/user_smt_theory.cpp @@ -646,7 +646,7 @@ namespace smt { context & ctx = _s.get_context(); // HACK symbol _name(name); ast_manager & m = ctx.get_manager(); - family_id fid = m.get_family_id(_name); + family_id fid = m.mk_family_id(_name); user_decl_plugin * dp = alloc(user_decl_plugin); m.register_plugin(fid, dp); simplifier & s = ctx.get_simplifier(); diff --git a/src/tactic/fpa/fpa2bv_converter.cpp b/src/tactic/fpa/fpa2bv_converter.cpp index 8a4b31612..b53ad21eb 100644 --- a/src/tactic/fpa/fpa2bv_converter.cpp +++ b/src/tactic/fpa/fpa2bv_converter.cpp @@ -32,7 +32,7 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) : m_mpz_manager(m_mpf_manager.mpz_manager()), m_bv_util(m), extra_assertions(m) { - m_plugin = static_cast(m.get_plugin(m.get_family_id("float"))); + m_plugin = static_cast(m.get_plugin(m.mk_family_id("float"))); } fpa2bv_converter::~fpa2bv_converter() { diff --git a/src/tactic/probe.cpp b/src/tactic/probe.cpp index 2940e93b9..1a696dc78 100644 --- a/src/tactic/probe.cpp +++ b/src/tactic/probe.cpp @@ -326,7 +326,7 @@ class num_consts_probe : public probe { unsigned m_counter; proc(ast_manager & _m, bool b, char const * family):m(_m), m_bool(b), m_counter(0) { if (family != 0) - m_fid = m.get_family_id(family); + m_fid = m.mk_family_id(family); else m_fid = null_family_id; } diff --git a/src/test/bv_simplifier_plugin.cpp b/src/test/bv_simplifier_plugin.cpp index 4a472425e..635143021 100644 --- a/src/test/bv_simplifier_plugin.cpp +++ b/src/test/bv_simplifier_plugin.cpp @@ -79,7 +79,7 @@ public: m_arith(m_manager), m_simp(m_manager, m_bsimp, m_bv_params), m_bv_util(m_manager), - m_fid(m_manager.get_family_id("bv")) { + m_fid(m_manager.mk_family_id("bv")) { reg_decl_plugins(m_manager); } @@ -139,7 +139,7 @@ public: m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); SASSERT(((a >> 8) | (a << 24)) == u32(e.get())); - params[0] = parameter(m_manager.mk_sort(m_manager.get_family_id("arith"), INT_SORT)); + params[0] = parameter(m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT)); ar = m_manager.mk_app(m_fid, OP_BV2INT, 1, params, 1, es); expr* es2[1] = { ar.get() }; params[0] = parameter(32); diff --git a/src/test/expr_rand.cpp b/src/test/expr_rand.cpp index 1ceeba8b8..19a07e98a 100644 --- a/src/test/expr_rand.cpp +++ b/src/test/expr_rand.cpp @@ -18,7 +18,7 @@ void tst_expr_arith(unsigned num_files) { er.seed(rand_seed); er.initialize_arith(20); - family_id fid = m.get_family_id("arith"); + family_id fid = m.mk_family_id("arith"); sort* int_ty = m.mk_sort(fid, INT_SORT, 0, 0); sort* real_ty = m.mk_sort(fid, REAL_SORT, 0, 0); @@ -56,7 +56,7 @@ void tst_expr_rand(unsigned num_files) { parameter p2(2); parameter p8(8); parameter p32(32); - family_id bvfid = m.get_family_id("bv"); + family_id bvfid = m.mk_family_id("bv"); sort* bv1 = m.mk_sort(bvfid, BV_SORT, 1, &p1); sort* bv2 = m.mk_sort(bvfid, BV_SORT, 1, &p2); sort* bv8 = m.mk_sort(bvfid, BV_SORT, 1, &p8); diff --git a/src/test/fuzzing/expr_rand.cpp b/src/test/fuzzing/expr_rand.cpp index e1a7631c4..a2aca7e6e 100644 --- a/src/test/fuzzing/expr_rand.cpp +++ b/src/test/fuzzing/expr_rand.cpp @@ -82,7 +82,7 @@ expr* expr_rand::choose_expr(sort* s) { void expr_rand::initialize_arith(unsigned num_vars) { arith_util u(m_manager); - family_id afid = m_manager.get_family_id("arith"); + family_id afid = m_manager.mk_family_id("arith"); sort* i_ty = m_manager.mk_sort(afid, INT_SORT, 0, 0); for(unsigned i = 0; i < num_vars; ++i) { add_var(i_ty); @@ -106,7 +106,7 @@ void expr_rand::initialize_arith(unsigned num_vars) { void expr_rand::initialize_bv(unsigned num_vars) { bv_util u(m_manager); family_id bfid = m_manager.get_basic_family_id(); - family_id bvfid = m_manager.get_family_id("bv"); + family_id bvfid = m_manager.mk_family_id("bv"); const unsigned num_sizes = 6; @@ -237,7 +237,7 @@ void expr_rand::initialize_bv(unsigned num_vars) { } void expr_rand::initialize_array(unsigned num_vars, sort* dom, sort* rng) { - family_id afid = m_manager.get_family_id("array"); + family_id afid = m_manager.mk_family_id("array"); parameter p1(dom), p2(rng); parameter ps[2] = { p1, p2 }; sort* a = m_manager.mk_sort(afid, ARRAY_SORT, 2, ps); diff --git a/src/test/model_retrieval.cpp b/src/test/model_retrieval.cpp index da6c3ddd0..f40f89d22 100644 --- a/src/test/model_retrieval.cpp +++ b/src/test/model_retrieval.cpp @@ -18,7 +18,7 @@ void tst_model_retrieval() ast_manager m; reg_decl_plugins(m); - family_id array_fid = m.get_family_id(symbol("array")); + family_id array_fid = m.mk_family_id(symbol("array")); array_util au(m); // arr_s and select_fn creation copy-pasted from z3.cpp From 7b1fac11e647c77eccd54cb591feb699b832d276 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 19 Dec 2012 12:33:14 -0800 Subject: [PATCH 49/57] Add new C++ examples Signed-off-by: Leonardo de Moura --- examples/c++/example.cpp | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index ab6e67ab9..9e92d99ab 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -812,6 +812,68 @@ void tst_visit() { visit(f); } +void incremental_example1() { + std::cout << "incremental example1\n"; + context c; + expr x = c.int_const("x"); + solver s(c); + s.add(x > 0); + std::cout << s.check() << "\n"; + // We can add more formulas to the solver + s.add(x < 0); + // and, invoke s.check() again... + std::cout << s.check() << "\n"; +} + +void incremental_example2() { + // In this example, we show how push() and pop() can be used + // to remove formulas added to the solver. + std::cout << "incremental example2\n"; + context c; + expr x = c.int_const("x"); + solver s(c); + s.add(x > 0); + std::cout << s.check() << "\n"; + // push() creates a backtracking point (aka a snapshot). + s.push(); + // We can add more formulas to the solver + s.add(x < 0); + // and, invoke s.check() again... + std::cout << s.check() << "\n"; + // pop() will remove all formulas added between this pop() and the matching push() + s.pop(); + // The context is satisfiable again + std::cout << s.check() << "\n"; + // and contains only x > 0 + std::cout << s << "\n"; +} + +void incremental_example3() { + // In this example, we show how to use assumptions to "remove" + // formulas added to a solver. Actually, we disable them. + std::cout << "incremental example3\n"; + context c; + expr x = c.int_const("x"); + solver s(c); + s.add(x > 0); + std::cout << s.check() << "\n"; + // Now, suppose we want to add x < 0 to the solver, but we also want + // to be able to disable it later. + // To do that, we create an auxiliary Boolean variable + expr b = c.bool_const("b"); + // and, assert (b implies x < 0) + s.add(implies(b, x < 0)); + // Now, we check whether s is satisfiable under the assumption "b" is true. + expr_vector a1(c); + a1.push_back(b); + std::cout << s.check(a1) << "\n"; + // To "disable" (x > 0), we may just ask with the assumption "not b" or not provide any assumption. + std::cout << s.check() << "\n"; + expr_vector a2(c); + a2.push_back(!b); + std::cout << s.check(a2) << "\n"; +} + int main() { try { demorgan(); std::cout << "\n"; @@ -842,6 +904,9 @@ int main() { tactic_example9(); std::cout << "\n"; tactic_qe(); std::cout << "\n"; tst_visit(); std::cout << "\n"; + incremental_example1(); std::cout << "\n"; + incremental_example2(); std::cout << "\n"; + incremental_example3(); std::cout << "\n"; std::cout << "done\n"; } catch (exception & ex) { From 27438b0fc948a78591f774108180b87b09499790 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Thu, 13 Dec 2012 11:33:38 +0000 Subject: [PATCH 50/57] Fix newlines --- src/api/ml/README-linux | 44 ++++++++++++++++++------------------ src/api/ml/README-osx | 44 ++++++++++++++++++------------------ src/api/ml/README-test-linux | 34 ++++++++++++++-------------- src/api/ml/README-test-osx | 34 ++++++++++++++-------------- src/api/ml/exec.sh | 8 +++---- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/api/ml/README-linux b/src/api/ml/README-linux index a726c0c94..5ee20bb27 100644 --- a/src/api/ml/README-linux +++ b/src/api/ml/README-linux @@ -1,22 +1,22 @@ -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! +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/README-osx b/src/api/ml/README-osx index a726c0c94..5ee20bb27 100644 --- a/src/api/ml/README-osx +++ b/src/api/ml/README-osx @@ -1,22 +1,22 @@ -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! +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/README-test-linux b/src/api/ml/README-test-linux index 34900883d..fc15fb2a2 100644 --- a/src/api/ml/README-test-linux +++ b/src/api/ml/README-test-linux @@ -1,17 +1,17 @@ -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. +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/README-test-osx b/src/api/ml/README-test-osx index bfc6b115e..3a20d1f1d 100644 --- a/src/api/ml/README-test-osx +++ b/src/api/ml/README-test-osx @@ -1,17 +1,17 @@ -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. +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/exec.sh b/src/api/ml/exec.sh index a1d3c8e49..573ec6ddf 100644 --- a/src/api/ml/exec.sh +++ b/src/api/ml/exec.sh @@ -1,4 +1,4 @@ -#!/bin/sh -export LD_LIBRARY_PATH=../../lib:$LD_LIBRARY_PATH # for linux -export DYLD_LIBRARY_PATH=../../lib:$DYLD_LIBRARY_PATH # for osx -./test_mlapi +#!/bin/sh +export LD_LIBRARY_PATH=../../lib:$LD_LIBRARY_PATH # for linux +export DYLD_LIBRARY_PATH=../../lib:$DYLD_LIBRARY_PATH # for osx +./test_mlapi From 32896a15e6e82e660164ddb9845d0c43fdcf2b25 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Wed, 12 Dec 2012 02:02:08 +0000 Subject: [PATCH 51/57] Fix for compiling ml api --- src/api/ml/Makefile.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/ml/Makefile.build b/src/api/ml/Makefile.build index 27c798bbf..0a737e356 100644 --- a/src/api/ml/Makefile.build +++ b/src/api/ml/Makefile.build @@ -13,7 +13,7 @@ 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 ../../z3.lib /out: +AR=lib /nologo /LIBPATH:../../build ../../libz3.lib /out: O=obj A=lib else From fd5372d7a27792e884bd7d94da053599f8f98eb6 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Sat, 8 Dec 2012 18:05:26 +0000 Subject: [PATCH 52/57] Z3_search_failure type not needed in v4 ml api --- src/api/z3_api.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index e12ce3591..e8306bfb6 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1080,6 +1080,7 @@ typedef enum { Z3_PK_INVALID } Z3_param_kind; +#ifdef CorML3 /** \mlonly {!search_failure} \endmlonly \conly \brief The different kinds of search failure types. @@ -1103,6 +1104,7 @@ typedef enum { Z3_THEORY, Z3_QUANTIFIERS } Z3_search_failure; +#endif /** \mlonly {!ast_print_mode} \endmlonly \conly \brief From a7f89dcdd2faabffd980d16326f15f9304fdca2e Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Thu, 20 Dec 2012 12:54:44 +0000 Subject: [PATCH 53/57] Move Z3_get_implied_equalities from v3 to v4 ml api as it now needs Z3_solver type --- src/api/z3_api.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index e8306bfb6..98bde7bcf 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -6924,12 +6924,15 @@ END_MLAPI_EXCLUDE ); /*@}*/ - +#endif + + /** @name Deprecated Constraints API */ /*@{*/ +#ifdef CorML3 /** \brief Set the SMTLIB logic to be used in the given logical context. It is incorrect to invoke this function after invoking @@ -7111,7 +7114,9 @@ END_MLAPI_EXCLUDE __out Z3_model * m, __out Z3_ast* proof, __inout unsigned* core_size, __inout_ecount(num_assumptions) Z3_ast core[] ); +#endif +#ifdef CorML4 /** \brief Retrieve congruence class representatives for terms. @@ -7142,7 +7147,9 @@ END_MLAPI_EXCLUDE __in_ecount(num_terms) Z3_ast const terms[], __out_ecount(num_terms) unsigned class_ids[] ); +#endif +#ifdef CorML3 /** \brief Delete a model object. From d7b8110cc8cf5d20540be1b0955dfb0241c857dd Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Thu, 20 Dec 2012 12:58:21 +0000 Subject: [PATCH 54/57] Regenerate ml api --- src/api/ml/z3.ml | 16 +----- src/api/ml/z3.mli | 71 ++++++++--------------- src/api/ml/z3_stubs.c | 131 ++++++++++++++++++------------------------ 3 files changed, 84 insertions(+), 134 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 4d391c06f..705f9a3e7 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -229,16 +229,6 @@ and param_kind = | 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 @@ -1598,6 +1588,9 @@ external stats_get_uint_value : context -> stats -> int -> int 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: *) (* @@ -2988,9 +2981,6 @@ external check : context -> lbool external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array = "camlidl_z3V3_Z3_check_assumptions" -external get_implied_equalities : context -> ast array -> lbool * int array - = "camlidl_z3V3_Z3_get_implied_equalities" - external del_model : context -> model -> unit = "camlidl_z3V3_Z3_del_model" diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 4dd3d5b14..2eb9eecb7 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -229,16 +229,6 @@ and param_kind = | 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 @@ -866,23 +856,9 @@ and goal_prec = - 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. @@ -891,7 +867,6 @@ and goal_prec = (** {!error_code} Z3 error codes - - OK: No error. - SORT_ERROR: User tried to build an invalid (type incorrect) AST. - IOB: Index out of bounds. @@ -908,7 +883,6 @@ and goal_prec = *) (** Definitions for update_api.py - def_Type('CONFIG', 'config', 'Config') def_Type('CONTEXT', 'context', 'ContextObj') def_Type('AST', 'ast', 'Ast') @@ -5043,6 +5017,30 @@ external stats_get_uint_value : context -> stats -> int -> int 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}} @@ -8941,27 +8939,6 @@ external check : context -> lbool external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array = "camlidl_z3V3_Z3_check_assumptions" -(** - 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. - The function return L_FALSE if the current assertions are not satisfiable. - - {b See also}: {!check_and_get_model} - - {b See also}: {!check} - @deprecated Subsumed by solver API - def_API('get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) -*) -external get_implied_equalities : context -> ast array -> lbool * int array - = "camlidl_z3V3_Z3_get_implied_equalities" - (** Summary: Delete a model object. - {b See also}: {!check_and_get_model} diff --git a/src/api/ml/z3_stubs.c b/src/api/ml/z3_stubs.c index 0cf20fb2e..bad4338de 100644 --- a/src/api/ml/z3_stubs.c +++ b/src/api/ml/z3_stubs.c @@ -594,30 +594,7 @@ value _v1; return _v1; } -int camlidl_transl_table_z3_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_z3_Z3_search_failure(value _v1, Z3_search_failure * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_8[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_search_failure(Z3_search_failure * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_8, 8, "typedef Z3_search_failure: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_9[4] = { +int camlidl_transl_table_z3_enum_8[4] = { Z3_PRINT_SMTLIB_FULL, Z3_PRINT_LOW_LEVEL, Z3_PRINT_SMTLIB_COMPLIANT, @@ -626,7 +603,7 @@ int camlidl_transl_table_z3_enum_9[4] = { void camlidl_ml2c_z3_Z3_ast_print_mode(value _v1, Z3_ast_print_mode * _c2, camlidl_ctx _ctx) { - (*_c2) = camlidl_transl_table_z3_enum_9[Int_val(_v1)]; + (*_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) @@ -642,7 +619,7 @@ value _v1; return _v1; } -int camlidl_transl_table_z3_enum_10[13] = { +int camlidl_transl_table_z3_enum_9[13] = { Z3_OK, Z3_SORT_ERROR, Z3_IOB, @@ -660,13 +637,13 @@ int camlidl_transl_table_z3_enum_10[13] = { void camlidl_ml2c_z3_Z3_error_code(value _v1, Z3_error_code * _c2, camlidl_ctx _ctx) { - (*_c2) = camlidl_transl_table_z3_enum_10[Int_val(_v1)]; + (*_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_10, 13, "typedef Z3_error_code: bad enum value"); + _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_9, 13, "typedef Z3_error_code: bad enum value"); return _v1; } @@ -698,7 +675,7 @@ void check_error_code (Z3_context c) /* Disable default error handler, all error checking is done by check_error_code */ void* error_handler_static = NULL; -int camlidl_transl_table_z3_enum_11[4] = { +int camlidl_transl_table_z3_enum_10[4] = { Z3_GOAL_PRECISE, Z3_GOAL_UNDER, Z3_GOAL_OVER, @@ -707,7 +684,7 @@ int camlidl_transl_table_z3_enum_11[4] = { void camlidl_ml2c_z3_Z3_goal_prec(value _v1, Z3_goal_prec * _c2, camlidl_ctx _ctx) { - (*_c2) = camlidl_transl_table_z3_enum_11[Int_val(_v1)]; + (*_c2) = camlidl_transl_table_z3_enum_10[Int_val(_v1)]; } value camlidl_c2ml_z3_Z3_goal_prec(Z3_goal_prec * _c2, camlidl_ctx _ctx) @@ -11110,6 +11087,56 @@ check_error_code(c); 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)); @@ -18321,50 +18348,6 @@ value camlidl_z3V3_Z3_check_assumptions( return _vresult; } -value camlidl_z3V3_Z3_get_implied_equalities( - value _v_c, - value _v_terms) -{ - Z3_context c; /*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_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_terms = _c1; - class_ids = camlidl_malloc(num_terms * sizeof(unsigned int ), _ctx); - _res = Z3_get_implied_equalities(c, num_terms, terms, class_ids); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_c2ml_z3V3_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); - return _vresult; -} - value camlidl_z3V3_Z3_del_model( value _v_c, value _v_m) From 7d97f407c22ef0dadc2459783dac71d3acb92d5d Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 20 Dec 2012 10:40:14 -0800 Subject: [PATCH 55/57] Remove non-ascii characters Signed-off-by: Leonardo de Moura --- src/math/polynomial/polynomial_factorization.cpp | 2 +- src/math/polynomial/polynomial_factorization.h | 2 +- src/math/polynomial/upolynomial_factorization.cpp | 2 +- src/math/polynomial/upolynomial_factorization.h | 2 +- src/math/polynomial/upolynomial_factorization_int.h | 2 +- src/muz_qe/dl_relation_manager.h | 6 +++--- src/smt/smt_model_finder.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/math/polynomial/polynomial_factorization.cpp b/src/math/polynomial/polynomial_factorization.cpp index e0f050411..220048a9a 100644 --- a/src/math/polynomial/polynomial_factorization.cpp +++ b/src/math/polynomial/polynomial_factorization.cpp @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/polynomial_factorization.h b/src/math/polynomial/polynomial_factorization.h index 48b4efd98..f069121ba 100644 --- a/src/math/polynomial/polynomial_factorization.h +++ b/src/math/polynomial/polynomial_factorization.h @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/upolynomial_factorization.cpp b/src/math/polynomial/upolynomial_factorization.cpp index a1e28e727..230d352f3 100644 --- a/src/math/polynomial/upolynomial_factorization.cpp +++ b/src/math/polynomial/upolynomial_factorization.cpp @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/upolynomial_factorization.h b/src/math/polynomial/upolynomial_factorization.h index e687786da..327fffc9c 100644 --- a/src/math/polynomial/upolynomial_factorization.h +++ b/src/math/polynomial/upolynomial_factorization.h @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/upolynomial_factorization_int.h b/src/math/polynomial/upolynomial_factorization_int.h index c076b2e6d..92d62301d 100644 --- a/src/math/polynomial/upolynomial_factorization_int.h +++ b/src/math/polynomial/upolynomial_factorization_int.h @@ -17,7 +17,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/muz_qe/dl_relation_manager.h b/src/muz_qe/dl_relation_manager.h index 270e06f12..ecba3d598 100644 --- a/src/muz_qe/dl_relation_manager.h +++ b/src/muz_qe/dl_relation_manager.h @@ -3,7 +3,7 @@ Copyright (c) 2006 Microsoft Corporation Module Name: - dl_remation_manager.h + dl_relation_manager.h Abstract: @@ -316,7 +316,7 @@ namespace datalog { oldTgt:=tgt.clone(); tgt:=tgt \union src if(tgt!=oldTgt) { - delta:=delta \union src //also “delta \union tgt” would work + delta:=delta \union src //also ?delta \union tgt? would work } } @@ -488,7 +488,7 @@ namespace datalog { oldTgt:=tgt.clone(); tgt:=tgt \union src if(tgt!=oldTgt) { - delta:=delta \union src //also “delta \union tgt” would work + delta:=delta \union src //also ?delta \union tgt? would work } } diff --git a/src/smt/smt_model_finder.h b/src/smt/smt_model_finder.h index 20d9ba6ef..b89603912 100644 --- a/src/smt/smt_model_finder.h +++ b/src/smt/smt_model_finder.h @@ -33,7 +33,7 @@ Abstract: Lugano, Switzerland, 2010. - Bugs, Moles and Skeletons: Symbolic Reasoning for Software - Development, Leonardo de Moura, Nikolaj Bjørner, IJCAR, + Development, Leonardo de Moura, Nikolaj Bjorner, IJCAR, Edinburgh, Scotland, 2010. Author: From 6602803850d84ef0e09c142c6133721b9692a8cf Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 20 Dec 2012 17:47:38 -0800 Subject: [PATCH 56/57] Add Python 3.x support Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 + examples/python/example.py | 4 +- scripts/mk_util.py | 209 ++++++++--------- scripts/update_api.py | 61 +++-- src/api/python/z3.py | 449 +++++++++++++++++++----------------- src/api/python/z3printer.py | 59 +++-- 6 files changed, 426 insertions(+), 358 deletions(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 234ba03fb..694a6d635 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -9,6 +9,8 @@ Version 4.3.2 - Added support for FreeBSD. Z3 can be compiled on FreeBSD using g++. +- Added support for Python 3.x. + - Reverted to `(set-option :global-decls false)` as the default. In Z3 4.3.0 and Z3 4.3.1, this option was set to true. Thanks to Julien Henry for reporting this problem. diff --git a/examples/python/example.py b/examples/python/example.py index a8a764a4d..879c17c43 100644 --- a/examples/python/example.py +++ b/examples/python/example.py @@ -4,5 +4,5 @@ x = Real('x') y = Real('y') s = Solver() s.add(x + y > 5, x > 1, y > 1) -print s.check() -print s.model() +print(s.check()) +print(s.model()) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3ffa7e313..268a6d27b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -7,11 +7,6 @@ # Author: Leonardo de Moura (leonardo) ############################################ import sys - -if sys.version >= "3": - print "ERROR: python 2.x required." - exit(1) - import os import glob import re @@ -134,8 +129,7 @@ def exec_cmd(cmd): first = True for e in cmd: if first: - # Allow spaces in the executable name - first = False + first = False new_cmd.append(e) else: if e != "": @@ -166,7 +160,7 @@ def exec_compiler_cmd(cmd): def test_cxx_compiler(cc): if is_verbose(): - print "Testing %s..." % cc + print("Testing %s..." % cc) t = TempFile('tst.cpp') t.add('#include\nint main() { return 0; }\n') t.commit() @@ -174,7 +168,7 @@ def test_cxx_compiler(cc): def test_c_compiler(cc): if is_verbose(): - print "Testing %s..." % cc + print("Testing %s..." % cc) t = TempFile('tst.c') t.add('#include\nint main() { return 0; }\n') t.commit() @@ -182,7 +176,7 @@ def test_c_compiler(cc): def test_gmp(cc): if is_verbose(): - print "Testing GMP..." + print("Testing GMP...") t = TempFile('tstgmp.cpp') t.add('#include\nint main() { mpz_t t; mpz_init(t); mpz_clear(t); return 0; }\n') t.commit() @@ -190,7 +184,7 @@ def test_gmp(cc): def test_openmp(cc): if is_verbose(): - print "Testing OpenMP..." + print("Testing OpenMP...") t = TempFile('tstomp.cpp') t.add('#include\nint main() { return omp_in_parallel() ? 1 : 0; }\n') t.commit() @@ -201,12 +195,12 @@ def check_java(): t.add('public class Hello { public static void main(String[] args) { System.out.println("Hello, World"); }}\n') t.commit() if is_verbose(): - print "Testing %s..." % JAVAC + print("Testing %s..." % JAVAC) r = exec_cmd([JAVAC, 'Hello.java']) if r != 0: raise MKException('Failed testing Java compiler. Set environment variable JAVAC with the path to the Java compiler') if is_verbose(): - print "Testing %s..." % JAVA + print("Testing %s..." % JAVA) r = exec_cmd([JAVA, 'Hello']) rmf('Hello.class') if r != 0: @@ -224,11 +218,11 @@ def find_java_home(): global JAVA_HOME if JAVA_HOME != None: if is_verbose(): - print "Checking jni.h..." + print("Checking jni.h...") if os.path.exists(os.path.join(JAVA_HOME, 'include', 'jni.h')): return if is_verbose(): - print "Finding JAVA_HOME..." + print("Finding JAVA_HOME...") t = TempFile('output') null = open(os.devnull, 'wb') try: @@ -242,17 +236,17 @@ def find_java_home(): m = open_pat.match(line) if m: # Remove last 3 directives from m.group(1) - print m.group(1) + print(m.group(1)) tmp = m.group(1).split(os.sep) path = string.join(tmp[:len(tmp) - 3], os.sep) if is_verbose(): - print "Checking jni.h..." + print("Checking jni.h...") jni_dir = find_jni_h(path) if not jni_dir: raise MKException("Failed to detect jni.h at '%s'.Possible solution: set JAVA_HOME with the path to JDK." % os.path.join(path, 'include')) JAVA_HOME = os.path.split(jni_dir)[0] if is_verbose(): - print 'JAVA_HOME=%s' % JAVA_HOME + print('JAVA_HOME=%s' % JAVA_HOME) return raise MKException('Failed to find JAVA_HOME') @@ -261,7 +255,7 @@ def is64(): def check_ar(): if is_verbose(): - print "Testing ar..." + print("Testing ar...") if which('ar')== None: raise MKException('ar (archive tool) was not found') @@ -322,7 +316,7 @@ def dos2unix(fname): fout.close() shutil.move(fname_new, fname) if is_verbose(): - print "dos2unix '%s'" % fname + print("dos2unix '%s'" % fname) def dos2unix_tree_core(pattern, dir, files): for filename in files: @@ -339,7 +333,7 @@ def check_eol(): # Linux/OSX/BSD check if the end-of-line is cr/lf if is_cr_lf('LICENSE.txt'): if is_verbose(): - print "Fixing end of line..." + print("Fixing end of line...") dos2unix_tree() if os.name == 'nt': @@ -355,42 +349,42 @@ elif os.name == 'posix': IS_LINUX=True def display_help(exit_code): - print "mk_make.py: Z3 Makefile generator\n" - print "This script generates the Makefile for the Z3 theorem prover." - 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("mk_make.py: Z3 Makefile generator\n") + print("This script generates the Makefile for the Z3 theorem prover.") + 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.") if not IS_WINDOWS: - print " -p , --prefix= installation prefix (default: %s)." % PREFIX - print " -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR + print(" -p , --prefix= installation prefix (default: %s)." % PREFIX) + print(" -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR) else: - print " --parallel=num use cl option /MP with 'num' parallel processes" - print " -b , --build= subdirectory where Z3 will be built (default: build)." - print " -d, --debug compile Z3 in debug mode." - print " -t, --trace enable tracing in release mode." + print(" --parallel=num use cl option /MP with 'num' parallel processes") + print(" -b , --build= subdirectory where Z3 will be built (default: build).") + print(" -d, --debug compile Z3 in debug mode.") + print(" -t, --trace enable tracing in release mode.") if IS_WINDOWS: - print " -x, --x64 create 64 binary when using Visual Studio." - print " -m, --makefiles generate only makefiles." + print(" -x, --x64 create 64 binary when using Visual Studio.") + print(" -m, --makefiles generate only makefiles.") if IS_WINDOWS: - print " -v, --vsproj generate Visual Studio Project Files." + print(" -v, --vsproj generate Visual Studio Project Files.") if IS_WINDOWS: - print " -n, --nodotnet do not generate Microsoft.Z3.dll make rules." - print " -j, --java generate Java bindinds." - print " --staticlib build Z3 static library." + print(" -n, --nodotnet do not generate Microsoft.Z3.dll make rules.") + print(" -j, --java generate Java bindinds.") + print(" --staticlib build Z3 static library.") if not IS_WINDOWS: - print " -g, --gmp use GMP." - print "" - print "Some influential environment variables:" + print(" -g, --gmp use GMP.") + print("") + print("Some influential environment variables:") if not IS_WINDOWS: - print " CXX C++ compiler" - print " CC C compiler" - print " LDFLAGS Linker flags, e.g., -L if you have libraries in a non-standard directory" - print " CPPFLAGS Preprocessor flags, e.g., -I if you have header files in a non-standard directory" - print " CXXFLAGS C++ compiler flags" - print " JAVA Java virtual machine (only relevant if -j or --java option is provided)" - print " JAVAC Java compiler (only relevant if -j or --java option is provided)" - print " JAVA_HOME JDK installation directory (only relevant if -j or --java option is provided)" + print(" CXX C++ compiler") + print(" CC C compiler") + print(" LDFLAGS Linker flags, e.g., -L if you have libraries in a non-standard directory") + print(" CPPFLAGS Preprocessor flags, e.g., -I if you have header files in a non-standard directory") + print(" CXXFLAGS C++ compiler flags") + print(" JAVA Java virtual machine (only relevant if -j or --java option is provided)") + print(" JAVAC Java compiler (only relevant if -j or --java option is provided)") + print(" JAVA_HOME JDK installation directory (only relevant if -j or --java option is provided)") exit(exit_code) # Parse configuration option for mk_make script @@ -403,7 +397,7 @@ def parse_options(): ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=', 'parallel=']) except: - print "ERROR: Invalid command line option" + print("ERROR: Invalid command line option") display_help(1) for opt, arg in options: @@ -446,7 +440,7 @@ def parse_options(): elif opt in ('-j', '--java'): JAVA_ENABLED = True else: - print "ERROR: Invalid command line option '%s'" % opt + print("ERROR: Invalid command line option '%s'" % opt) display_help(1) # Return a list containing a file names included using '#include' in @@ -497,7 +491,7 @@ def set_z3py_dir(p): raise MKException("Python bindings directory '%s' does not exist" % full) Z3PY_SRC_DIR = full if VERBOSE: - print "Python bindinds directory was detected." + print("Python bindinds directory was detected.") _UNIQ_ID = 0 @@ -781,7 +775,7 @@ def comp_components(c1, c2): # Sort components based on (reverse) definition time def sort_components(cnames): - return sorted(cnames, cmp=comp_components) + return sorted(cnames, key=lambda c: get_component(c).id, reverse=True) class ExeComponent(Component): def __init__(self, name, exe_name, path, deps, install): @@ -1196,7 +1190,7 @@ class PythonExampleComponent(ExampleComponent): for py in filter(lambda f: f.endswith('.py'), os.listdir(full)): shutil.copyfile(os.path.join(full, py), os.path.join(BUILD_DIR, py)) if is_verbose(): - print "Copied Z3Py example '%s' to '%s'" % (py, BUILD_DIR) + print("Copied Z3Py example '%s' to '%s'" % (py, BUILD_DIR)) out.write('_ex_%s: \n\n' % self.name) @@ -1208,7 +1202,7 @@ def reg_component(name, c): _ComponentNames.add(name) _Name2Component[name] = c if VERBOSE: - print "New component: '%s'" % name + print("New component: '%s'" % name) def add_lib(name, deps=[], path=None, includes2install=[]): c = LibComponent(name, path, deps, includes2install) @@ -1315,11 +1309,11 @@ def mk_config(): # End of Windows VS config.mk if is_verbose(): - print '64-bit: %s' % is64() + print('64-bit: %s' % is64()) if is_java_enabled(): - print 'Java Home: %s' % JAVA_HOME - print 'Java Compiler: %s' % JAVAC - print 'Java VM: %s' % JAVA + print('Java Home: %s' % JAVA_HOME) + print('Java Compiler: %s' % JAVAC) + print('Java VM: %s' % JAVA) else: global CXX, CC, GMP, CPPFLAGS, CXXFLAGS, LDFLAGS ARITH = "internal" @@ -1401,17 +1395,17 @@ def mk_config(): config.write('SLINK_EXTRA_FLAGS=%s\n' % SLIBEXTRAFLAGS) config.write('SLINK_OUT_FLAG=-o \n') if is_verbose(): - print 'Host platform: %s' % sysname - print 'C++ Compiler: %s' % CXX - print 'C Compiler : %s' % CC - print 'Arithmetic: %s' % ARITH - print 'OpenMP: %s' % HAS_OMP - print 'Prefix: %s' % PREFIX - print '64-bit: %s' % is64() + print('Host platform: %s' % sysname) + print('C++ Compiler: %s' % CXX) + print('C Compiler : %s' % CC) + print('Arithmetic: %s' % ARITH) + print('OpenMP: %s' % HAS_OMP) + print('Prefix: %s' % PREFIX) + print('64-bit: %s' % is64()) if is_java_enabled(): - print 'Java Home: %s' % JAVA_HOME - print 'Java Compiler: %s' % JAVAC - print 'Java VM: %s' % JAVA + print('Java Home: %s' % JAVA_HOME) + print('Java Compiler: %s' % JAVAC) + print('Java VM: %s' % JAVA) def mk_install(out): out.write('install:\n') @@ -1437,7 +1431,7 @@ def mk_makefile(): mk_dir(BUILD_DIR) mk_config() if VERBOSE: - print "Writing %s" % os.path.join(BUILD_DIR, 'Makefile') + print("Writing %s" % os.path.join(BUILD_DIR, 'Makefile')) out = open(os.path.join(BUILD_DIR, 'Makefile'), 'w') out.write('# Automatically generated file.\n') out.write('include config.mk\n') @@ -1465,24 +1459,24 @@ def mk_makefile(): mk_uninstall(out) # Finalize if VERBOSE: - print "Makefile was successfully generated." + print("Makefile was successfully generated.") if not IS_WINDOWS: - print " python packages dir:", PYTHON_PACKAGE_DIR + print(" python packages dir: %s" % PYTHON_PACKAGE_DIR) if DEBUG_MODE: - print " compilation mode: Debug" + print(" compilation mode: Debug") else: - print " compilation mode: Release" + print(" compilation mode: Release") if IS_WINDOWS: if VS_X64: - print " platform: x64\n" - print "To build Z3, open a [Visual Studio x64 Command Prompt], then" + print(" platform: x64\n") + print("To build Z3, open a [Visual Studio x64 Command Prompt], then") else: - print " platform: x86" - print "To build Z3, open a [Visual Studio Command Prompt], then" - print "type 'cd %s && nmake'\n" % os.path.join(os.getcwd(), BUILD_DIR) - print 'Remark: to open a Visual Studio Command Prompt, go to: "Start > All Programs > Visual Studio > Visual Studio Tools"' + print(" platform: x86") + print("To build Z3, open a [Visual Studio Command Prompt], then") + print("type 'cd %s && nmake'\n" % os.path.join(os.getcwd(), BUILD_DIR)) + print('Remark: to open a Visual Studio Command Prompt, go to: "Start > All Programs > Visual Studio > Visual Studio Tools"') else: - print "Type 'cd %s; make' to build Z3" % BUILD_DIR + print("Type 'cd %s; make' to build Z3" % BUILD_DIR) # Generate automatically generated source code def mk_auto_src(): @@ -1577,7 +1571,7 @@ def def_module_params(module_name, export, params, class_name=None, description= out.write('};\n') out.write('#endif\n') if is_verbose(): - print "Generated '%s'" % hpp + print("Generated '%s'" % hpp) def max_memory_param(): return ('max_memory', UINT, UINT_MAX, 'maximum amount of memory in megabytes') @@ -1591,6 +1585,10 @@ PYG_GLOBALS = { 'UINT' : UINT, 'BOOL' : BOOL, 'DOUBLE' : DOUBLE, 'STRING' : STRI 'max_steps_param' : max_steps_param, 'def_module_params' : def_module_params } +def _execfile(file, globals=globals(), locals=locals()): + with open(file, "r") as fh: + exec(fh.read()+"\n", globals, locals) + # Execute python auxiliary scripts that generate extra code for Z3. def exec_pyg_scripts(): global CURR_PYG @@ -1599,7 +1597,7 @@ def exec_pyg_scripts(): if f.endswith('.pyg'): script = os.path.join(root, f) CURR_PYG = script - execfile(script, PYG_GLOBALS) + _execfile(script, PYG_GLOBALS) # TODO: delete after src/ast/pattern/expr_pattern_match # database.smt ==> database.h @@ -1612,7 +1610,7 @@ def mk_pat_db(): fout.write('"%s\\n"\n' % line.strip('\n')) fout.write(';\n') if VERBOSE: - print "Generated '%s'" % os.path.join(c.src_dir, 'database.h') + print("Generated '%s'" % os.path.join(c.src_dir, 'database.h')) # Update version numbers def update_version(): @@ -1637,7 +1635,7 @@ def mk_version_dot_h(major, minor, build, revision): fout.write('#define Z3_BUILD_NUMBER %s\n' % build) fout.write('#define Z3_REVISION_NUMBER %s\n' % revision) if VERBOSE: - print "Generated '%s'" % os.path.join(c.src_dir, 'version.h') + print("Generated '%s'" % os.path.join(c.src_dir, 'version.h')) # Update version number in AssemblyInfo.cs files def update_all_assembly_infos(major, minor, build, revision): @@ -1686,13 +1684,13 @@ def update_assembly_info_version(assemblyinfo, major, minor, build, revision, is else: fout.write(line) # if VERBOSE: - # print "%s version numbers updated at '%s'" % (num_updates, assemblyinfo) + # print("%s version numbers updated at '%s'" % (num_updates, assemblyinfo)) assert num_updates == 2, "unexpected number of version number updates" fin.close() fout.close() shutil.move(tmp, assemblyinfo) if VERBOSE: - print "Updated '%s'" % assemblyinfo + print("Updated '%s'" % assemblyinfo) ADD_TACTIC_DATA=[] ADD_PROBE_DATA=[] @@ -1734,7 +1732,7 @@ def mk_install_tactic_cpp(cnames, path): added_include = True fout.write('#include"%s"\n' % h_file) try: - exec line.strip('\n ') in globals() + exec(line.strip('\n '), globals()) except: raise MKException("Failed processing ADD_TACTIC command at '%s'\n%s" % (fullname, line)) if probe_pat.match(line): @@ -1742,7 +1740,7 @@ def mk_install_tactic_cpp(cnames, path): added_include = True fout.write('#include"%s"\n' % h_file) try: - exec line.strip('\n ') in globals() + exec(line.strip('\n '), globals()) except: raise MKException("Failed processing ADD_PROBE command at '%s'\n%s" % (fullname, line)) # First pass will just generate the tactic factories @@ -1761,7 +1759,7 @@ def mk_install_tactic_cpp(cnames, path): fout.write(' ADD_PROBE("%s", "%s", %s);\n' % data) fout.write('}\n') if VERBOSE: - print "Generated '%s'" % fullname + print("Generated '%s'" % fullname) def mk_all_install_tactic_cpps(): if not ONLY_MAKEFILES: @@ -1824,7 +1822,7 @@ def mk_mem_initializer_cpp(cnames, path): fout.write('\n') fout.write('}\n') if VERBOSE: - print "Generated '%s'" % fullname + print("Generated '%s'" % fullname) def mk_all_mem_initializer_cpps(): if not ONLY_MAKEFILES: @@ -1881,7 +1879,7 @@ def mk_gparams_register_modules(cnames, path): fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr)) fout.write('}\n') if VERBOSE: - print "Generated '%s'" % fullname + print("Generated '%s'" % fullname) def mk_all_gparams_register_modules(): if not ONLY_MAKEFILES: @@ -1914,7 +1912,7 @@ def mk_def_file(c): i = i + 1 num = num + 1 if VERBOSE: - print "Generated '%s'" % defname + print("Generated '%s'" % defname) def mk_def_files(): if not ONLY_MAKEFILES: @@ -1934,7 +1932,7 @@ def cp_z3pyc_to_build(): shutil.copyfile(os.path.join(Z3PY_SRC_DIR, pyc), os.path.join(BUILD_DIR, pyc)) os.remove(os.path.join(Z3PY_SRC_DIR, pyc)) if is_verbose(): - print "Generated '%s'" % pyc + print("Generated '%s'" % pyc) def mk_bindings(api_files): if not ONLY_MAKEFILES: @@ -1945,12 +1943,12 @@ def mk_bindings(api_files): for api_file in api_files: api_file_path = api.find_file(api_file, api.name) new_api_files.append(os.path.join(api_file_path.src_dir, api_file)) - g = {} + g = globals() g["API_FILES"] = new_api_files if is_java_enabled(): check_java() mk_z3consts_java(api_files) - execfile(os.path.join('scripts', 'update_api.py'), g) # HACK + _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3pyc_to_build() # Extract enumeration types from API files, and add python definitions. @@ -2014,7 +2012,8 @@ def mk_z3consts_py(api_files): if m: name = words[1] z3consts.write('# enum %s\n' % name) - for k, i in decls.iteritems(): + for k in decls: + i = decls[k] z3consts.write('%s = %s\n' % (k, i)) z3consts.write('\n') mode = SEARCHING @@ -2028,7 +2027,7 @@ def mk_z3consts_py(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s'" % os.path.join(Z3PY_SRC_DIR, 'z3consts.py') + print("Generated '%s'" % os.path.join(Z3PY_SRC_DIR, 'z3consts.py')) # Extract enumeration types from z3_api.h, and add .Net definitions @@ -2098,7 +2097,8 @@ def mk_z3consts_dotnet(api_files): z3consts.write(' /// %s\n' % name) z3consts.write(' public enum %s {\n' % name) z3consts.write - for k, i in decls.iteritems(): + for k in decls: + i = decls[k] z3consts.write(' %s = %s,\n' % (k, i)) z3consts.write(' }\n\n') mode = SEARCHING @@ -2113,7 +2113,7 @@ def mk_z3consts_dotnet(api_files): linenum = linenum + 1 z3consts.write('}\n'); if VERBOSE: - print "Generated '%s'" % os.path.join(dotnet.src_dir, 'Enumerations.cs') + print("Generated '%s'" % os.path.join(dotnet.src_dir, 'Enumerations.cs')) # Extract enumeration types from z3_api.h, and add Java definitions @@ -2187,7 +2187,8 @@ def mk_z3consts_java(api_files): efile.write('public enum %s {\n' % name) efile.write first = True - for k, i in decls.iteritems(): + for k in decls: + i = decls[k] if first: first = False else: @@ -2218,7 +2219,7 @@ def mk_z3consts_java(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s'" % ('%s' % gendir) + print("Generated '%s'" % ('%s' % gendir)) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id @@ -2305,7 +2306,7 @@ def mk_vs_proj(name, components): f.write(' \n') f.write('\n') if is_verbose(): - print "Generated '%s'" % proj_name + print("Generated '%s'" % proj_name) def mk_win_dist(build_path, dist_path): for c in get_components(): diff --git a/scripts/update_api.py b/scripts/update_api.py index a636a1a02..08dd012e3 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -84,6 +84,19 @@ def lib(): raise Z3Exception("init(Z3_LIBRARY_PATH) must be invoked before using Z3-python") return _lib +def _to_ascii(s): + if isinstance(s, str): + return s.encode('ascii') + else: + return s + +if sys.version < '3': + def _to_pystr(s): + return s +else: + def _to_pystr(s): + return s.decode('utf-8') + def init(PATH): global _lib _lib = ctypes.CDLL(PATH) @@ -146,20 +159,22 @@ next_type_id = FIRST_OBJ_ID def def_Type(var, c_type, py_type): global next_type_id - exec ('%s = %s' % (var, next_type_id)) in globals() + exec('%s = %s' % (var, next_type_id), globals()) Type2Str[next_type_id] = c_type Type2PyStr[next_type_id] = py_type next_type_id = next_type_id + 1 def def_Types(): - pat1 = re.compile(" *def_Type.*") + import re + pat1 = re.compile(" *def_Type\(\'(.*)\',[^\']*\'(.*)\',[^\']*\'(.*)\'\)[ \t]*") for api_file in API_FILES: api = open(api_file, 'r') for line in api: m = pat1.match(line) if m: - eval(line) - for k, v in Type2Str.iteritems(): + def_Type(m.group(1), m.group(2), m.group(3)) + for k in Type2Str: + v = Type2Str[k] if is_obj(k): Type2Dotnet[k] = v @@ -258,7 +273,7 @@ def param2java(p): elif param_type(p) == STRING: return "StringPtr" else: - print "ERROR: unreachable code" + print("ERROR: unreachable code") assert(False) exit(1) if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: @@ -313,6 +328,17 @@ def display_args(num): core_py.write(", ") core_py.write("a%s" % i) +def display_args_to_z3(params): + i = 0 + for p in params: + if i > 0: + core_py.write(", ") + if param_type(p) == STRING: + core_py.write("_to_ascii(a%s)" % i) + else: + core_py.write("a%s" % i) + i = i + 1 + def mk_py_wrappers(): core_py.write("\n") for sig in _API2PY: @@ -327,13 +353,15 @@ def mk_py_wrappers(): core_py.write(" r = lib().%s(" % name) else: core_py.write(" lib().%s(" % name) - display_args(num) + display_args_to_z3(params) core_py.write(")\n") if len(params) > 0 and param_type(params[0]) == CONTEXT: core_py.write(" err = lib().Z3_get_error_code(a0)\n") core_py.write(" if err != Z3_OK:\n") core_py.write(" raise Z3Exception(lib().Z3_get_error_msg_ex(a0, err))\n") - if result != VOID: + if result == STRING: + core_py.write(" return _to_pystr(r)\n") + elif result != VOID: core_py.write(" return r\n") core_py.write("\n") @@ -356,7 +384,8 @@ def mk_dotnet(): dotnet.write('#pragma warning disable 1591\n\n'); dotnet.write('namespace Microsoft.Z3\n') dotnet.write('{\n') - for k, v in Type2Str.iteritems(): + for k in Type2Str: + v = Type2Str[k] if is_obj(k): dotnet.write(' using %s = System.IntPtr;\n' % v) dotnet.write('\n'); @@ -579,7 +608,7 @@ def mk_java(): java_wrapper.write(' } \n\n') java_wrapper.write('#define RELEASELONGAELEMS(OLD,NEW) \\\n') java_wrapper.write(' delete [] NEW; \n\n') - java_wrapper.write('#define GETLONGAREGION(T,OLD,Z,SZ,NEW) \\\n') + java_wrapper.write('#define GETLONGAREGION(T,OLD,Z,SZ,NEW) \\\n') java_wrapper.write(' { \\\n') java_wrapper.write(' jlong * temp = new jlong[SZ]; \\\n') java_wrapper.write(' jenv->GetLongArrayRegion(OLD,Z,(jsize)SZ,(jlong*)temp); \\\n') @@ -702,7 +731,7 @@ def mk_java(): java_wrapper.write('}\n') java_wrapper.write('#endif\n') if is_verbose(): - print "Generated '%s'" % java_nativef + print("Generated '%s'" % java_nativef) def mk_log_header(file, name, params): file.write("void log_%s(" % name) @@ -710,7 +739,7 @@ def mk_log_header(file, name, params): for p in params: if i > 0: file.write(", "); - file.write("%s a%s" % (param2str(p), i)) + file.write("%s a%s" % (param2str(p), i)) i = i + 1 file.write(")"); @@ -981,8 +1010,8 @@ exe_c.close() core_py.close() if is_verbose(): - print "Generated '%s'" % os.path.join(api_dir, 'api_log_macros.h') - print "Generated '%s'" % os.path.join(api_dir, 'api_log_macros.cpp') - print "Generated '%s'" % os.path.join(api_dir, 'api_commands.cpp') - print "Generated '%s'" % os.path.join(get_z3py_dir(), 'z3core.py') - print "Generated '%s'" % os.path.join(dotnet_dir, 'Native.cs') + print("Generated '%s'" % os.path.join(api_dir, 'api_log_macros.h')) + print("Generated '%s'" % os.path.join(api_dir, 'api_log_macros.cpp')) + print("Generated '%s'" % os.path.join(api_dir, 'api_commands.cpp')) + print("Generated '%s'" % os.path.join(get_z3py_dir(), 'z3core.py')) + print("Generated '%s'" % os.path.join(dotnet_dir, 'Native.cs')) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 8a13c7a99..169152ff4 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -37,15 +37,23 @@ Z3 exceptions: ... # the expression x + y is type incorrect ... n = x + y ... except Z3Exception as ex: -... print "failed:", ex +... print("failed: %s" % ex) failed: 'sort mismatch' """ from z3core import * from z3types import * from z3consts import * from z3printer import * +import sys import io +if sys.version < '3': + def _is_int(v): + return isinstance(v, int) or isinstance(v, long) +else: + def _is_int(v): + return isinstance(v, int) + def enable_trace(msg): Z3_enable_trace(msg) @@ -102,12 +110,12 @@ _error_handler_fptr = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint) # list of arguments. def _get_args(args): try: - if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): - return args[0] - else: - return args + if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): + return args[0] + else: + return args except: # len is not necessarily defined when args is not a sequence (use reflection?) - return args + return args def _Z3python_error_handler_core(c, e): # Do nothing error handler, just avoid exit(0) @@ -140,7 +148,8 @@ class Context: if __debug__: _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.") conf = Z3_mk_config() - for key, value in kws.iteritems(): + for key in kws: + value = kws[key] Z3_set_param_value(conf, str(key).upper(), _to_param_value(value)) prev = None for a in args: @@ -209,10 +218,12 @@ def set_param(*args, **kws): if __debug__: _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.") new_kws = {} - for k, v in kws.iteritems(): + for k in kws: + v = kws[k] if not set_pp_option(k, v): new_kws[k] = v - for key, value in new_kws.iteritems(): + for key in new_kws: + value = new_kws[key] Z3_global_param_set(str(key).upper(), _to_param_value(value)) prev = None for a in args: @@ -240,7 +251,7 @@ def get_param(name): """ ptr = (ctypes.c_char_p * 1)() if Z3_global_param_get(str(name), ptr): - r = str(ptr[0]) + r = z3core._to_pystr(ptr[0]) return r raise Z3Exception("failed to retrieve value for '%s'" % name) @@ -899,11 +910,22 @@ def _coerce_exprs(a, b, ctx=None): b = s.cast(b) return (a, b) +def _reduce(f, l, a): + r = a + for e in l: + r = f(r, e) + return r + def _coerce_expr_list(alist, ctx=None): - if filter(is_expr, alist) == []: - alist = map(lambda a: _py2expr(a, ctx), alist) - s = reduce(_coerce_expr_merge, alist, None) - return map(lambda a: s.cast(a), alist) + has_expr = False + for a in alist: + if is_expr(a): + has_expr = True + break + if not has_expr: + alist = [ _py2expr(a, ctx) for a in alist ] + s = _reduce(_coerce_expr_merge, alist, None) + return [ s.cast(a) for a in alist ] def is_expr(a): """Return `True` if `a` is a Z3 expression. @@ -1518,7 +1540,7 @@ def MultiPattern(*args): """ if __debug__: _z3_assert(len(args) > 0, "At least one argument expected") - _z3_assert(all(map(is_expr, args)), "Z3 expressions expected") + _z3_assert(all([ is_expr(a) for a in args ]), "Z3 expressions expected") ctx = args[0].ctx args, sz = _to_ast_array(args) return PatternRef(Z3_mk_pattern(ctx.ref(), sz, args), ctx) @@ -1695,9 +1717,9 @@ def is_quantifier(a): def _mk_quantifier(is_forall, vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]): if __debug__: _z3_assert(is_bool(body), "Z3 expression expected") - _z3_assert(is_const(vs) or (len(vs) > 0 and all(map(is_const, vs))), "Invalid bounded variable(s)") - _z3_assert(all(map(lambda a: is_pattern(a) or is_expr(a), patterns)), "Z3 patterns expected") - _z3_assert(all(map(is_expr, no_patterns)), "no patterns are Z3 expressions") + _z3_assert(is_const(vs) or (len(vs) > 0 and all([ is_const(v) for v in vs])), "Invalid bounded variable(s)") + _z3_assert(all([is_pattern(a) or is_expr(a) for a in patterns]), "Z3 patterns expected") + _z3_assert(all([is_expr(p) for p in no_patterns]), "no patterns are Z3 expressions") ctx = body.ctx if is_app(vs): vs = [vs] @@ -1706,7 +1728,7 @@ def _mk_quantifier(is_forall, vs, body, weight=1, qid="", skid="", patterns=[], for i in range(num_vars): ## TODO: Check if is constant _vs[i] = vs[i].as_ast() - patterns = map(_to_pattern, patterns) + patterns = [ _to_pattern(p) for p in patterns ] num_pats = len(patterns) _pats = (Pattern * num_pats)() for i in range(num_pats): @@ -2008,7 +2030,7 @@ class ArithRef(ExprRef): def __truediv__(self, other): """Create the Z3 expression `other/self`.""" - self.__div__(other) + return self.__div__(other) def __rdiv__(self, other): """Create the Z3 expression `other/self`. @@ -2029,7 +2051,7 @@ class ArithRef(ExprRef): def __rtruediv__(self, other): """Create the Z3 expression `other/self`.""" - self.__rdiv__(other) + return self.__rdiv__(other) def __mod__(self, other): """Create the Z3 expression `other%self`. @@ -2413,11 +2435,11 @@ class IntNumRef(ArithRef): >>> v + 1 1 + 1 >>> v.as_long() + 1 - 2L + 2 """ if __debug__: _z3_assert(self.is_int(), "Integer value expected") - return long(self.as_string()) + return int(self.as_string()) def as_string(self): """Return a Z3 integer numeral as a Python string. @@ -2465,7 +2487,7 @@ class RatNumRef(ArithRef): >>> v + 1 10000000000 + 1 >>> v.numerator_as_long() + 1 - 10000000001L + 10000000001 """ return self.numerator().as_long() @@ -2476,7 +2498,7 @@ class RatNumRef(ArithRef): >>> v 1/3 >>> v.denominator_as_long() - 3L + 3 """ return self.denominator().as_long() @@ -2529,7 +2551,7 @@ class AlgebraicNumRef(ArithRef): def _py2expr(a, ctx=None): if isinstance(a, bool): return BoolVal(a, ctx) - if isinstance(a, int) or isinstance(a, long): + if _is_int(a): return IntVal(a, ctx) if isinstance(a, float): return RealVal(a, ctx) @@ -2576,9 +2598,7 @@ def _to_int_str(val): return "1" else: return "0" - elif isinstance(val, int): - return str(val) - elif isinstance(val, long): + elif _is_int(val): return str(val) elif isinstance(val, str): return val @@ -2625,8 +2645,8 @@ def RatVal(a, b, ctx=None): Real """ if __debug__: - _z3_assert(isinstance(a, int) or isinstance(a, str) or isinstance(a, long), "First argument cannot be converted into an integer") - _z3_assert(isinstance(b, int) or isinstance(b, str) or isinstance(a, long), "Second argument cannot be converted into an integer") + _z3_assert(_is_int(a) or isinstance(a, str), "First argument cannot be converted into an integer") + _z3_assert(_is_int(b) or isinstance(b, str), "Second argument cannot be converted into an integer") return simplify(RealVal(a, ctx)/RealVal(b, ctx)) def Q(a, b, ctx=None): @@ -3078,7 +3098,7 @@ class BitVecRef(ExprRef): def __truediv__(self, other): """Create the Z3 expression (signed) division `self / other`.""" - self.__div__(other) + return self.__div__(other) def __rdiv__(self, other): """Create the Z3 expression (signed) division `other / self`. @@ -3098,7 +3118,7 @@ class BitVecRef(ExprRef): def __rtruediv__(self, other): """Create the Z3 expression (signed) division `other / self`.""" - self.__rdiv__(other) + return self.__rdiv__(other) def __mod__(self, other): """Create the Z3 expression (signed) mod `self % other`. @@ -3218,9 +3238,9 @@ class BitVecRef(ExprRef): >>> BitVecVal(4, 3) 4 >>> BitVecVal(4, 3).as_signed_long() - -4L + -4 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long() - -2L + -2 >>> simplify(BitVecVal(4, 3) >> 1) 6 >>> simplify(LShR(BitVecVal(4, 3), 1)) @@ -3284,32 +3304,32 @@ class BitVecNumRef(BitVecRef): >>> v = BitVecVal(0xbadc0de, 32) >>> v 195936478 - >>> print "0x%.8x" % v.as_long() + >>> print("0x%.8x" % v.as_long()) 0x0badc0de """ - return long(self.as_string()) + return int(self.as_string()) def as_signed_long(self): """Return a Z3 bit-vector numeral as a Python long (bignum) numeral. The most significant bit is assumed to be the sign. >>> BitVecVal(4, 3).as_signed_long() - -4L + -4 >>> BitVecVal(7, 3).as_signed_long() - -1L + -1 >>> BitVecVal(3, 3).as_signed_long() - 3L - >>> BitVecVal(2L**32 - 1, 32).as_signed_long() - -1L - >>> BitVecVal(2L**64 - 1, 64).as_signed_long() - -1L + 3 + >>> BitVecVal(2**32 - 1, 32).as_signed_long() + -1 + >>> BitVecVal(2**64 - 1, 64).as_signed_long() + -1 """ - sz = long(self.size()) + sz = self.size() val = self.as_long() - if val >= 2L**(sz - 1): - val = val - 2L**sz - if val < -2L**(sz - 1): - val = val + 2L**sz - return val + if val >= 2**(sz - 1): + val = val - 2**sz + if val < -2**(sz - 1): + val = val + 2**sz + return int(val) def as_string(self): return Z3_get_numeral_string(self.ctx_ref(), self.as_ast()) @@ -3379,7 +3399,7 @@ def BitVecVal(val, bv, ctx=None): >>> v = BitVecVal(10, 32) >>> v 10 - >>> print "0x%.8x" % v.as_long() + >>> print("0x%.8x" % v.as_long()) 0x0000000a """ if is_bv_sort(bv): @@ -3440,12 +3460,12 @@ def Concat(*args): Concat(Concat(1, 1 + 1), 1) >>> simplify(Concat(v, v+1, v)) 289 - >>> print "%.3x" % simplify(Concat(v, v+1, v)).as_long() + >>> print("%.3x" % simplify(Concat(v, v+1, v)).as_long()) 121 """ args = _get_args(args) if __debug__: - _z3_assert(all(map(is_bv, args)), "All arguments must be Z3 bit-vector expressions.") + _z3_assert(all([is_bv(a) for a in args]), "All arguments must be Z3 bit-vector expressions.") _z3_assert(len(args) >= 2, "At least two arguments expected.") ctx = args[0].ctx r = args[0] @@ -3615,9 +3635,9 @@ def LShR(a, b): >>> BitVecVal(4, 3) 4 >>> BitVecVal(4, 3).as_signed_long() - -4L + -4 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long() - -2L + -2 >>> simplify(BitVecVal(4, 3) >> 1) 6 >>> simplify(LShR(BitVecVal(4, 3), 1)) @@ -3682,7 +3702,7 @@ def SignExt(n, a): 254 >>> v.size() 8 - >>> print "%.x" % v.as_long() + >>> print("%.x" % v.as_long()) fe """ if __debug__: @@ -3727,12 +3747,12 @@ def RepeatBitVec(n, a): >>> n.size() 32 >>> v0 = BitVecVal(10, 4) - >>> print "%.x" % v0.as_long() + >>> print("%.x" % v0.as_long()) a >>> v = simplify(RepeatBitVec(4, v0)) >>> v.size() 16 - >>> print "%.x" % v.as_long() + >>> print("%.x" % v.as_long()) aaaa """ if __debug__: @@ -4006,7 +4026,7 @@ def Map(f, *args): if __debug__: _z3_assert(len(args) > 0, "At least one Z3 array expression expected") _z3_assert(is_func_decl(f), "First argument must be a Z3 function declaration") - _z3_assert(all(map(is_array, args)), "Z3 array expected expected") + _z3_assert(all([is_array(a) for a in args]), "Z3 array expected expected") _z3_assert(len(args) == f.arity(), "Number of arguments mismatch") _args, sz = _to_ast_array(args) ctx = f.ctx @@ -4100,7 +4120,7 @@ class Datatype: if __debug__: _z3_assert(isinstance(name, str), "String expected") _z3_assert(isinstance(rec_name, str), "String expected") - _z3_assert(all(map(_valid_accessor, args)), "Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort)") + _z3_assert(all([_valid_accessor(a) for a in args]), "Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort)") self.constructors.append((name, rec_name, args)) def declare(self, name, *args): @@ -4187,9 +4207,9 @@ def CreateDatatypes(*ds): ds = _get_args(ds) if __debug__: _z3_assert(len(ds) > 0, "At least one Datatype must be specified") - _z3_assert(all(map(lambda d: isinstance(d, Datatype), ds)), "Arguments must be Datatypes") - _z3_assert(all(map(lambda d: d.ctx == ds[0].ctx, ds)), "Context mismatch") - _z3_assert(all(map(lambda d: d.constructors != [], ds)), "Non-empty Datatypes expected") + _z3_assert(all([isinstance(d, Datatype) for d in ds]), "Arguments must be Datatypes") + _z3_assert(all([d.ctx == ds[0].ctx for d in ds]), "Context mismatch") + _z3_assert(all([d.constructors != [] for d in ds]), "Non-empty Datatypes expected") ctx = ds[0].ctx num = len(ds) names = (Symbol * num)() @@ -4355,7 +4375,7 @@ def EnumSort(name, values, ctx=None): """ if __debug__: _z3_assert(isinstance(name, str), "Name must be a string") - _z3_assert(all(map(lambda v: isinstance(v, str), values)), "Eumeration sort values must be strings") + _z3_assert(all([isinstance(v, str) for v in values]), "Eumeration sort values must be strings") _z3_assert(len(values) > 0, "At least one value expected") ctx = _get_ctx(ctx) num = len(values) @@ -4369,7 +4389,7 @@ def EnumSort(name, values, ctx=None): V = [] for i in range(num): V.append(FuncDeclRef(_values[i], ctx)) - V = map(lambda a: a(), V) + V = [a() for a in V] return S, V ######################################### @@ -4432,7 +4452,8 @@ def args2params(arguments, keywords, ctx=None): else: r.set(prev, a) prev = None - for k, v in keywords.iteritems(): + for k in keywords: + v = keywords[k] r.set(k, v) return r @@ -4469,7 +4490,7 @@ class ParamDescrsRef: return Z3_param_descrs_get_kind(self.ctx.ref(), self.descr, to_symbol(n, self.ctx)) def __getitem__(self, arg): - if isinstance(arg, int) or isinstance(arg, long): + if _is_int(arg): return self.get_name(arg) else: return self.get_kind(arg) @@ -5057,7 +5078,7 @@ class FuncEntry: >>> try: ... e.arg_value(2) ... except IndexError: - ... print "index error" + ... print("index error") index error """ if idx >= self.num_args(): @@ -5435,7 +5456,7 @@ class ModelRef(Z3PPObject): 1 >>> m[f] [1 -> 0, else -> 0] - >>> for d in m: print "%s -> %s" % (d, m[d]) + >>> for d in m: print("%s -> %s" % (d, m[d])) x -> 1 f -> [1 -> 0, else -> 0] """ @@ -5506,16 +5527,16 @@ class Statistics: if in_html_mode(): out = io.StringIO() even = True - out.write(u'') + out.write(u('
')) for k, v in self: if even: - out.write(u'') + out.write(u('')) even = False else: - out.write(u'') + out.write(u('')) even = True - out.write(u'' % (k, v)) - out.write(u'
%s%s
') + out.write(u('%s%s' % (k, v))) + out.write(u('')) return out.getvalue() else: return Z3_stats_to_string(self.ctx.ref(), self.stats) @@ -5813,7 +5834,7 @@ class Solver(Z3PPObject): >>> s.assert_and_track(x > 0, 'p1') >>> s.assert_and_track(x != 1, 'p2') >>> s.assert_and_track(x < 0, p3) - >>> print s.check() + >>> print(s.check()) unsat >>> c = s.unsat_core() >>> len(c) @@ -5961,7 +5982,7 @@ class Solver(Z3PPObject): def help(self): """Display a string describing all available options.""" - print Z3_solver_get_help(self.ctx.ref(), self.solver) + print(Z3_solver_get_help(self.ctx.ref(), self.solver)) def param_descrs(self): """Return the parameter description set.""" @@ -6032,7 +6053,7 @@ class Fixedpoint(Z3PPObject): else: self.fixedpoint = fixedpoint Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint) - self.vars = [] + self.vars = [] def __del__(self): if self.fixedpoint != None: @@ -6046,8 +6067,8 @@ class Fixedpoint(Z3PPObject): def help(self): """Display a string describing all available options.""" - print Z3_fixedpoint_get_help(self.ctx.ref(), self.fixedpoint) - + print(Z3_fixedpoint_get_help(self.ctx.ref(), self.fixedpoint)) + def param_descrs(self): """Return the parameter description set.""" return ParamDescrsRef(Z3_fixedpoint_get_param_descrs(self.ctx.ref(), self.fixedpoint), self.ctx) @@ -6059,11 +6080,11 @@ class Fixedpoint(Z3PPObject): for arg in args: if isinstance(arg, Goal) or isinstance(arg, AstVector): for f in arg: - f = self.abstract(f) + f = self.abstract(f) Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, f.as_ast()) else: arg = s.cast(arg) - arg = self.abstract(arg) + arg = self.abstract(arg) Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, arg.as_ast()) def add(self, *args): @@ -6079,38 +6100,38 @@ class Fixedpoint(Z3PPObject): self.assert_exprs(*args) def add_rule(self, head, body = None, name = None): - """Assert rules defining recursive predicates to the fixedpoint solver. + """Assert rules defining recursive predicates to the fixedpoint solver. >>> a = Bool('a') - >>> b = Bool('b') + >>> b = Bool('b') >>> s = Fixedpoint() - >>> s.register_relation(a.decl()) - >>> s.register_relation(b.decl()) - >>> s.fact(a) + >>> s.register_relation(a.decl()) + >>> s.register_relation(b.decl()) + >>> s.fact(a) >>> s.rule(b, a) - >>> s.query(b) - sat - """ - if name == None: - name = "" + >>> s.query(b) + sat + """ + if name == None: + name = "" name = to_symbol(name, self.ctx) - if body == None: - head = self.abstract(head) - 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)) - Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) - + if body == None: + head = self.abstract(head) + 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)) + Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) + def rule(self, head, body = None, name = None): - """Assert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" - self.add_rule(head, body, name) - + """Assert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" + self.add_rule(head, body, name) + def fact(self, head, name = None): - """Assert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" - self.add_rule(head, None, name) + """Assert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" + self.add_rule(head, None, name) def query(self, *query): - """Query the fixedpoint engine whether formula is derivable. + """Query the fixedpoint engine whether formula is derivable. You can also pass an tuple or list of recursive predicates. """ query = _get_args(query) @@ -6141,17 +6162,17 @@ class Fixedpoint(Z3PPObject): def update_rule(self, head, body, name): """update rule""" - if name == None: - name = "" + if name == None: + name = "" name = to_symbol(name, self.ctx) body = _get_args(body) f = self.abstract(Implies(And(body),head)) - Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) + Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) - def get_answer(self): - """Retrieve answer from last query call.""" - r = Z3_fixedpoint_get_answer(self.ctx.ref(), self.fixedpoint) - return _to_expr_ref(r, self.ctx) + def get_answer(self): + """Retrieve answer from last query call.""" + r = Z3_fixedpoint_get_answer(self.ctx.ref(), self.fixedpoint) + return _to_expr_ref(r, self.ctx) def get_num_levels(self, predicate): """Retrieve number of levels used for predicate in PDR engine""" @@ -6167,40 +6188,40 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_add_cover(self.ctx.ref(), self.fixedpoint, level, predicate.ast, property.ast) def register_relation(self, *relations): - """Register relation as recursive""" - relations = _get_args(relations) - for f in relations: - Z3_fixedpoint_register_relation(self.ctx.ref(), self.fixedpoint, f.ast) + """Register relation as recursive""" + relations = _get_args(relations) + for f in relations: + Z3_fixedpoint_register_relation(self.ctx.ref(), self.fixedpoint, f.ast) def set_predicate_representation(self, f, *representations): - """Control how relation is represented""" - representations = _get_args(representations) - representations = map(to_symbol, representations) - sz = len(representations) - args = (Symbol * sz)() - for i in range(sz): - args[i] = representations[i] - Z3_fixedpoint_set_predicate_representation(self.ctx.ref(), self.fixedpoint, f.ast, sz, args) + """Control how relation is represented""" + representations = _get_args(representations) + representations = [to_symbol(s) for s in representations] + sz = len(representations) + args = (Symbol * sz)() + for i in range(sz): + args[i] = representations[i] + Z3_fixedpoint_set_predicate_representation(self.ctx.ref(), self.fixedpoint, f.ast, sz, args) def parse_string(self, s): - """Parse rules and queries from a string""" - return AstVector(Z3_fixedpoint_from_string(self.ctx.ref(), self.fixedpoint, s), self.ctx) - + """Parse rules and queries from a string""" + return AstVector(Z3_fixedpoint_from_string(self.ctx.ref(), self.fixedpoint, s), self.ctx) + def parse_file(self, f): - """Parse rules and queries from a file""" - return AstVector(Z3_fixedpoint_from_file(self.ctx.ref(), self.fixedpoint, f), self.ctx) + """Parse rules and queries from a file""" + return AstVector(Z3_fixedpoint_from_file(self.ctx.ref(), self.fixedpoint, f), self.ctx) def get_rules(self): - """retrieve rules that have been added to fixedpoint context""" - return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx) + """retrieve rules that have been added to fixedpoint context""" + return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx) def get_assertions(self): - """retrieve assertions that have been added to fixedpoint context""" - return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx) + """retrieve assertions that have been added to fixedpoint context""" + return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx) def __repr__(self): """Return a formatted string with all added rules and constraints.""" - return self.sexpr() + return self.sexpr() def sexpr(self): """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format. @@ -6208,16 +6229,16 @@ class Fixedpoint(Z3PPObject): return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, 0, (Ast * 0)()) def to_string(self, queries): - """Return a formatted string (in Lisp-like format) with all added constraints. + """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format. - Include also queries. + Include also queries. """ - args, len = _to_ast_array(queries) + args, len = _to_ast_array(queries) return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, len, args) def statistics(self): """Return statistics for the last `query()`. - """ + """ return Statistics(Z3_fixedpoint_get_statistics(self.ctx.ref(), self.fixedpoint), self.ctx) def reason_unknown(self): @@ -6226,21 +6247,21 @@ class Fixedpoint(Z3PPObject): return Z3_fixedpoint_get_reason_unknown(self.ctx.ref(), self.fixedpoint) def declare_var(self, *vars): - """Add variable or several variables. - The added variable or variables will be bound in the rules - and queries - """ - vars = _get_args(vars) - for v in vars: - self.vars += [v] - + """Add variable or several variables. + The added variable or variables will be bound in the rules + and queries + """ + vars = _get_args(vars) + for v in vars: + self.vars += [v] + def abstract(self, fml, is_forall=True): - if self.vars == []: - return fml - if is_forall: - return ForAll(self.vars, fml) - else: - return Exists(self.vars, fml) + if self.vars == []: + return fml + if is_forall: + return ForAll(self.vars, fml) + else: + return Exists(self.vars, fml) ######################################### # @@ -6432,7 +6453,7 @@ class Tactic: def help(self): """Display a string containing a description of the available options for the `self` tactic.""" - print Z3_tactic_get_help(self.ctx.ref(), self.tactic) + print(Z3_tactic_get_help(self.ctx.ref(), self.tactic)) def param_descrs(self): """Return the parameter description set.""" @@ -6528,7 +6549,7 @@ def ParOr(*ts, **ks): if __debug__: _z3_assert(len(ts) >= 2, "At least two arguments expected") ctx = _get_ctx(ks.get('ctx', None)) - ts = map(lambda t: _to_tactic(t, ctx), ts) + ts = [ _to_tactic(t, ctx) for t in ts ] sz = len(ts) _args = (TacticObj * sz)() for i in range(sz): @@ -6573,7 +6594,7 @@ def Repeat(t, max=4294967295, ctx=None): >>> c = And(Or(x == 0, x == 1), Or(y == 0, y == 1), x > y) >>> t = Repeat(OrElse(Tactic('split-clause'), Tactic('skip'))) >>> r = t(c) - >>> for subgoal in r: print subgoal + >>> for subgoal in r: print(subgoal) [x == 0, y == 0, x > y] [x == 0, y == 1, x > y] [x == 1, y == 0, x > y] @@ -6615,19 +6636,19 @@ def describe_tactics(): """Display a (tabular) description of all available tactics in Z3.""" if in_html_mode(): even = True - print '' + print('
') for t in tactics(): if even: - print '' + print('') even = False else: - print '' + print('') even = True - print '' % (t, insert_line_breaks(tactic_description(t), 40)) - print '
%s%s
' + print('%s%s' % (t, insert_line_breaks(tactic_description(t), 40))) + print('') else: for t in tactics(): - print '%s : %s' % (t, tactic_description(t)) + print('%s : %s' % (t, tactic_description(t))) class Probe: """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.""" @@ -6638,7 +6659,7 @@ class Probe: self.probe = probe elif isinstance(probe, float): self.probe = Z3_probe_const(self.ctx.ref(), probe) - elif isinstance(probe, int) or isinstance(probe, long): + elif _is_int(probe): self.probe = Z3_probe_const(self.ctx.ref(), float(probe)) elif isinstance(probe, bool): if probe: @@ -6803,19 +6824,19 @@ def describe_probes(): """Display a (tabular) description of all available probes in Z3.""" if in_html_mode(): even = True - print '' + print('
') for p in probes(): if even: - print '' + print('') even = False else: - print '' + print('') even = True - print '' % (p, insert_line_breaks(probe_description(p), 40)) - print '
%s%s
' + print('%s%s' % (p, insert_line_breaks(probe_description(p), 40))) + print('') else: for p in probes(): - print '%s : %s' % (p, probe_description(p)) + print('%s : %s' % (p, probe_description(p))) def _probe_nary(f, args, ctx): if __debug__: @@ -6911,7 +6932,7 @@ def simplify(a, *arguments, **keywords): def help_simplify(): """Return a string describing all options available for Z3 `simplify` procedure.""" - print Z3_simplify_get_help(main_ctx().ref()) + print(Z3_simplify_get_help(main_ctx().ref())) def simplify_param_descrs(): """Return the set of parameter descriptions for Z3 `simplify` procedure.""" @@ -6934,7 +6955,7 @@ def substitute(t, *m): m = _get_args(m1) if __debug__: _z3_assert(is_expr(t), "Z3 expression expected") - _z3_assert(all(map(lambda p: isinstance(p, tuple) and is_expr(p[0]) and is_expr(p[1]) and p[0].sort().eq(p[1].sort()), m)), "Z3 invalid substitution, expression pairs expected.") + _z3_assert(all([isinstance(p, tuple) and is_expr(p[0]) and is_expr(p[1]) and p[0].sort().eq(p[1].sort()) for p in m]), "Z3 invalid substitution, expression pairs expected.") num = len(m) _from = (Ast * num)() _to = (Ast * num)() @@ -6956,7 +6977,7 @@ def substitute_vars(t, *m): """ if __debug__: _z3_assert(is_expr(t), "Z3 expression expected") - _z3_assert(all(map(is_expr, m)), "Z3 invalid substitution, list of expressions expected.") + _z3_assert(all([is_expr(n) for n in m]), "Z3 invalid substitution, list of expressions expected.") num = len(m) _to = (Ast * num)() for i in range(num): @@ -6983,7 +7004,7 @@ def Sum(*args): _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression") args = _coerce_expr_list(args, ctx) if is_bv(args[0]): - return reduce(lambda a, b: a + b, args, 0) + return _reduce(lambda a, b: a + b, args, 0) else: _args, sz = _to_ast_array(args) return ArithRef(Z3_mk_add(ctx.ref(), sz, _args), ctx) @@ -7008,7 +7029,7 @@ def Product(*args): _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression") args = _coerce_expr_list(args, ctx) if is_bv(args[0]): - return reduce(lambda a, b: a * b, args, 1) + return _reduce(lambda a, b: a * b, args, 1) else: _args, sz = _to_ast_array(args) return ArithRef(Z3_mk_mul(ctx.ref(), sz, _args), ctx) @@ -7028,18 +7049,18 @@ def solve(*args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print s + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: - print s.model() + print(s.model()) def solve_using(s, *args, **keywords): """Solve the constraints `*args` using solver `s`. @@ -7054,21 +7075,21 @@ def solve_using(s, *args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print "Problem:" - print s + print("Problem:") + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: if keywords.get('show', False): - print "Solution:" - print s.model() + print("Solution:") + print(s.model()) def prove(claim, **keywords): """Try to prove the given claim. @@ -7086,16 +7107,16 @@ def prove(claim, **keywords): s.set(**keywords) s.add(Not(claim)) if keywords.get('show', False): - print s + print(s) r = s.check() if r == unsat: - print "proved" + print("proved") elif r == unknown: - print "failed to prove" - print s.model() + print("failed to prove") + print(s.model()) else: - print "counterexample" - print s.model() + print("counterexample") + print(s.model()) def _solve_html(*args, **keywords): """Version of funcion `solve` used in RiSE4Fun.""" @@ -7103,21 +7124,21 @@ def _solve_html(*args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print "Problem:" - print s + print("Problem:") + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: if keywords.get('show', False): - print "Solution:" - print s.model() + print("Solution:") + print(s.model()) def _solve_using_html(s, *args, **keywords): """Version of funcion `solve_using` used in RiSE4Fun.""" @@ -7126,21 +7147,21 @@ def _solve_using_html(s, *args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print "Problem:" - print s + print("Problem:") + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: if keywords.get('show', False): - print "Solution:" - print s.model() + print("Solution:") + print(s.model()) def _prove_html(claim, **keywords): """Version of funcion `prove` used in RiSE4Fun.""" @@ -7150,23 +7171,24 @@ def _prove_html(claim, **keywords): s.set(**keywords) s.add(Not(claim)) if keywords.get('show', False): - print s + print(s) r = s.check() if r == unsat: - print "proved" + print("proved") elif r == unknown: - print "failed to prove" - print s.model() + print("failed to prove") + print(s.model()) else: - print "counterexample" - print s.model() + print("counterexample") + print(s.model()) def _dict2sarray(sorts, ctx): sz = len(sorts) _names = (Symbol * sz)() _sorts = (Sort * sz) () i = 0 - for k, v in sorts.iteritems(): + for k in sorts: + v = sorts[k] if __debug__: _z3_assert(isinstance(k, str), "String expected") _z3_assert(is_sort(v), "Z3 sort expected") @@ -7180,7 +7202,8 @@ def _dict2darray(decls, ctx): _names = (Symbol * sz)() _decls = (FuncDecl * sz) () i = 0 - for k, v in decls.iteritems(): + for k in decls: + v = decls[k] if __debug__: _z3_assert(isinstance(k, str), "String expected") _z3_assert(is_func_decl(v) or is_const(v), "Z3 declaration or constant expected") diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index 3ad8f21b9..d3dc43d3e 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -74,6 +74,15 @@ def _is_add(k): def _is_sub(k): return k == Z3_OP_SUB or k == Z3_OP_BSUB +import sys +if sys.version < '3': + import codecs + def u(x): + return codecs.unicode_escape_decode(x)[0] +else: + def u(x): + return x + _z3_infix_compact = [ Z3_OP_MUL, Z3_OP_BMUL, Z3_OP_POWER, Z3_OP_DIV, Z3_OP_IDIV, Z3_OP_MOD, Z3_OP_BSDIV, Z3_OP_BSMOD ] _ellipses = '...' @@ -161,15 +170,19 @@ def _get_precedence(k): return _z3_precedence.get(k, 100000) _z3_html_op_to_str = {} -for _k, _v in _z3_op_to_str.iteritems(): +for _k in _z3_op_to_str: + _v = _z3_op_to_str[_k] _z3_html_op_to_str[_k] = _v -for _k, _v in _z3_pre_html_op_to_str.iteritems(): +for _k in _z3_pre_html_op_to_str: + _v = _z3_pre_html_op_to_str[_k] _z3_html_op_to_str[_k] = _v _z3_html_precedence = {} -for _k, _v in _z3_precedence.iteritems(): +for _k in _z3_precedence: + _v = _z3_precedence[_k] _z3_html_precedence[_k] = _v -for _k, _v in _z3_pre_html_precedence.iteritems(): +for _k in _z3_pre_html_precedence: + _v = _z3_pre_html_precedence[_k] _z3_html_precedence[_k] = _v _html_infix_map = {} @@ -237,7 +250,7 @@ class FormatObject: class NAryFormatObject(FormatObject): def __init__(self, fs): - assert all(map(lambda a: isinstance(a, FormatObject), fs)) + assert all([isinstance(a, FormatObject) for a in fs]) self.children = fs def children(self): return self.children @@ -246,7 +259,7 @@ class ComposeFormatObject(NAryFormatObject): def is_compose(sef): return True def as_tuple(self): - return ('compose', map(lambda a: a.as_tuple(), self.children)) + return ('compose', [ a.as_tuple() for a in self.children ]) def space_upto_nl(self): r = 0 for child in self.children: @@ -256,13 +269,13 @@ class ComposeFormatObject(NAryFormatObject): return (r, True) return (r, False) def flat(self): - return compose(map(lambda a: a.flat(), self.children)) + return compose([a.flat() for a in self.children ]) class ChoiceFormatObject(NAryFormatObject): def is_choice(sef): return True def as_tuple(self): - return ('choice', map(lambda a: a.as_tuple(), self.children)) + return ('choice', [ a.as_tuple() for a in self.children ]) def space_upto_nl(self): return self.children[0].space_upto_nl() def flat(self): @@ -388,11 +401,11 @@ class PP: if not self.bounded or self.pos <= self.max_width: sz = _len(f) if self.bounded and self.pos + sz > self.max_width: - self.out.write(_ellipses) + self.out.write(u(_ellipses)) else: self.pos = self.pos + sz self.ribbon_pos = self.ribbon_pos + sz - self.out.write(unicode(f.string)) + self.out.write(u(f.string)) def pp_compose(self, f, indent): for c in f.children: @@ -410,11 +423,11 @@ class PP: self.ribbon_pos = 0 self.line = self.line + 1 if self.line < self.max_lines: - self.out.write(unicode('\n')) + self.out.write(u('\n')) for i in range(indent): - self.out.write(unicode(' ')) + self.out.write(u(' ')) else: - self.out.write(unicode('\n...')) + self.out.write(u('\n...')) raise StopPPException() def pp(self, f, indent): @@ -957,23 +970,23 @@ def in_html_mode(): def pp(a): if _support_pp(a): - print obj_to_string(a) + print(obj_to_string(a)) else: - print a + print(a) def print_matrix(m): z3._z3_assert(isinstance(m, list) or isinstance(m, tuple), "matrix expected") if not in_html_mode(): - print obj_to_string(m) + print(obj_to_string(m)) else: - print '' + print('
') for r in m: z3._z3_assert(isinstance(r, list) or isinstance(r, tuple), "matrix expected") - print '' + print('') for c in r: - print '' % c - print '' - print '
%s
' + print('%s' % c) + print('') + print('') def insert_line_breaks(s, width): """Break s in lines of size width (approx)""" @@ -984,9 +997,9 @@ def insert_line_breaks(s, width): w = 0 for i in range(sz): if w > width and s[i] == ' ': - new_str.write(u'
') + new_str.write(u('
')) w = 0 else: - new_str.write(unicode(s[i])) + new_str.write(u(s[i])) w = w + 1 return new_str.getvalue() From 3cc9d57438cb8f4e56122a63e7b18d7d99478c5b Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 21 Dec 2012 16:58:10 -0800 Subject: [PATCH 57/57] Fix pytest, it should work with Python 2.7.x and 3.x Signed-off-by: Leonardo de Moura --- src/api/python/z3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 169152ff4..9b1d5f1f0 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -2486,8 +2486,8 @@ class RatNumRef(ArithRef): 10000000000 >>> v + 1 10000000000 + 1 - >>> v.numerator_as_long() + 1 - 10000000001 + >>> v.numerator_as_long() + 1 == 10000000001 + True """ return self.numerator().as_long()