From 13b61d894c0c352b2baa1e3c3cae7a939e97c160 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Tue, 9 Sep 2014 14:02:46 -0700 Subject: [PATCH 001/117] adding recursion bounds to duality --- src/duality/duality.h | 5 +++-- src/duality/duality_rpfp.cpp | 5 ++++- src/duality/duality_solver.cpp | 23 ++++++++++++++++------- src/muz/base/dl_context.cpp | 8 ++++++-- src/muz/base/dl_context.h | 5 +++-- src/muz/duality/duality_dl_interface.cpp | 17 ++++++++++++++--- src/muz/fp/dl_cmds.cpp | 20 ++++++++++++++------ 7 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/duality/duality.h b/src/duality/duality.h index c1c9797f3..16576dd65 100755 --- a/src/duality/duality.h +++ b/src/duality/duality.h @@ -488,9 +488,10 @@ protected: std::vector Incoming; Term dual; Node *map; + unsigned recursion_bound; Node(const FuncDecl &_Name, const Transformer &_Annotation, const Transformer &_Bound, const Transformer &_Underapprox, const Term &_dual, RPFP *_owner, int _number) - : Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0;} + : Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0; recursion_bound = UINT_MAX;} }; /** Create a node in the graph. The input is a term R(v_1...v_n) @@ -829,7 +830,7 @@ protected: #ifdef _WINDOWS __declspec(dllexport) #endif - void FromClauses(const std::vector &clauses); + void FromClauses(const std::vector &clauses, const std::vector *bounds = 0); void FromFixpointContext(fixedpoint fp, std::vector &queries); diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index ef37dd8a2..8c88dda72 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -3570,7 +3570,7 @@ namespace Duality { #define USE_QE_LITE - void RPFP::FromClauses(const std::vector &unskolemized_clauses){ + void RPFP::FromClauses(const std::vector &unskolemized_clauses, const std::vector *bounds){ hash_map pmap; func_decl fail_pred = ctx.fresh_func_decl("@Fail", ctx.bool_sort()); @@ -3663,6 +3663,7 @@ namespace Duality { pmap[R] = node; if (is_query) node->Bound = CreateRelation(std::vector(), ctx.bool_val(false)); + node->recursion_bound = bounds ? 0 : UINT_MAX; } } @@ -3728,6 +3729,8 @@ namespace Duality { Transformer T = CreateTransformer(Relparams,Indparams,body); Edge *edge = CreateEdge(Parent,T,Children); edge->labeled = labeled;; // remember for label extraction + if(bounds) + Parent->recursion_bound = std::max(Parent->recursion_bound,(*bounds)[i]); // edges.push_back(edge); } diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index 681582415..f54e00693 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -33,6 +33,7 @@ Revision History: #include #include #include +#include // TODO: make these official options or get rid of them @@ -304,7 +305,7 @@ namespace Duality { #ifdef BOUNDED struct Counter { - int val; + unsigned val; Counter(){val = 0;} }; typedef std::map NodeToCounter; @@ -321,6 +322,10 @@ namespace Duality { heuristic = !cex.get_tree() ? (Heuristic *)(new LocalHeuristic(rpfp)) : (Heuristic *)(new ReplayHeuristic(rpfp,cex)); #endif + // determine if we are recursion bounded + for(unsigned i = 0; i < rpfp->nodes.size(); i++) + if(rpfp->nodes[i]->recursion_bound < UINT_MAX) + RecursionBound = 0; cex.clear(); // in case we didn't use it for heuristic if(unwinding) delete unwinding; unwinding = new RPFP(rpfp->ls); @@ -461,7 +466,7 @@ namespace Duality { } return false; } - + /** Create an instance of a node in the unwinding. Set its annotation to true, and mark it unexpanded. */ Node* CreateNodeInstance(Node *node, int number = 0){ @@ -780,10 +785,8 @@ namespace Duality { std::vector &insts = insts_of_node[node]; for(unsigned j = 0; j < insts.size(); j++) if(indset->Contains(insts[j])) - if(NodePastRecursionBound(insts[j])){ + if(NodePastRecursionBound(insts[j],true)) recursionBounded = true; - return; - } } } @@ -801,12 +804,18 @@ namespace Duality { } #ifdef BOUNDED - bool NodePastRecursionBound(Node *node){ + bool NodePastRecursionBound(Node *node, bool report = false){ if(RecursionBound < 0) return false; NodeToCounter &backs = back_edges[node]; for(NodeToCounter::iterator it = backs.begin(), en = backs.end(); it != en; ++it){ - if(it->second.val > RecursionBound) + if(it->second.val > it->first->recursion_bound){ + if(report){ + std::ostringstream os; + os << "cut off " << it->first->Name.name() << " at depth " << it->second.val; + reporter->Message(os.str()); + } return true; + } } return false; } diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index fbef46ae3..80af7eeb0 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -246,6 +246,7 @@ namespace datalog { m_rule_fmls_head = 0; m_rule_fmls.reset(); m_rule_names.reset(); + m_rule_bounds.reset(); m_argument_var_names.reset(); m_preds.reset(); m_preds_by_name.reset(); @@ -474,9 +475,10 @@ namespace datalog { return new_pred; } - void context::add_rule(expr* rl, symbol const& name) { + void context::add_rule(expr* rl, symbol const& name, unsigned bound) { m_rule_fmls.push_back(rl); m_rule_names.push_back(name); + m_rule_bounds.push_back(bound); } void context::flush_add_rules() { @@ -1102,12 +1104,13 @@ namespace datalog { } } - void context::get_raw_rule_formulas(expr_ref_vector& rules, svector& names){ + void context::get_raw_rule_formulas(expr_ref_vector& rules, svector& names, vector &bounds){ for (unsigned i = 0; i < m_rule_fmls.size(); ++i) { expr_ref r = bind_variables(m_rule_fmls[i].get(), true); rules.push_back(r.get()); // rules.push_back(m_rule_fmls[i].get()); names.push_back(m_rule_names[i]); + bounds.push_back(m_rule_bounds[i]); } } @@ -1125,6 +1128,7 @@ namespace datalog { m_rule_names[i] = m_rule_names.back(); m_rule_fmls.pop_back(); m_rule_names.pop_back(); + m_rule_bounds.pop_back(); --i; } } diff --git a/src/muz/base/dl_context.h b/src/muz/base/dl_context.h index 7349fa889..cf2c53913 100644 --- a/src/muz/base/dl_context.h +++ b/src/muz/base/dl_context.h @@ -194,6 +194,7 @@ namespace datalog { unsigned m_rule_fmls_head; expr_ref_vector m_rule_fmls; svector m_rule_names; + vector m_rule_bounds; expr_ref_vector m_background; model_converter_ref m_mc; proof_converter_ref m_pc; @@ -366,7 +367,7 @@ namespace datalog { rule_set & get_rules() { flush_add_rules(); return m_rule_set; } void get_rules_as_formulas(expr_ref_vector& fmls, svector& names); - void get_raw_rule_formulas(expr_ref_vector& fmls, svector& names); + void get_raw_rule_formulas(expr_ref_vector& fmls, svector& names, vector &bounds); void add_fact(app * head); void add_fact(func_decl * pred, const relation_fact & fact); @@ -383,7 +384,7 @@ namespace datalog { /** Method exposed from API for adding rules. */ - void add_rule(expr* rl, symbol const& name); + void add_rule(expr* rl, symbol const& name, unsigned bound = UINT_MAX); /** diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 849cf94ea..08c57b05e 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -155,8 +155,9 @@ lbool dl_interface::query(::expr * query) { expr_ref_vector rules(m_ctx.get_manager()); svector< ::symbol> names; + vector bounds; // m_ctx.get_rules_as_formulas(rules, names); - m_ctx.get_raw_rule_formulas(rules, names); + m_ctx.get_raw_rule_formulas(rules, names, bounds); // get all the rules as clauses std::vector &clauses = _d->clauses; @@ -200,6 +201,7 @@ lbool dl_interface::query(::expr * query) { expr qc = implies(q,_d->ctx.bool_val(false)); qc = _d->ctx.make_quant(Forall,b_sorts,b_names,qc); clauses.push_back(qc); + bounds.push_back(UINT_MAX); // get the background axioms unsigned num_asserts = m_ctx.get_num_assertions(); @@ -243,13 +245,21 @@ lbool dl_interface::query(::expr * query) { expr c = implies(_d->ctx.bool_val(false),f(args)); c = _d->ctx.make_quant(Forall,args,c); clauses.push_back(c); + bounds.push_back(UINT_MAX); } } } } + unsigned rb = m_ctx.get_params().recursion_bound(); + std::vector std_bounds; + for(unsigned i = 0; i < bounds.size(); i++){ + unsigned b = bounds[i]; + if (b == UINT_MAX) b = rb; + std_bounds.push_back(b); + } // creates 1-1 map between clauses and rpfp edges - _d->rpfp->FromClauses(clauses); + _d->rpfp->FromClauses(clauses,&std_bounds); // populate the edge-to-clause map for(unsigned i = 0; i < _d->rpfp->edges.size(); ++i) @@ -271,11 +281,12 @@ lbool dl_interface::query(::expr * query) { rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0"); rs->SetOption("batch_expand",m_ctx.get_params().batch_expand() ? "1" : "0"); rs->SetOption("conjecture_file",m_ctx.get_params().conjecture_file()); - unsigned rb = m_ctx.get_params().recursion_bound(); +#if 0 if(rb != UINT_MAX){ std::ostringstream os; os << rb; rs->SetOption("recursion_bound", os.str()); } +#endif // Solve! bool ans; diff --git a/src/muz/fp/dl_cmds.cpp b/src/muz/fp/dl_cmds.cpp index f9916808c..e2e3680cc 100644 --- a/src/muz/fp/dl_cmds.cpp +++ b/src/muz/fp/dl_cmds.cpp @@ -100,7 +100,7 @@ struct dl_context { dlctx().set_predicate_representation(pred, num_kinds, kinds); } - void add_rule(expr * rule, symbol const& name) { + void add_rule(expr * rule, symbol const& name, unsigned bound) { init(); if (m_collected_cmds) { expr_ref rl = m_context->bind_variables(rule, true); @@ -110,7 +110,7 @@ struct dl_context { m_trail.push(push_back_vector >(m_collected_cmds->m_names)); } else { - m_context->add_rule(rule, name); + m_context->add_rule(rule, name, bound); } } @@ -151,19 +151,22 @@ class dl_rule_cmd : public cmd { mutable unsigned m_arg_idx; expr* m_t; symbol m_name; + unsigned m_bound; public: dl_rule_cmd(dl_context * dl_ctx): cmd("rule"), m_dl_ctx(dl_ctx), m_arg_idx(0), - m_t(0) {} - virtual char const * get_usage() const { return "(forall (q) (=> (and body) head)) :optional-name"; } + m_t(0), + m_bound(UINT_MAX) {} + virtual char const * get_usage() const { return "(forall (q) (=> (and body) head)) :optional-name :optional-recursion-bound"; } virtual char const * get_descr(cmd_context & ctx) const { return "add a Horn rule."; } virtual unsigned get_arity() const { return VAR_ARITY; } virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { switch(m_arg_idx) { case 0: return CPK_EXPR; case 1: return CPK_SYMBOL; + case 2: return CPK_UINT; default: return CPK_SYMBOL; } } @@ -173,13 +176,18 @@ public: } virtual void set_next_arg(cmd_context & ctx, symbol const & s) { m_name = s; + m_arg_idx++; + } + virtual void set_next_arg(cmd_context & ctx, unsigned bound) { + m_bound = bound; + m_arg_idx++; } virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); } - virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; } + virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; m_bound = UINT_MAX; } virtual void finalize(cmd_context & ctx) { } virtual void execute(cmd_context & ctx) { - m_dl_ctx->add_rule(m_t, m_name); + m_dl_ctx->add_rule(m_t, m_name, m_bound); } }; From c917c1c53db30b875a645ba19879a61512d89b17 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 12 Sep 2014 15:54:42 -0700 Subject: [PATCH 002/117] reset ast trail on context deletion Signed-off-by: Nikolaj Bjorner --- src/api/api_context.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 05e1ca675..338c12f61 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -128,6 +128,7 @@ namespace api { for (unsigned i = 0; i < m_replay_stack.size(); ++i) { dealloc(m_replay_stack[i]); } + m_ast_trail.reset(); } reset_parser(); dealloc(m_solver); From 67b802c9d905329d2411615131b426789cb3856d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 12 Sep 2014 17:38:34 -0700 Subject: [PATCH 003/117] fix scope accounting bug and documentation per Konrad's request Signed-off-by: Nikolaj Bjorner --- src/api/api_context.cpp | 1 + src/api/api_solver_old.cpp | 2 +- src/api/z3_api.h | 7 ++++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 338c12f61..3349bed7c 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -361,6 +361,7 @@ namespace api { } } } + SASSERT(num_scopes <= get_smt_kernel().get_scope_level()); get_smt_kernel().pop(num_scopes); } diff --git a/src/api/api_solver_old.cpp b/src/api/api_solver_old.cpp index e0533fbd9..b81fb2f2c 100644 --- a/src/api/api_solver_old.cpp +++ b/src/api/api_solver_old.cpp @@ -40,7 +40,7 @@ extern "C" { LOG_Z3_pop(c, num_scopes); RESET_ERROR_CODE(); CHECK_SEARCHING(c); - if (num_scopes > mk_c(c)->get_smt_kernel().get_scope_level()) { + if (num_scopes > mk_c(c)->get_num_scopes()) { SET_ERROR_CODE(Z3_IOB); return; } diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 4ffdfa9c2..e1c42667a 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -7069,7 +7069,7 @@ END_MLAPI_EXCLUDE \mlonly then a valid model is returned. Otherwise, it is unsafe to use the returned model.\endmlonly \conly The caller is responsible for deleting the model using the function #Z3_del_model. - \conly \remark In constrast with the rest of the Z3 API, the reference counter of the + \conly \remark In contrast with the rest of the Z3 API, the reference counter of the \conly model is incremented. This is to guarantee backward compatibility. In previous \conly versions, models did not support reference counting. @@ -7182,6 +7182,11 @@ END_MLAPI_EXCLUDE \brief Delete a model object. \sa Z3_check_and_get_model + + \conly \remark The Z3_check_and_get_model automatically increments a reference count on the model. + \conly The expected usage is that models created by that method are deleted using Z3_del_model. + \conly This is for backwards compatibility and in contrast to the rest of the API where + \conly callers are responsible for managing reference counts. \deprecated Subsumed by Z3_solver API From 919e0a5ea2f2bef4fe8ab9880e91dd52a7fc2bd1 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Tue, 16 Sep 2014 14:56:59 +0100 Subject: [PATCH 004/117] Z3Py: fix bug in substitute() with a list of on variable e.g. print substitute(Int('x'), [(Int('x'), Int('y'))]) Signed-off-by: Nuno Lopes --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 50d29a790..d46d40ab2 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -6960,7 +6960,7 @@ def substitute(t, *m): if isinstance(m, tuple): m1 = _get_args(m) if isinstance(m1, list): - m = _get_args(m1) + m = m1 if __debug__: _z3_assert(is_expr(t), "Z3 expression 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.") From f7c3559c31b5d5c7335706a61a7f9c6e47a55545 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Tue, 16 Sep 2014 15:26:01 +0100 Subject: [PATCH 005/117] fix a few compiler warnings Signed-off-by: Nuno Lopes --- src/api/api_interp.cpp | 2 +- src/muz/pdr/pdr_farkas_learner.cpp | 1 - src/smt/smt_model_checker.cpp | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 03d5ff843..e06ad5192 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -411,7 +411,7 @@ static void get_file_params(const char *filename, hash_map= 0 && eqpos < tok.size()){ + if(eqpos != std::string::npos){ std::string left = tok.substr(0,eqpos); std::string right = tok.substr(eqpos+1,tok.size()-eqpos-1); params[left] = right; diff --git a/src/muz/pdr/pdr_farkas_learner.cpp b/src/muz/pdr/pdr_farkas_learner.cpp index 7c38bf86f..b440ef519 100644 --- a/src/muz/pdr/pdr_farkas_learner.cpp +++ b/src/muz/pdr/pdr_farkas_learner.cpp @@ -905,7 +905,6 @@ namespace pdr { void farkas_learner::get_asserted(proof* p, expr_set const& bs, ast_mark& b_closed, obj_hashtable& lemma_set, expr_ref_vector& lemmas) { ast_manager& m = lemmas.get_manager(); ast_mark visited; - proof* p0 = p; ptr_vector todo; todo.push_back(p); diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index 526447f9f..7053d63ec 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -136,9 +136,8 @@ namespace smt { if (cex == 0) return false; // no model available. unsigned num_decls = q->get_num_decls(); - unsigned num_sks = sks.size(); // Remark: sks were created for the flat version of q. - SASSERT(num_sks >= num_decls); + SASSERT(sks.size() >= num_decls); expr_ref_buffer bindings(m_manager); bindings.resize(num_decls); unsigned max_generation = 0; From 79326e24dfb9dff723d1ce64b3f50bcf394bd48c Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Tue, 16 Sep 2014 15:29:25 +0100 Subject: [PATCH 006/117] fix debug build.. Signed-off-by: Nuno Lopes --- src/muz/pdr/pdr_farkas_learner.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/muz/pdr/pdr_farkas_learner.cpp b/src/muz/pdr/pdr_farkas_learner.cpp index b440ef519..7c38bf86f 100644 --- a/src/muz/pdr/pdr_farkas_learner.cpp +++ b/src/muz/pdr/pdr_farkas_learner.cpp @@ -905,6 +905,7 @@ namespace pdr { void farkas_learner::get_asserted(proof* p, expr_set const& bs, ast_mark& b_closed, obj_hashtable& lemma_set, expr_ref_vector& lemmas) { ast_manager& m = lemmas.get_manager(); ast_mark visited; + proof* p0 = p; ptr_vector todo; todo.push_back(p); From d01ca110012a7f92495bf37827df641a2d6378db Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 16 Sep 2014 17:13:09 -0700 Subject: [PATCH 007/117] reduce asymptotic overhead of asserting bounds Signed-off-by: Nikolaj Bjorner --- src/muz/base/dl_context.cpp | 8 +- src/smt/theory_arith.h | 17 +++ src/smt/theory_arith_core.h | 264 ++++++++++++++++++++++++++++++++---- 3 files changed, 259 insertions(+), 30 deletions(-) diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index fbef46ae3..3d0c7c880 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -1104,10 +1104,10 @@ namespace datalog { void context::get_raw_rule_formulas(expr_ref_vector& rules, svector& names){ for (unsigned i = 0; i < m_rule_fmls.size(); ++i) { - expr_ref r = bind_variables(m_rule_fmls[i].get(), true); - rules.push_back(r.get()); - // rules.push_back(m_rule_fmls[i].get()); - names.push_back(m_rule_names[i]); + expr_ref r = bind_variables(m_rule_fmls[i].get(), true); + rules.push_back(r.get()); + // rules.push_back(m_rule_fmls[i].get()); + names.push_back(m_rule_names[i]); } } diff --git a/src/smt/theory_arith.h b/src/smt/theory_arith.h index 998dd72e6..d1af762bb 100644 --- a/src/smt/theory_arith.h +++ b/src/smt/theory_arith.h @@ -410,6 +410,7 @@ namespace smt { atoms m_atoms; // set of theory atoms ptr_vector m_asserted_bounds; // set of asserted bounds unsigned m_asserted_qhead; + ptr_vector m_new_atoms; // new bound atoms that have yet to be internalized. svector m_nl_monomials; // non linear monomials svector m_nl_propagated; // non linear monomials that became linear v_dependency_manager m_dep_manager; // for tracking bounds during non-linear reasoning @@ -570,6 +571,22 @@ namespace smt { void mk_clause(literal l1, literal l2, unsigned num_params, parameter * params); void mk_clause(literal l1, literal l2, literal l3, unsigned num_params, parameter * params); void mk_bound_axioms(atom * a); + void mk_bound_axiom(atom* a1, atom* a2); + void flush_bound_axioms(); + typename atoms::iterator next_sup(atom* a1, atom_kind kind, + typename atoms::iterator it, + typename atoms::iterator end, + bool& found_compatible); + typename atoms::iterator next_inf(atom* a1, atom_kind kind, + typename atoms::iterator it, + typename atoms::iterator end, + bool& found_compatible); + typename atoms::iterator first(atom_kind kind, + typename atoms::iterator it, + typename atoms::iterator end); + struct compare_atoms { + bool operator()(atom* a1, atom* a2) const { return a1->get_k() < a2->get_k(); } + }; virtual bool default_internalizer() const { return false; } virtual bool internalize_atom(app * n, bool gate_ctx); virtual bool internalize_term(app * term); diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index fbc043048..ba4eefc36 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -348,13 +348,24 @@ namespace smt { context & ctx = get_context(); simplifier & s = ctx.get_simplifier(); expr_ref s_ante(m), s_conseq(m); + expr* s_conseq_n, * s_ante_n; + bool negated; proof_ref pr(m); + s(ante, s_ante, pr); + negated = m.is_not(s_ante, s_ante_n); + if (negated) s_ante = s_ante_n; ctx.internalize(s_ante, false); literal l_ante = ctx.get_literal(s_ante); + if (negated) l_ante.neg(); + s(conseq, s_conseq, pr); + negated = m.is_not(s_conseq, s_conseq_n); + if (negated) s_conseq = s_conseq_n; ctx.internalize(s_conseq, false); literal l_conseq = ctx.get_literal(s_conseq); + if (negated) l_conseq.neg(); + literal lits[2] = {l_ante, l_conseq}; ctx.mk_th_axiom(get_id(), 2, lits); if (ctx.relevancy()) { @@ -800,48 +811,244 @@ namespace smt { template void theory_arith::mk_bound_axioms(atom * a1) { theory_var v = a1->get_var(); - literal l1(a1->get_bool_var()); + atoms & occs = m_var_occs[v]; + if (!get_context().is_searching()) { + // + // NB. We make an assumption that user push calls propagation + // before internal scopes are pushed. This flushes all newly + // asserted atoms into the right context. + // + m_new_atoms.push_back(a1); + return; + } numeral const & k1(a1->get_k()); atom_kind kind1 = a1->get_atom_kind(); TRACE("mk_bound_axioms", tout << "making bound axioms for v" << v << " " << kind1 << " " << k1 << "\n";); - atoms & occs = m_var_occs[v]; typename atoms::iterator it = occs.begin(); typename atoms::iterator end = occs.end(); + + typename atoms::iterator lo_inf = end, lo_sup = end; + typename atoms::iterator hi_inf = end, hi_sup = end; for (; it != end; ++it) { - atom * a2 = *it; - literal l2(a2->get_bool_var()); - numeral const & k2 = a2->get_k(); - atom_kind kind2 = a2->get_atom_kind(); + atom * a2 = *it; + numeral const & k2(a2->get_k()); + atom_kind kind2 = a2->get_atom_kind(); SASSERT(k1 != k2 || kind1 != kind2); - SASSERT(a2->get_var() == v); - parameter coeffs[3] = { parameter(symbol("farkas")), parameter(rational(1)), parameter(rational(1)) }; - if (kind1 == A_LOWER) { - if (kind2 == A_LOWER) { - // x >= k1, x >= k2 - if (k1 >= k2) mk_clause(~l1, l2, 3, coeffs); - else mk_clause(~l2, l1, 3, coeffs); + if (kind2 == A_LOWER) { + if (k2 < k1) { + if (lo_inf == end || k2 > (*lo_inf)->get_k()) { + lo_inf = it; + } } - else { - // x >= k1, x <= k2 - if (k1 > k2) mk_clause(~l1, ~l2, 3, coeffs); - else mk_clause(l1, l2, 3, coeffs); + else if (lo_sup == end || k2 < (*lo_sup)->get_k()) { + lo_sup = it; } } - else { - if (kind2 == A_LOWER) { - // x <= k1, x >= k2 - if (k1 < k2) mk_clause(~l1, ~l2, 3, coeffs); - else mk_clause(l1, l2, 3, coeffs); + else if (k2 < k1) { + if (hi_inf == end || k2 > (*hi_inf)->get_k()) { + hi_inf = it; + } + } + else if (hi_sup == end || k2 < (*hi_sup)->get_k()) { + hi_sup = it; + } + } + if (lo_inf != end) mk_bound_axiom(a1, *lo_inf); + if (lo_sup != end) mk_bound_axiom(a1, *lo_sup); + if (hi_inf != end) mk_bound_axiom(a1, *hi_inf); + if (hi_sup != end) mk_bound_axiom(a1, *hi_sup); + } + + template + void theory_arith::mk_bound_axiom(atom* a1, atom* a2) { + theory_var v = a1->get_var(); + literal l1(a1->get_bool_var()); + literal l2(a2->get_bool_var()); + numeral const & k1(a1->get_k()); + numeral const & k2(a2->get_k()); + atom_kind kind1 = a1->get_atom_kind(); + atom_kind kind2 = a2->get_atom_kind(); + bool v_is_int = is_int(v); + SASSERT(v == a2->get_var()); + SASSERT(k1 != k2 || kind1 != kind2); + parameter coeffs[3] = { parameter(symbol("farkas")), + parameter(rational(1)), parameter(rational(1)) }; + + //std::cout << "v" << v << " " << ((kind1==A_LOWER)?"<= ":">= ") << k1 << "\t "; + //std::cout << "v" << v << " " << ((kind2==A_LOWER)?"<= ":">= ") << k2 << "\n"; + + if (kind1 == A_LOWER) { + if (kind2 == A_LOWER) { + if (k2 <= k1) { + mk_clause(~l1, l2, 3, coeffs); } else { - // x <= k1, x <= k2 - if (k1 < k2) mk_clause(~l1, l2, 3, coeffs); - else mk_clause(~l2, l1, 3, coeffs); + mk_clause(l1, ~l2, 3, coeffs); + } + } + else if (k1 <= k2) { + // k1 <= k2, k1 <= x or x <= k2 + mk_clause(l1, l2, 3, coeffs); + } + else { + // k1 > hi_inf, k1 <= x => ~(x <= hi_inf) + mk_clause(~l1, ~l2, 3, coeffs); + if (v_is_int && k1 == k2 + numeral(1)) { + // k1 <= x or x <= k1-1 + mk_clause(l1, l2, 3, coeffs); } } } + else if (kind2 == A_LOWER) { + if (k1 >= k2) { + // k1 >= lo_inf, k1 >= x or lo_inf <= x + mk_clause(l1, l2, 3, coeffs); + } + else { + // k1 < k2, k2 <= x => ~(x <= k1) + mk_clause(~l1, ~l2, 3, coeffs); + if (v_is_int && k1 == k2 - numeral(1)) { + // x <= k1 or k1+l <= x + mk_clause(l1, l2, 3, coeffs); + } + + } + } + else { + // kind1 == A_UPPER, kind2 == A_UPPER + if (k1 >= k2) { + // k1 >= k2, x <= k2 => x <= k1 + mk_clause(l1, ~l2, 3, coeffs); + } + else { + // k1 <= hi_sup , x <= k1 => x <= hi_sup + mk_clause(~l1, l2, 3, coeffs); + } + } } + template + void theory_arith::flush_bound_axioms() { + while (!m_new_atoms.empty()) { + ptr_vector atoms; + atoms.push_back(m_new_atoms.back()); + m_new_atoms.pop_back(); + theory_var v = atoms.back()->get_var(); + for (unsigned i = 0; i < m_new_atoms.size(); ++i) { + if (m_new_atoms[i]->get_var() == v) { + atoms.push_back(m_new_atoms[i]); + m_new_atoms[i] = m_new_atoms.back(); + m_new_atoms.pop_back(); + --i; + } + } + ptr_vector occs(m_var_occs[v]); + + std::sort(atoms.begin(), atoms.end(), compare_atoms()); + std::sort(occs.begin(), occs.end(), compare_atoms()); + + typename atoms::iterator begin1 = occs.begin(); + typename atoms::iterator begin2 = occs.begin(); + typename atoms::iterator end = occs.end(); + begin1 = first(A_LOWER, begin1, end); + begin2 = first(A_UPPER, begin2, end); + + typename atoms::iterator lo_inf = begin1, lo_sup = begin1; + typename atoms::iterator hi_inf = begin2, hi_sup = begin2; + typename atoms::iterator lo_inf1 = begin1, lo_sup1 = begin1; + typename atoms::iterator hi_inf1 = begin2, hi_sup1 = begin2; + bool flo_inf, fhi_inf, flo_sup, fhi_sup; + // std::cout << atoms.size() << "\n"; + ptr_addr_hashtable visited; + for (unsigned i = 0; i < atoms.size(); ++i) { + atom* a1 = atoms[i]; + lo_inf1 = next_inf(a1, A_LOWER, lo_inf, end, flo_inf); + hi_inf1 = next_inf(a1, A_UPPER, hi_inf, end, fhi_inf); + lo_sup1 = next_sup(a1, A_LOWER, lo_sup, end, flo_sup); + hi_sup1 = next_sup(a1, A_UPPER, hi_sup, end, fhi_sup); +// std::cout << "v" << a1->get_var() << ((a1->get_atom_kind()==A_LOWER)?" <= ":" >= ") << a1->get_k() << "\n"; + // std::cout << (lo_inf1 != end) << " " << (lo_sup1 != end) << " " << (hi_inf1 != end) << " " << (hi_sup1 != end) << "\n"; + if (lo_inf1 != end) lo_inf = lo_inf1; + if (lo_sup1 != end) lo_sup = lo_sup1; + if (hi_inf1 != end) hi_inf = hi_inf1; + if (hi_sup1 != end) hi_sup = hi_sup1; + if (!flo_inf) lo_inf = end; + if (!fhi_inf) hi_inf = end; + if (!flo_sup) lo_sup = end; + if (!fhi_sup) hi_sup = end; + visited.insert(a1); + if (lo_inf1 != end && lo_inf != end && !visited.contains(*lo_inf)) mk_bound_axiom(a1, *lo_inf); + if (lo_sup1 != end && lo_sup != end && !visited.contains(*lo_sup)) mk_bound_axiom(a1, *lo_sup); + if (hi_inf1 != end && hi_inf != end && !visited.contains(*hi_inf)) mk_bound_axiom(a1, *hi_inf); + if (hi_sup1 != end && hi_sup != end && !visited.contains(*hi_sup)) mk_bound_axiom(a1, *hi_sup); + } + } + } + + template + typename theory_arith::atoms::iterator + theory_arith::first( + atom_kind kind, + typename atoms::iterator it, + typename atoms::iterator end) { + for (; it != end; ++it) { + atom* a = *it; + if (a->get_atom_kind() == kind) return it; + } + return end; + } + + template + typename theory_arith::atoms::iterator + theory_arith::next_inf( + atom* a1, + atom_kind kind, + typename atoms::iterator it, + typename atoms::iterator end, + bool& found_compatible) { + numeral const & k1(a1->get_k()); + typename atoms::iterator result = end; + found_compatible = false; + for (; it != end; ++it) { + atom * a2 = *it; + if (a1 == a2) continue; + if (a2->get_atom_kind() != kind) continue; + numeral const & k2(a2->get_k()); + found_compatible = true; + if (k2 <= k1) { + result = it; + } + else { + break; + } + } + return result; + } + + template + typename theory_arith::atoms::iterator + theory_arith::next_sup( + atom* a1, + atom_kind kind, + typename atoms::iterator it, + typename atoms::iterator end, + bool& found_compatible) { + numeral const & k1(a1->get_k()); + found_compatible = false; + for (; it != end; ++it) { + atom * a2 = *it; + if (a1 == a2) continue; + if (a2->get_atom_kind() != kind) continue; + numeral const & k2(a2->get_k()); + found_compatible = true; + if (k1 < k2) { + return it; + } + } + return end; + } + + template bool theory_arith::internalize_atom(app * n, bool gate_ctx) { TRACE("arith_internalize", tout << "internalising atom:\n" << mk_pp(n, this->get_manager()) << "\n";); @@ -879,7 +1086,7 @@ namespace smt { bool_var bv = ctx.mk_bool_var(n); ctx.set_var_theory(bv, get_id()); rational _k; - m_util.is_numeral(rhs, _k); + VERIFY(m_util.is_numeral(rhs, _k)); numeral k(_k); atom * a = alloc(atom, bv, v, k, kind); mk_bound_axioms(a); @@ -927,6 +1134,7 @@ namespace smt { template void theory_arith::assign_eh(bool_var v, bool is_true) { + TRACE("arith", tout << "v" << v << " " << is_true << "\n";); atom * a = get_bv2a(v); if (!a) return; SASSERT(get_context().get_assignment(a->get_bool_var()) != l_undef); @@ -1142,6 +1350,7 @@ namespace smt { CASSERT("arith", wf_columns()); CASSERT("arith", valid_row_assignment()); + flush_bound_axioms(); propagate_linear_monomials(); while (m_asserted_qhead < m_asserted_bounds.size()) { bound * b = m_asserted_bounds[m_asserted_qhead]; @@ -2421,6 +2630,8 @@ namespace smt { if (val == l_undef) continue; // TODO: check if the following line is a bottleneck + TRACE("arith", tout << "v" << a->get_bool_var() << " " << (val == l_true) << "\n";); + a->assign_eh(val == l_true, get_epsilon(a->get_var())); if (val != l_undef && a->get_bound_kind() == b->get_bound_kind()) { SASSERT((ctx.get_assignment(bv) == l_true) == a->is_true()); @@ -2916,6 +3127,7 @@ namespace smt { SASSERT(m_to_patch.empty()); m_to_check.reset(); m_in_to_check.reset(); + m_new_atoms.reset(); CASSERT("arith", wf_rows()); CASSERT("arith", wf_columns()); CASSERT("arith", valid_row_assignment()); From 1636e35bf99443d4186f9a4b9c7f828b2aa9502d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 16 Sep 2014 20:11:44 -0700 Subject: [PATCH 008/117] fix scope accounting bug in deprecated solver mode Signed-off-by: Nikolaj Bjorner --- src/api/api_context.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 3349bed7c..b10621d43 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -343,22 +343,18 @@ namespace api { void context::push() { get_smt_kernel().push(); - if (!m_user_ref_count) { - m_ast_lim.push_back(m_ast_trail.size()); - m_replay_stack.push_back(0); - } + m_ast_lim.push_back(m_ast_trail.size()); + m_replay_stack.push_back(0); } void context::pop(unsigned num_scopes) { for (unsigned i = 0; i < num_scopes; ++i) { - if (!m_user_ref_count) { - unsigned sz = m_ast_lim.back(); - m_ast_lim.pop_back(); - dealloc(m_replay_stack.back()); - m_replay_stack.pop_back(); - while (m_ast_trail.size() > sz) { - m_ast_trail.pop_back(); - } + unsigned sz = m_ast_lim.back(); + m_ast_lim.pop_back(); + dealloc(m_replay_stack.back()); + m_replay_stack.pop_back(); + while (m_ast_trail.size() > sz) { + m_ast_trail.pop_back(); } } SASSERT(num_scopes <= get_smt_kernel().get_scope_level()); From a85f1784db95c5975c3484215407f985d19f61ae Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 16 Sep 2014 23:25:39 -0700 Subject: [PATCH 009/117] updated answer to binary interpolant Signed-off-by: Nikolaj Bjorner --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index d46d40ab2..879b19597 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -7344,7 +7344,7 @@ def binary_interpolant(a,b,p=None,ctx=None): >>> x = Int('x') >>> print binary_interpolant(x<0,x>2) - x <= 2 + Not(x >= 0) """ f = And(Interp(a),b) return tree_interpolant(f,p,ctx)[0] From b95f5b0fea8f239d45ffaf88615c400339ca1101 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 17 Sep 2014 16:33:27 +0100 Subject: [PATCH 010/117] fix bug in the datalog compiler when using negation We now perform negation after filtering with interpreted constraints so that the table reflects relevant columns which were not being added by the negation Signed-off-by: Nuno Lopes --- src/muz/rel/dl_compiler.cpp | 84 ++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/muz/rel/dl_compiler.cpp b/src/muz/rel/dl_compiler.cpp index 276e7b836..2a2507d7f 100644 --- a/src/muz/rel/dl_compiler.cpp +++ b/src/muz/rel/dl_compiler.cpp @@ -589,49 +589,8 @@ namespace datalog { dealloc = true; } - //enforce negative predicates - unsigned ut_len=r->get_uninterpreted_tail_size(); - for(unsigned i=pt_len; iget_tail(i); - func_decl * neg_pred = neg_tail->get_decl(); - variable_intersection neg_intersection(m_context.get_manager()); - neg_intersection.populate(single_res_expr, neg_tail); - unsigned_vector t_cols(neg_intersection.size(), neg_intersection.get_cols1()); - unsigned_vector neg_cols(neg_intersection.size(), neg_intersection.get_cols2()); - - unsigned neg_len = neg_tail->get_num_args(); - for(unsigned i=0; iget_arg(i); - if(is_var(e)) { - continue; - } - SASSERT(is_app(e)); - relation_sort arg_sort; - m_context.get_rel_context()->get_rmanager().from_predicate(neg_pred, i, arg_sort); - reg_idx new_reg; - bool new_dealloc; - make_add_constant_column(head_pred, filtered_res, arg_sort, to_app(e), new_reg, new_dealloc, acc); - - if (dealloc) - make_dealloc_non_void(filtered_res, acc); - dealloc = new_dealloc; - filtered_res = new_reg; // here filtered_res value gets changed !! - - t_cols.push_back(single_res_expr.size()); - neg_cols.push_back(i); - single_res_expr.push_back(e); - } - SASSERT(t_cols.size()==neg_cols.size()); - - reg_idx neg_reg = m_pred_regs.find(neg_pred); - if (!dealloc) - make_clone(filtered_res, filtered_res, acc); - acc.push_back(instruction::mk_filter_by_negation(filtered_res, neg_reg, t_cols.size(), - t_cols.c_ptr(), neg_cols.c_ptr())); - dealloc = true; - } - // enforce interpreted tail predicates + unsigned ut_len = r->get_uninterpreted_tail_size(); unsigned ft_len = r->get_tail_size(); // full tail ptr_vector tail; for (unsigned tail_index = ut_len; tail_index < ft_len; ++tail_index) { @@ -738,6 +697,47 @@ namespace datalog { dealloc = true; } + //enforce negative predicates + for (unsigned i = pt_len; iget_tail(i); + func_decl * neg_pred = neg_tail->get_decl(); + variable_intersection neg_intersection(m_context.get_manager()); + neg_intersection.populate(single_res_expr, neg_tail); + unsigned_vector t_cols(neg_intersection.size(), neg_intersection.get_cols1()); + unsigned_vector neg_cols(neg_intersection.size(), neg_intersection.get_cols2()); + + unsigned neg_len = neg_tail->get_num_args(); + for (unsigned i = 0; iget_arg(i); + if (is_var(e)) { + continue; + } + SASSERT(is_app(e)); + relation_sort arg_sort; + m_context.get_rel_context()->get_rmanager().from_predicate(neg_pred, i, arg_sort); + reg_idx new_reg; + bool new_dealloc; + make_add_constant_column(head_pred, filtered_res, arg_sort, to_app(e), new_reg, new_dealloc, acc); + + if (dealloc) + make_dealloc_non_void(filtered_res, acc); + dealloc = new_dealloc; + filtered_res = new_reg; // here filtered_res value gets changed !! + + t_cols.push_back(single_res_expr.size()); + neg_cols.push_back(i); + single_res_expr.push_back(e); + } + SASSERT(t_cols.size() == neg_cols.size()); + + reg_idx neg_reg = m_pred_regs.find(neg_pred); + if (!dealloc) + make_clone(filtered_res, filtered_res, acc); + acc.push_back(instruction::mk_filter_by_negation(filtered_res, neg_reg, t_cols.size(), + t_cols.c_ptr(), neg_cols.c_ptr())); + dealloc = true; + } + #if 0 // this version is potentially better for non-symbolic tables, // since it constraints each unbound column at a time (reducing the From 45bfcda16cd209f565b0dad6518b0179b2cb7057 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 17 Sep 2014 16:37:53 -0700 Subject: [PATCH 011/117] remove typename Signed-off-by: Nikolaj Bjorner --- src/smt/theory_arith_core.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index ba4eefc36..c743562da 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -874,9 +874,6 @@ namespace smt { parameter coeffs[3] = { parameter(symbol("farkas")), parameter(rational(1)), parameter(rational(1)) }; - //std::cout << "v" << v << " " << ((kind1==A_LOWER)?"<= ":">= ") << k1 << "\t "; - //std::cout << "v" << v << " " << ((kind2==A_LOWER)?"<= ":">= ") << k2 << "\n"; - if (kind1 == A_LOWER) { if (kind2 == A_LOWER) { if (k2 <= k1) { @@ -958,16 +955,13 @@ namespace smt { typename atoms::iterator lo_inf1 = begin1, lo_sup1 = begin1; typename atoms::iterator hi_inf1 = begin2, hi_sup1 = begin2; bool flo_inf, fhi_inf, flo_sup, fhi_sup; - // std::cout << atoms.size() << "\n"; - ptr_addr_hashtable visited; + ptr_addr_hashtable visited; for (unsigned i = 0; i < atoms.size(); ++i) { atom* a1 = atoms[i]; lo_inf1 = next_inf(a1, A_LOWER, lo_inf, end, flo_inf); hi_inf1 = next_inf(a1, A_UPPER, hi_inf, end, fhi_inf); lo_sup1 = next_sup(a1, A_LOWER, lo_sup, end, flo_sup); hi_sup1 = next_sup(a1, A_UPPER, hi_sup, end, fhi_sup); -// std::cout << "v" << a1->get_var() << ((a1->get_atom_kind()==A_LOWER)?" <= ":" >= ") << a1->get_k() << "\n"; - // std::cout << (lo_inf1 != end) << " " << (lo_sup1 != end) << " " << (hi_inf1 != end) << " " << (hi_sup1 != end) << "\n"; if (lo_inf1 != end) lo_inf = lo_inf1; if (lo_sup1 != end) lo_sup = lo_sup1; if (hi_inf1 != end) hi_inf = hi_inf1; From 61d67dc2dee3270919caf883128f3a655b18f5c9 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Thu, 18 Sep 2014 14:38:40 +0100 Subject: [PATCH 012/117] fix a few compiler warnings Signed-off-by: Nuno Lopes --- src/muz/rel/dl_vector_relation.h | 2 -- src/util/debug.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/muz/rel/dl_vector_relation.h b/src/muz/rel/dl_vector_relation.h index 114f4ca43..4d0917359 100644 --- a/src/muz/rel/dl_vector_relation.h +++ b/src/muz/rel/dl_vector_relation.h @@ -62,8 +62,6 @@ namespace datalog { dealloc(m_elems); } - virtual bool can_swap() const { return true; } - virtual void swap(relation_base& other) { vector_relation& o = dynamic_cast(other); if (&o == this) return; diff --git a/src/util/debug.h b/src/util/debug.h index 9e519982f..a36743f73 100644 --- a/src/util/debug.h +++ b/src/util/debug.h @@ -73,7 +73,7 @@ bool is_debug_enabled(const char * tag); UNREACHABLE(); \ } #else -#define VERIFY(_x_) (_x_) +#define VERIFY(_x_) (void)(_x_) #endif #define MAKE_NAME2(LINE) zofty_ ## LINE From 9949c7e31c8dae78dcf7dc44eabc8157981c0310 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 18 Sep 2014 17:09:22 +0100 Subject: [PATCH 013/117] fixed typos Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5e100b527..411fdd1e1 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -455,7 +455,7 @@ def display_help(exit_code): 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(" -j, --java generate Java bindings.") print(" --staticlib build Z3 static library.") if not IS_WINDOWS: print(" -g, --gmp use GMP.") @@ -587,7 +587,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 bindings directory was detected.") _UNIQ_ID = 0 From d36cecc2f328cdd742c601cee6bc803dca1b2b14 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Fri, 19 Sep 2014 15:51:08 +0100 Subject: [PATCH 014/117] make use of count population intrinsincs on MSVC/gcc/clang Signed-off-by: Nuno Lopes --- src/util/util.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/util/util.h b/src/util/util.h index 0aa8f881d..58120b2f2 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -95,7 +95,12 @@ unsigned uint64_log2(uint64 v); COMPILE_TIME_ASSERT(sizeof(unsigned) == 4); // Return the number of 1 bits in v. -inline unsigned get_num_1bits(unsigned v) { +static inline unsigned get_num_1bits(unsigned v) { +#ifdef _MSC_VER + return __popcnt(v); +#elif defined(__GNUC__) + return __builtin_popcount(v); +#else #ifdef Z3DEBUG unsigned c; unsigned v1 = v; @@ -108,15 +113,16 @@ inline unsigned get_num_1bits(unsigned v) { unsigned r = (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; SASSERT(c == r); return r; +#endif } // Remark: on gcc, the operators << and >> do not produce zero when the second argument >= 64. // So, I'm using the following two definitions to fix the problem -inline uint64 shift_right(uint64 x, uint64 y) { +static inline uint64 shift_right(uint64 x, uint64 y) { return y < 64ull ? (x >> y) : 0ull; } -inline uint64 shift_left(uint64 x, uint64 y) { +static inline uint64 shift_left(uint64 x, uint64 y) { return y < 64ull ? (x << y) : 0ull; } @@ -255,10 +261,6 @@ inline std::ostream & operator<<(std::ostream & out, std::pair const & p return out; } -#ifndef _WINDOWS -#define __forceinline inline -#endif - template bool has_duplicates(const IT & begin, const IT & end) { for (IT it1 = begin; it1 != end; ++it1) { From b243ac945f7e87fe669b9527d6f6c0e705cfe666 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 21 Sep 2014 15:20:43 +0100 Subject: [PATCH 015/117] hoprfully fix the build for MSVC 2010 Signed-off-by: Nuno Lopes --- src/util/util.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/util.h b/src/util/util.h index 58120b2f2..eb24ece13 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -24,6 +24,9 @@ Revision History: #include #include #include +#ifdef _MSC_VER +#include +#endif #ifndef SIZE_MAX #define SIZE_MAX std::numeric_limits::max() From dca3ce6b24f1a8752bf0a7252c2eaf1bb888d5ba Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 22 Sep 2014 01:16:16 -0700 Subject: [PATCH 016/117] update documentation on models associated with solver objects Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index e1c42667a..b561b6bf1 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -6620,6 +6620,13 @@ END_MLAPI_EXCLUDE /** \brief Create a new (incremental) solver. + The function #Z3_solver_get_model retrieves a model if the + assertions is satisfiable (i.e., the result is \c + Z3_L_TRUE) and model construction is enabled. + The function #Z3_solver_get_model can also be used even + if the result is \c Z3_L_UNDEF, but the returned model + is not guaranteed to satisfy quantified assertions. + def_API('Z3_mk_simple_solver', SOLVER, (_in(CONTEXT),)) */ Z3_solver Z3_API Z3_mk_simple_solver(__in Z3_context c); @@ -6757,8 +6764,11 @@ END_MLAPI_EXCLUDE \brief Check whether the assertions in a given solver are consistent or not. The function #Z3_solver_get_model retrieves a model if the - assertions are not unsatisfiable (i.e., the result is not \c - Z3_L_FALSE) and model construction is enabled. + assertions is satisfiable (i.e., the result is \c + Z3_L_TRUE) and model construction is enabled. + Note that if the call returns Z3_L_UNDEF, Z3 does not + ensure that calls to #Z3_solver_get_model succeed and any models + produced in this case are not guaranteed to satisfy the assertions. The function #Z3_solver_get_proof retrieves a proof if proof generation was enabled when the context was created, and the From 4995ce1fdee47ffd61d4726c89ff908f468d6450 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 22 Sep 2014 22:22:26 -0700 Subject: [PATCH 017/117] disable unstable interpolation sample Signed-off-by: Nikolaj Bjorner --- 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 879b19597..b6cceeb8e 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -7342,8 +7342,8 @@ def binary_interpolant(a,b,p=None,ctx=None): If parameters p are supplied, these are used in creating the solver that determines satisfiability. - >>> x = Int('x') - >>> print binary_interpolant(x<0,x>2) + x = Int('x') + print binary_interpolant(x<0,x>2) Not(x >= 0) """ f = And(Interp(a),b) From 9412890c6324a2df3c5c769fb0e28dddc0adc475 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 26 Sep 2014 12:58:55 -0700 Subject: [PATCH 018/117] trace reason for undef in arithmetic, enable model generation on THEORY incompleteness, but retain undef result Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 2 +- src/smt/theory_arith_core.h | 4 +++- src/smt/theory_arith_int.h | 4 +++- src/smt/theory_arith_nl.h | 6 ++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 4f3c73ce6..02ee06985 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -3945,7 +3945,7 @@ namespace smt { m_fingerprints.display(tout); ); failure fl = get_last_search_failure(); - if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS || fl == THEORY) { + if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS) { // don't generate model. return; } diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index c743562da..66d232227 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1274,8 +1274,10 @@ namespace smt { } } while (m_final_check_idx != old_idx); - if (result == FC_DONE && m_found_unsupported_op) + if (result == FC_DONE && m_found_unsupported_op) { + TRACE("arith", tout << "Found unsupported operation\n";); result = FC_GIVEUP; + } return result; } diff --git a/src/smt/theory_arith_int.h b/src/smt/theory_arith_int.h index e0ecc087a..0a70e2645 100644 --- a/src/smt/theory_arith_int.h +++ b/src/smt/theory_arith_int.h @@ -1294,8 +1294,10 @@ namespace smt { } tout << "max: " << max << ", min: " << min << "\n";); - if (m_params.m_arith_ignore_int) + if (m_params.m_arith_ignore_int) { + TRACE("arith", tout << "Ignore int: give up\n";); return FC_GIVEUP; + } if (!gcd_test()) return FC_CONTINUE; diff --git a/src/smt/theory_arith_nl.h b/src/smt/theory_arith_nl.h index d02c9e540..6a7017a29 100644 --- a/src/smt/theory_arith_nl.h +++ b/src/smt/theory_arith_nl.h @@ -2314,13 +2314,15 @@ namespace smt { return FC_DONE; } - if (!m_params.m_nl_arith) + if (!m_params.m_nl_arith) { + TRACE("non_linear", tout << "Non-linear is not enabled\n";); return FC_GIVEUP; + } TRACE("process_non_linear", display(tout);); if (m_nl_rounds > m_params.m_nl_arith_rounds) { - TRACE("non_linear", tout << "GIVE UP non linear problem...\n";); + TRACE("non_linear", tout << "GIVEUP non linear problem...\n";); IF_VERBOSE(3, verbose_stream() << "Max. non linear arithmetic rounds. Increase threshold using NL_ARITH_ROUNDS=\n";); return FC_GIVEUP; } From e57e5328cebcd55065cb6bb9da68601fa5a00e8c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 26 Sep 2014 16:42:11 -0700 Subject: [PATCH 019/117] configuration update to SAT solver on creation time. Adding random_seed to sat parameters to enable command-line and module mode to work at the level of sat solver Signed-off-by: Nikolaj Bjorner --- src/sat/sat_config.cpp | 5 ++++- src/sat/sat_config.h | 1 + src/sat/sat_params.pyg | 1 + src/sat/sat_solver.cpp | 4 ++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index cc0f97ff0..fb81809b1 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -68,7 +68,10 @@ namespace sat { m_restart_factor = p.restart_factor(); m_random_freq = p.random_freq(); - + m_random_seed = p.random_seed(); + if (m_random_seed == 0) + m_random_seed = _p.get_uint("random_seed", 0); + m_burst_search = p.burst_search(); m_max_conflicts = p.max_conflicts(); diff --git a/src/sat/sat_config.h b/src/sat/sat_config.h index 90ebe968b..253786e11 100644 --- a/src/sat/sat_config.h +++ b/src/sat/sat_config.h @@ -53,6 +53,7 @@ namespace sat { unsigned m_restart_initial; double m_restart_factor; // for geometric case double m_random_freq; + unsigned m_random_seed; unsigned m_burst_search; unsigned m_max_conflicts; diff --git a/src/sat/sat_params.pyg b/src/sat/sat_params.pyg index 71579b86a..de0283897 100644 --- a/src/sat/sat_params.pyg +++ b/src/sat/sat_params.pyg @@ -9,6 +9,7 @@ def_module_params('sat', ('restart.initial', UINT, 100, 'initial restart (number of conflicts)'), ('restart.factor', DOUBLE, 1.5, 'restart increment factor for geometric strategy'), ('random_freq', DOUBLE, 0.01, 'frequency of random case splits'), + ('random_seed', UINT, 0, 'random seed'), ('burst_search', UINT, 100, 'number of conflicts before first global simplification'), ('max_conflicts', UINT, UINT_MAX, 'maximum number of conflicts'), ('gc', SYMBOL, 'glue_psm', 'garbage collection strategy: psm, glue, glue_psm, dyn_psm'), diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index f4bf5393c..e7dee83ae 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -46,7 +46,7 @@ namespace sat { m_qhead(0), m_scope_lvl(0), m_params(p) { - m_config.updt_params(p); + updt_params(p); } solver::~solver() { @@ -1972,7 +1972,7 @@ namespace sat { m_asymm_branch.updt_params(p); m_probing.updt_params(p); m_scc.updt_params(p); - m_rand.set_seed(p.get_uint("random_seed", 0)); + m_rand.set_seed(m_config.m_random_seed); } void solver::collect_param_descrs(param_descrs & d) { From 5f59dd1644bfe64a02c24b4fc67dfd8f7c09bba6 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 28 Sep 2014 11:37:11 +0100 Subject: [PATCH 020/117] revert usage of popcnt is MSVC Signed-off-by: Nuno Lopes --- src/util/util.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/util/util.h b/src/util/util.h index eb24ece13..cbc19b759 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -24,9 +24,6 @@ Revision History: #include #include #include -#ifdef _MSC_VER -#include -#endif #ifndef SIZE_MAX #define SIZE_MAX std::numeric_limits::max() @@ -99,9 +96,7 @@ COMPILE_TIME_ASSERT(sizeof(unsigned) == 4); // Return the number of 1 bits in v. static inline unsigned get_num_1bits(unsigned v) { -#ifdef _MSC_VER - return __popcnt(v); -#elif defined(__GNUC__) +#ifdef __GNUC__ return __builtin_popcount(v); #else #ifdef Z3DEBUG From 97a5e6d326cbfad117bd40a0730a40ffcb4c2d21 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Sun, 28 Sep 2014 12:21:56 +0100 Subject: [PATCH 021/117] assorted compiler warnings fixes Signed-off-by: Nuno Lopes --- src/math/polynomial/polynomial.cpp | 6 ++---- src/smt/theory_diff_logic_def.h | 7 ++----- src/util/bit_vector.cpp | 3 +-- src/util/mpf.cpp | 16 +++++++++++----- src/util/mpff.cpp | 3 +-- src/util/mpfx.cpp | 3 +-- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index f5d96e740..3f1883749 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -4117,7 +4117,6 @@ namespace polynomial { polynomial_ref H(m_wrapper), C(m_wrapper); polynomial_ref lc_H(m_wrapper); unsigned min_deg_q = UINT_MAX; - var next_x = vars[idx+1]; unsigned counter = 0; for (;; counter++) { @@ -4137,7 +4136,7 @@ namespace polynomial { var q_var = max_var(q); unsigned deg_q = q_var == null_var ? 0 : degree(q, q_var); TRACE("mgcd_detail", tout << "counter: " << counter << "\nidx: " << idx << "\nq: " << q << "\ndeg_q: " << deg_q << "\nmin_deg_q: " << - min_deg_q << "\nnext_x: x" << next_x << "\nmax_var(q): " << q_var << "\n";); + min_deg_q << "\nnext_x: x" << vars[idx+1] << "\nmax_var(q): " << q_var << "\n";); if (deg_q < min_deg_q) { TRACE("mgcd_detail", tout << "reseting...\n";); counter = 0; @@ -5113,10 +5112,9 @@ namespace polynomial { monomial const * m_r = R.m(max_R); numeral const & a_r = R.a(max_R); monomial * m_r_q = 0; - bool q_div_r = div(m_r, m_q, m_r_q); + VERIFY(div(m_r, m_q, m_r_q)); TRACE("polynomial", tout << "m_r: "; m_r->display(tout); tout << "\nm_q: "; m_q->display(tout); tout << "\n"; if (m_r_q) { tout << "m_r_q: "; m_r_q->display(tout); tout << "\n"; }); - SASSERT(q_div_r); m_r_q_ref = m_r_q; m_manager.div(a_r, a_q, a_r_q); C.add(a_r_q, m_r_q); // C <- C + (a_r/a_q)*(m_r/m_q) diff --git a/src/smt/theory_diff_logic_def.h b/src/smt/theory_diff_logic_def.h index 390803957..a2e1ece40 100644 --- a/src/smt/theory_diff_logic_def.h +++ b/src/smt/theory_diff_logic_def.h @@ -983,11 +983,8 @@ template void theory_diff_logic::get_eq_antecedents( theory_var v1, theory_var v2, unsigned timestamp, conflict_resolution & cr) { imp_functor functor(cr); - bool r; - r = m_graph.find_shortest_zero_edge_path(v1, v2, timestamp, functor); - SASSERT(r); - r = m_graph.find_shortest_zero_edge_path(v2, v1, timestamp, functor); - SASSERT(r); + VERIFY(m_graph.find_shortest_zero_edge_path(v1, v2, timestamp, functor)); + VERIFY(m_graph.find_shortest_zero_edge_path(v2, v1, timestamp, functor)); } template diff --git a/src/util/bit_vector.cpp b/src/util/bit_vector.cpp index 6885b93e8..1490b9628 100644 --- a/src/util/bit_vector.cpp +++ b/src/util/bit_vector.cpp @@ -138,9 +138,8 @@ bool bit_vector::operator==(bit_vector const & source) const { bit_vector & bit_vector::operator|=(bit_vector const & source) { if (size() < source.size()) resize(source.size(), false); - unsigned n1 = num_words(); unsigned n2 = source.num_words(); - SASSERT(n2 <= n1); + SASSERT(n2 <= num_words()); unsigned bit_rest = source.m_num_bits % 32; if (bit_rest == 0) { unsigned i = 0; diff --git a/src/util/mpf.cpp b/src/util/mpf.cpp index 8cb6ed4fc..f5785c072 100644 --- a/src/util/mpf.cpp +++ b/src/util/mpf.cpp @@ -120,7 +120,8 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, double value) { // double === mpf(11, 53) COMPILE_TIME_ASSERT(sizeof(double) == 8); - uint64 raw = *reinterpret_cast(&value); + uint64 raw; + memcpy(&raw, &value, sizeof(double)); bool sign = (raw >> 63) != 0; int64 e = ((raw & 0x7FF0000000000000ull) >> 52) - 1023; uint64 s = raw & 0x000FFFFFFFFFFFFFull; @@ -155,7 +156,8 @@ void mpf_manager::set(mpf & o, unsigned ebits, unsigned sbits, float value) { // single === mpf(8, 24) COMPILE_TIME_ASSERT(sizeof(float) == 4); - unsigned int raw = *reinterpret_cast(&value); + unsigned int raw; + memcpy(&raw, &value, sizeof(float)); bool sign = (raw >> 31) != 0; signed int e = ((raw & 0x7F800000) >> 23) - 127; unsigned int s = raw & 0x007FFFFF; @@ -1288,7 +1290,9 @@ double mpf_manager::to_double(mpf const & x) { if (x.sign) raw = raw | 0x8000000000000000ull; - return *reinterpret_cast(&raw); + double ret; + memcpy(&ret, &raw, sizeof(double)); + return ret; } float mpf_manager::to_float(mpf const & x) { @@ -1318,7 +1322,9 @@ float mpf_manager::to_float(mpf const & x) { if (x.sign) raw = raw | 0x80000000; - return *reinterpret_cast(&raw); + float ret; + memcpy(&ret, &raw, sizeof(float)); + return ret; } bool mpf_manager::is_nan(mpf const & x) { @@ -1679,7 +1685,7 @@ void mpf_manager::round(mpf_rounding_mode rm, mpf & o) { TRACE("mpf_dbg", tout << "OVF2 = " << OVF2 << std::endl;); TRACE("mpf_dbg", tout << "o_has_max_exp = " << o_has_max_exp << std::endl;); - if (!OVFen && SIGovf && o_has_max_exp) + if (!OVFen && OVF2) mk_round_inf(rm, o); else { const mpz & p = m_powers2(o.sbits-1); diff --git a/src/util/mpff.cpp b/src/util/mpff.cpp index 892a7fe24..7678a051e 100644 --- a/src/util/mpff.cpp +++ b/src/util/mpff.cpp @@ -43,8 +43,7 @@ mpff_manager::mpff_manager(unsigned prec, unsigned initial_capacity) { for (unsigned i = 0; i < MPFF_NUM_BUFFERS; i++) m_buffers[i].resize(2 * prec, 0); // Reserve space for zero - unsigned zero_sig_idx = m_id_gen.mk(); - SASSERT(zero_sig_idx == 0); + VERIFY(m_id_gen.mk() == 0); set(m_one, 1); } diff --git a/src/util/mpfx.cpp b/src/util/mpfx.cpp index cf6f8338f..c0b3a1936 100644 --- a/src/util/mpfx.cpp +++ b/src/util/mpfx.cpp @@ -38,8 +38,7 @@ mpfx_manager::mpfx_manager(unsigned int_sz, unsigned frac_sz, unsigned initial_c m_buffer0.resize(2*m_total_sz, 0); m_buffer1.resize(2*m_total_sz, 0); m_buffer2.resize(2*m_total_sz, 0); - unsigned zero_sig_idx = m_id_gen.mk(); - SASSERT(zero_sig_idx == 0); + VERIFY(m_id_gen.mk() == 0); set(m_one, 1); } From 4c71e9479d00048a9a6f8666499d7e1f4b616c73 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Tue, 30 Sep 2014 11:21:34 -0700 Subject: [PATCH 022/117] optimizing array final check --- src/smt/theory_array_base.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index 3f96a1d62..6325a2a99 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -376,8 +376,10 @@ namespace smt { enode_vector::const_iterator end = r->end_parents(); for (; it != end; ++it) { enode * parent = *it; +#if 0 if (!ctx.is_relevant(parent)) continue; +#endif unsigned num_args = parent->get_num_args(); if (is_store(parent)) { SET_ARRAY(parent->get_arg(0)); @@ -399,6 +401,7 @@ namespace smt { return false; } +#if 0 void theory_array_base::collect_shared_vars(sbuffer & result) { TRACE("array_shared", tout << "collecting shared vars...\n";); context & ctx = get_context(); @@ -420,6 +423,29 @@ namespace smt { } unmark_enodes(to_unmark.size(), to_unmark.c_ptr()); } +#else + void theory_array_base::collect_shared_vars(sbuffer & result) { + TRACE("array_shared", tout << "collecting shared vars...\n";); + context & ctx = get_context(); + ptr_buffer to_unmark; + unsigned num_vars = get_num_vars(); + for (unsigned i = 0; i < num_vars; i++) { + enode * n = get_enode(i); + if (ctx.is_relevant(n)) { + enode * r = n->get_root(); + if (!r->is_marked() && is_array_sort(r) && ctx.is_shared(r)) { + TRACE("array_shared", tout << "new shared var: #" << r->get_owner_id() << "\n";); + theory_var r_th_var = r->get_th_var(get_id()); + SASSERT(r_th_var != null_theory_var); + result.push_back(r_th_var); + } + r->set_mark(); + to_unmark.push_back(r); + } + } + unmark_enodes(to_unmark.size(), to_unmark.c_ptr()); + } +#endif /** \brief Create interface variables for shared array variables. From 47635325014f2951d203897eae4d8120787a283d Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Tue, 30 Sep 2014 11:25:47 -0700 Subject: [PATCH 023/117] adding compile-time option to replace arrays with maps in smt (define SPARSE_MAP) --- src/smt/smt_context.h | 7 ++++++- src/smt/smt_enode.cpp | 6 +++--- src/smt/smt_enode.h | 29 ++++++++++++++++++++++++++--- src/util/map.h | 2 +- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 7940b17be..5abdfa5f9 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -54,7 +54,11 @@ Revision History: // the case that each context only references a few expressions. // Using a map instead of a vector for the literals can compress space // consumption. +#ifdef SPARSE_MAP +#define USE_BOOL_VAR_VECTOR 0 +#else #define USE_BOOL_VAR_VECTOR 1 +#endif namespace smt { @@ -69,6 +73,7 @@ namespace smt { std::string last_failure_as_string() const; void set_progress_callback(progress_callback *callback); + protected: ast_manager & m_manager; smt_params & m_fparams; @@ -106,7 +111,7 @@ namespace smt { // ----------------------------------- enode * m_true_enode; enode * m_false_enode; - ptr_vector m_app2enode; // app -> enode + app2enode_t m_app2enode; // app -> enode ptr_vector m_enodes; plugin_manager m_theories; // mapping from theory_id -> theory ptr_vector m_theory_set; // set of theories for fast traversal diff --git a/src/smt/smt_enode.cpp b/src/smt/smt_enode.cpp index 98b8eaf8b..451577357 100644 --- a/src/smt/smt_enode.cpp +++ b/src/smt/smt_enode.cpp @@ -24,7 +24,7 @@ namespace smt { /** \brief Initialize an enode in the given memory position. */ - enode * enode::init(ast_manager & m, void * mem, ptr_vector const & app2enode, app * owner, + enode * enode::init(ast_manager & m, void * mem, app2enode_t const & app2enode, app * owner, unsigned generation, bool suppress_args, bool merge_tf, unsigned iscope_lvl, bool cgc_enabled, bool update_children_parent) { SASSERT(m.is_bool(owner) || !merge_tf); @@ -60,7 +60,7 @@ namespace smt { return n; } - enode * enode::mk(ast_manager & m, region & r, ptr_vector const & app2enode, app * owner, + enode * enode::mk(ast_manager & m, region & r, app2enode_t const & app2enode, app * owner, unsigned generation, bool suppress_args, bool merge_tf, unsigned iscope_lvl, bool cgc_enabled, bool update_children_parent) { SASSERT(m.is_bool(owner) || !merge_tf); @@ -69,7 +69,7 @@ namespace smt { return init(m, mem, app2enode, owner, generation, suppress_args, merge_tf, iscope_lvl, cgc_enabled, update_children_parent); } - enode * enode::mk_dummy(ast_manager & m, ptr_vector const & app2enode, app * owner) { + enode * enode::mk_dummy(ast_manager & m, app2enode_t const & app2enode, app * owner) { unsigned sz = get_enode_size(owner->get_num_args()); void * mem = alloc_svect(char, sz); return init(m, mem, app2enode, owner, 0, false, false, 0, true, false); diff --git a/src/smt/smt_enode.h b/src/smt/smt_enode.h index 505dea0ee..ca75028c3 100644 --- a/src/smt/smt_enode.h +++ b/src/smt/smt_enode.h @@ -38,6 +38,29 @@ namespace smt { } }; + /** \ brief Use sparse maps in SMT solver. + + Define this to use hash maps rather than vectors over ast + nodes. This is useful in the case there are many solvers, each + referencing few nodes from a large ast manager. There is some + unknown performance penalty for this. */ + + // #define SPARSE_MAP + +#ifndef SPARSE_MAP + typedef ptr_vector app2enode_t; // app -> enode +#else + class app2enode_t : public u_map { + public: + void setx(unsigned x, enode *val, enode *def){ + if(val == 0) + erase(x); + else + insert(x,val); + } + }; +#endif + class tmp_enode; /** @@ -115,7 +138,7 @@ namespace smt { friend class tmp_enode; - static enode * init(ast_manager & m, void * mem, ptr_vector const & app2enode, app * owner, + static enode * init(ast_manager & m, void * mem, app2enode_t const & app2enode, app * owner, unsigned generation, bool suppress_args, bool merge_tf, unsigned iscope_lvl, bool cgc_enabled, bool update_children_parent); public: @@ -124,11 +147,11 @@ namespace smt { return sizeof(enode) + num_args * sizeof(enode*); } - static enode * mk(ast_manager & m, region & r, ptr_vector const & app2enode, app * owner, + static enode * mk(ast_manager & m, region & r, app2enode_t const & app2enode, app * owner, unsigned generation, bool suppress_args, bool merge_tf, unsigned iscope_lvl, bool cgc_enabled, bool update_children_parent); - static enode * mk_dummy(ast_manager & m, ptr_vector const & app2enode, app * owner); + static enode * mk_dummy(ast_manager & m, app2enode_t const & app2enode, app * owner); static void del_dummy(enode * n) { dealloc_svect(reinterpret_cast(n)); } diff --git a/src/util/map.h b/src/util/map.h index 3e8e10891..d659b89c0 100644 --- a/src/util/map.h +++ b/src/util/map.h @@ -131,7 +131,7 @@ public: value const& get(key const& k, value const& default_value) const { entry* e = find_core(k); if (e) { - return e->m_value; + return e->get_data().m_value; } else { return default_value; From 301cb51bbb81a3fd8db81e9baa8850dc2d6bc117 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Tue, 30 Sep 2014 12:42:30 -0700 Subject: [PATCH 024/117] added restarts options to duality (plus some other disabled features) --- src/duality/duality.h | 6 + src/duality/duality_rpfp.cpp | 67 ++++ src/duality/duality_solver.cpp | 391 +++++++++++++++++++++-- src/muz/base/fixedpoint_params.pyg | 1 + src/muz/duality/duality_dl_interface.cpp | 1 + 5 files changed, 446 insertions(+), 20 deletions(-) diff --git a/src/duality/duality.h b/src/duality/duality.h index 16576dd65..edd89d78f 100755 --- a/src/duality/duality.h +++ b/src/duality/duality.h @@ -104,6 +104,8 @@ namespace Duality { FuncDecl RenumberPred(const FuncDecl &f, int n); + FuncDecl NumberPred(const FuncDecl &f, int n); + Term ExtractStores(hash_map &memo, const Term &t, std::vector &cnstrs, hash_map &renaming); @@ -903,6 +905,10 @@ protected: int CumulativeDecisions(); + void GreedyReduceNodes(std::vector &nodes); + + check_result CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes); + solver &slvr(){ return *ls->slvr; } diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index 8c88dda72..f2824c9b0 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -2816,6 +2816,62 @@ namespace Duality { } } + void foobar(){ + } + + void RPFP::GreedyReduceNodes(std::vector &nodes){ + std::vector lits; + for(unsigned i = 0; i < nodes.size(); i++){ + Term b; std::vector v; + RedVars(nodes[i], b, v); + lits.push_back(!b); + expr bv = dualModel.eval(b); + if(eq(bv,ctx.bool_val(true))){ + check_result res = slvr_check(lits.size(),&lits[0]); + if(res == unsat) + lits.pop_back(); + else + foobar(); + } + } + } + + check_result RPFP::CheckWithConstrainedNodes(std::vector &posnodes,std::vector &negnodes){ + timer_start("Check"); + std::vector lits; + for(unsigned i = 0; i < posnodes.size(); i++){ + Term b; std::vector v; + RedVars(posnodes[i], b, v); + lits.push_back(b); + } + for(unsigned i = 0; i < negnodes.size(); i++){ + Term b; std::vector v; + RedVars(negnodes[i], b, v); + lits.push_back(!b); + } + check_result res = slvr_check(lits.size(),&lits[0]); + if(res == unsat && posnodes.size()){ + lits.resize(posnodes.size()); + res = slvr_check(lits.size(),&lits[0]); + } + dualModel = slvr().get_model(); +#if 0 + if(!dualModel.null()){ + std::cout << "posnodes called:\n"; + for(unsigned i = 0; i < posnodes.size(); i++) + if(!Empty(posnodes[i])) + std::cout << posnodes[i]->Name.name() << "\n"; + std::cout << "negnodes called:\n"; + for(unsigned i = 0; i < negnodes.size(); i++) + if(!Empty(negnodes[i])) + std::cout << negnodes[i]->Name.name() << "\n"; + } +#endif + timer_stop("Check"); + return res; + } + + void RPFP_caching::FilterCore(std::vector &core, std::vector &full_core){ hash_set core_set; std::copy(full_core.begin(),full_core.end(),std::inserter(core_set,core_set.begin())); @@ -3333,6 +3389,17 @@ namespace Duality { return ctx.function(name.c_str(), arity, &domain[0], f.range()); } + Z3User::FuncDecl Z3User::NumberPred(const FuncDecl &f, int n) + { + std::string name = f.name().str(); + name = name + "_" + string_of_int(n); + int arity = f.arity(); + std::vector domain; + for(int i = 0; i < arity; i++) + domain.push_back(f.domain(i)); + return ctx.function(name.c_str(), arity, &domain[0], f.range()); + } + // Scan the clause body for occurrences of the predicate unknowns RPFP::Term RPFP::ScanBody(hash_map &memo, diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index f54e00693..49e591be2 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -255,6 +255,13 @@ namespace Duality { /** Called when done expanding a tree */ virtual void Done() {} + + /** Ask whether a node should be used/unused in the tree. Returns, + 1 if yes, -1 if no, and 0 if don't care. */ + + virtual int UseNode(Node *node){ + return 0; + } }; /** The Proposer class proposes conjectures eagerly. These can come @@ -302,6 +309,7 @@ namespace Duality { hash_set overapproxes; std::vector proposers; std::string ConjectureFile; + bool stratified_inlining_done; #ifdef BOUNDED struct Counter { @@ -314,6 +322,13 @@ namespace Duality { /** Solve the problem. */ virtual bool Solve(){ + PreSolve(); + bool res = SolveMain(); // does the actual work + PostSolve(); + return res; + } + + void PreSolve(){ reporter = Report ? CreateStdoutReporter(rpfp) : new Reporter(rpfp); conj_reporter = ConjectureFile.empty() ? 0 : CreateConjectureFileReporter(rpfp,ConjectureFile); #ifndef LOCALIZE_CONJECTURES @@ -342,9 +357,10 @@ namespace Duality { return false; #endif StratifiedLeafCount = -1; - timer_start("SolveMain"); - bool res = SolveMain(); // does the actual work - timer_stop("SolveMain"); + stratified_inlining_done = false; + } + + void PostSolve(){ // print_profile(std::cout); delete indset; delete heuristic; @@ -354,7 +370,16 @@ namespace Duality { delete conj_reporter; for(unsigned i = 0; i < proposers.size(); i++) delete proposers[i]; - return res; + } + + bool RecheckBounds(){ + for(unsigned i = 0; i < unwinding->nodes.size(); i++){ + Node *node = unwinding->nodes[i]; + node->Bound = node->map->Bound; + if(!SatisfyUpperBound(node)) + return false; + } + return true; } void CreateInitialUnwinding(){ @@ -417,6 +442,7 @@ namespace Duality { bool StratifiedInlining; // Do stratified inlining as preprocessing step int RecursionBound; // Recursion bound for bounded verification bool BatchExpand; + bool EnableRestarts; bool SetBoolOption(bool &opt, const std::string &value){ if(value == "0") { @@ -464,6 +490,9 @@ namespace Duality { if(option == "conjecture_file"){ ConjectureFile = value; } + if(option == "enable_restarts"){ + return SetBoolOption(EnableRestarts,value); + } return false; } @@ -901,6 +930,9 @@ namespace Duality { */ bool DoStratifiedInlining(){ + if(stratified_inlining_done) + return true; + stratified_inlining_done = true; DoTopoSort(); int depth = 1; // TODO: make this an option std::vector > unfolding_levels(depth+1); @@ -1043,10 +1075,17 @@ namespace Duality { h->SetOldNode(node); } + bool SolveMain(){ + timer_start("SolveMain"); + bool res = SolveMainInt(); // does the actual work + timer_stop("SolveMain"); + return res; + } + /** This does the actual solving work. We try to generate candidates for extension. If we succed, we extend the unwinding. If we fail, we have a solution. */ - bool SolveMain(){ + bool SolveMainInt(){ if(StratifiedInlining && !DoStratifiedInlining()) return false; #ifdef BOUNDED @@ -1776,6 +1815,7 @@ namespace Duality { } timer_stop("Propagate"); } + /** This class represents a derivation tree. */ class DerivationTree { @@ -2127,6 +2167,8 @@ namespace Duality { hash_map updates; + int restart_interval; + DerivationTreeSlow(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand) : DerivationTree(_duality, rpfp, _reporter, _heuristic, _full_expand) { stack.push_back(stack_entry()); @@ -2135,6 +2177,7 @@ namespace Duality { struct DoRestart {}; virtual bool Build(){ + restart_interval = 3; while (true) { try { return BuildMain(); @@ -2145,15 +2188,47 @@ namespace Duality { while(stack.size() > 1) PopLevel(); reporter->Message("restarted"); + restart_interval += 1; } } } + + // When we check, try to use the same children that were used in the + // previous counterexample. + check_result Check(){ +#if 0 + std::vector posnodes, negnodes; + std::vector &expansions = stack.back().expansions; + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + std::vector &chs = node->Outgoing->Children; + for(unsigned j = 0; j < chs.size(); j++){ + Node *ch = chs[j]; + int use = heuristic->UseNode(ch); + if(use == 1) + posnodes.push_back(ch); + else if (use == -1) + negnodes.push_back(ch); + } + } + if(!(posnodes.empty() && negnodes.empty())){ + check_result res = tree->CheckWithConstrainedNodes(posnodes,negnodes); + if(res != unsat){ + reporter->Message("matched previous counterexample"); + return res; + } + } +#endif + return tree->Check(top); + } + bool BuildMain(){ stack.back().level = tree->slvr().get_scope_level(); bool was_sat = true; int update_failures = 0; + int total_updates = 0; while (true) { @@ -2165,7 +2240,7 @@ namespace Duality { reporter->Depth(stack.size()); // res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop - check_result foo = tree->Check(top); + check_result foo = Check(); res = foo == unsat ? l_false : l_true; if (res == l_false) { @@ -2193,11 +2268,18 @@ namespace Duality { throw DoRestart(); } #endif - if(RecordUpdate(node)) + if(RecordUpdate(node)){ update_count++; + total_updates++; + } else heuristic->Update(node->map); // make it less likely to expand this node in future } +#if 1 + if(duality->EnableRestarts) + if(total_updates >= restart_interval) + throw DoRestart(); +#endif if(update_count == 0){ if(was_sat){ update_failures++; @@ -2243,6 +2325,10 @@ namespace Duality { tree->Push(); std::vector &expansions = stack.back().expansions; #ifndef NO_DECISIONS +#if 0 + if(expansions.size() > 0) + tree->GreedyReduceNodes(expansions[0]->Outgoing->Children); // try to reduce number of children +#endif for(unsigned i = 0; i < expansions.size(); i++){ tree->FixCurrentState(expansions[i]->Outgoing); } @@ -2262,15 +2348,42 @@ namespace Duality { if(ExpandSomeNodes(false,expand_max)) continue; tree->Pop(1); + node_order.clear(); while(stack.size() > 1){ tree->Pop(1); + std::vector &expansions = stack.back().expansions; + for(unsigned i = 0; i < expansions.size(); i++) + node_order.push_back(expansions[i]); stack.pop_back(); } +#if 0 + Reduce(); +#endif return true; } } } + std::vector node_order; + + void Reduce(){ + tree->Push(); + // tree->AssertNode(top); // assert the negation of the top-level spec + for(int i = node_order.size()-1; i >= 0; --i){ + Edge *edge = node_order[i]->Outgoing; + if(edge){ + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *ch = edge->Children[j]; + if(!ch->Outgoing) + ch->Annotation.SetEmpty(); + } + tree->AssertEdge(edge,0,true); + } + } + tree->GreedyReduceNodes(node_order); // try to reduce the counterexample size + tree->Pop(1); + } + void PopLevel(){ std::vector &expansions = stack.back().expansions; tree->Pop(1); @@ -2869,17 +2982,7 @@ namespace Duality { return name; } - virtual void ChooseExpand(const std::set &choices, std::set &best, bool high_priority, bool best_only){ - if(!high_priority || !old_cex.get_tree()){ - Heuristic::ChooseExpand(choices,best,false); - return; - } - // first, try to match the derivatino tree nodes to the old cex - std::set matched, unmatched; - for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ - Node *node = (*it); - if(cex_map.empty()) - cex_map[node] = old_cex.get_root(); // match the root nodes + Node *MatchNode(Node *node){ if(cex_map.find(node) == cex_map.end()){ // try to match an unmatched node Node *parent = node->Incoming[0]->Parent; // assumes we are a tree! if(cex_map.find(parent) == cex_map.end()) @@ -2902,7 +3005,30 @@ namespace Duality { cex_map[chs[i]] = 0; } matching_done: - Node *old_node = cex_map[node]; + return cex_map[node]; + } + + int UseNode(Node *node){ + if (!old_cex.get_tree()) + return 0; + Node *old_node = MatchNode(node); + if(!old_node) + return 0; + return old_cex.get_tree()->Empty(old_node) ? -1 : 1; + } + + virtual void ChooseExpand(const std::set &choices, std::set &best, bool high_priority, bool best_only){ + if(cex_map.empty()) + cex_map[*(choices.begin())] = old_cex.get_root(); // match the root nodes + if(!high_priority || !old_cex.get_tree()){ + Heuristic::ChooseExpand(choices,best,false); + return; + } + // first, try to match the derivatino tree nodes to the old cex + std::set matched, unmatched; + for(std::set::iterator it = choices.begin(), en = choices.end(); it != en; ++it){ + Node *node = (*it); + Node *old_node = MatchNode(node); if(!old_node) unmatched.insert(node); else if(old_cex.get_tree()->Empty(old_node)) @@ -3177,8 +3303,233 @@ namespace Duality { }; + + class DualityDepthBounded : public Solver { + + Duality *duality; + context &ctx; // Z3 context + solver &slvr; // Z3 solver + + public: + DualityDepthBounded(RPFP *_rpfp) : + ctx(_rpfp->ctx), + slvr(_rpfp->slvr()){ + rpfp = _rpfp; + DepthBoundRPFP(); + duality = alloc(Duality,drpfp); + } + + ~DualityDepthBounded(){ + dealloc(duality); + delete drpfp; + } + + bool Solve(){ + int depth_bound = 10; + bool res; + SetMaxDepthRPFP(depth_bound); + duality->PreSolve(); + while(true){ + res = duality->SolveMain(); + if(!res || GetSolution()) + break; + depth_bound++; + SetMaxDepthRPFP(depth_bound); + res = duality->RecheckBounds(); + if(!res) + break; + } + duality->PostSolve(); + if(!res) + ConvertCex(); + return res; + } + + Counterexample &GetCounterexample(){ + return cex; + } + + bool SetOption(const std::string &option, const std::string &value){ + return duality->SetOption(option,value); + } + + virtual void LearnFrom(Solver *old_solver){ + DualityDepthBounded *old = dynamic_cast(old_solver); + if(old){ + duality->LearnFrom(old->duality); + } + } + + bool IsResultRecursionBounded(){ + return duality->IsResultRecursionBounded(); + } + + void Cancel(){ + duality->Cancel(); + } + + typedef RPFP::Node Node; + typedef RPFP::Edge Edge; + RPFP *rpfp, *drpfp; + hash_map db_map, db_rev_map; + hash_map db_edge_rev_map; + std::vector db_saved_bounds; + Counterexample cex; + + expr AddParamToRels(hash_map &memo, hash_map &rmap, const expr &p, const expr &t) { + std::pair foo(t,expr(ctx)); + std::pair::iterator, bool> bar = memo.insert(foo); + expr &res = bar.first->second; + if(!bar.second) return res; + + if (t.is_app()) + { + func_decl f = t.decl(); + std::vector args; + int nargs = t.num_args(); + for(int i = 0; i < nargs; i++) + args.push_back(AddParamToRels(memo, rmap, p, t.arg(i))); + hash_map::iterator rit = rmap.find(f); + if(rit != rmap.end()){ + args.push_back(p); + res = (rit->second)(args); + res = ctx.make(And,res,ctx.make(Geq,p,ctx.int_val(0))); + } + else + res = f(args); + } + else if (t.is_quantifier()) + { + expr body = AddParamToRels(memo, rmap, p, t.body()); + res = clone_quantifier(t, body); + } + else res = t; + return res; + } + + + void DepthBoundRPFP(){ + drpfp = new RPFP(rpfp->ls); + expr dvar = ctx.int_const("@depth"); + expr dmax = ctx.int_const("@depth_max"); + for(unsigned i = 0; i < rpfp->nodes.size(); i++){ + Node *node = rpfp->nodes[i]; + std::vector arg_sorts; + const std::vector ¶ms = node->Annotation.IndParams; + for(unsigned j = 0; j < params.size(); j++) + arg_sorts.push_back(params[j].get_sort()); + arg_sorts.push_back(ctx.int_sort()); + std::string new_name = std::string("@db@") + node->Name.name().str(); + func_decl f = ctx.function(new_name.c_str(),arg_sorts.size(), &arg_sorts[0],ctx.bool_sort()); + std::vector args = params; + args.push_back(dvar); + expr pat = f(args); + Node *dnode = drpfp->CreateNode(pat); + db_map[node] = dnode; + db_rev_map[dnode] = node; + expr bound_fmla = node->Bound.Formula; + if(!eq(bound_fmla,ctx.bool_val(true))){ + bound_fmla = implies(dvar == dmax,bound_fmla); + dnode->Bound.Formula = bound_fmla; + } + db_saved_bounds.push_back(bound_fmla); + // dnode->Annotation.Formula = ctx.make(And,node->Annotation.Formula,ctx.make(Geq,dvar,ctx.int_val(0))); + } + for(unsigned i = 0; i < rpfp->edges.size(); i++){ + Edge *edge = rpfp->edges[i]; + std::vector new_children; + std::vector new_relparams; + hash_map rmap; + for(unsigned j = 0; j < edge->Children.size(); j++){ + Node *ch = edge->Children[j]; + Node *nch = db_map[ch]; + func_decl f = nch->Name; + func_decl sf = drpfp->NumberPred(f,j); + new_children.push_back(nch); + new_relparams.push_back(sf); + rmap[edge->F.RelParams[j]] = sf; + } + std::vector new_indparams = edge->F.IndParams; + new_indparams.push_back(dvar); + hash_map memo; + expr new_fmla = AddParamToRels(memo,rmap,ctx.make(Sub,dvar,ctx.int_val(1)),edge->F.Formula); + RPFP::Transformer new_t = drpfp->CreateTransformer(new_relparams,new_indparams,new_fmla); + Node *new_parent = db_map[edge->Parent]; + db_edge_rev_map[drpfp->CreateEdge(new_parent,new_t,new_children)] = edge; + } + } + + void SetMaxDepthRPFP(int depth){ + hash_map subst; + expr dmax = ctx.int_const("@depth_max"); + subst[dmax] = ctx.int_val(depth); + for(unsigned i = 0; i < drpfp->nodes.size(); i++){ + Node *node = drpfp->nodes[i]; + expr fmla = db_saved_bounds[i]; + fmla = drpfp->SubstRec(subst,fmla); + node->Bound.Formula = fmla; + } + } + + void ConvertCex(){ + cex.clear(); + RPFP *tree = new RPFP(rpfp->ls); + Node *root; + Counterexample &dctx = duality->GetCounterexample(); + hash_map ctx_node_map; + for(unsigned i = 0; i < dctx.get_tree()->nodes.size(); i++){ + Node *dnode = dctx.get_tree()->nodes[i]; + Node *onode = db_rev_map[dnode->map->map]; + Node *node = tree->CloneNode(onode); + node->number = dnode->number; // numbers have to match for model to make sense + ctx_node_map[dnode] = node; + if(dnode == dctx.get_root()) + root = node; + } + for(unsigned i = 0; i < dctx.get_tree()->edges.size(); i++){ + Edge *dedge = dctx.get_tree()->edges[i]; + Edge *oedge = db_edge_rev_map[dedge->map]; + Node *parent = ctx_node_map[dedge->Parent]; + std::vector chs; + for(unsigned j = 0; j < dedge->Children.size(); j++) + chs.push_back(ctx_node_map[dedge->Children[j]]); + Edge *edge = tree->CreateEdge(parent,oedge->F,chs); + edge->number = dedge->number; // numbers have to match for model to make sense + edge->map = oedge; + } + tree->dualModel = dctx.get_tree()->dualModel; + cex.set(tree,root); + } + + bool GetSolution(){ + for(unsigned i = 0; i < rpfp->nodes.size(); i++) + if(!drpfp->nodes[i]->Annotation.SubsetEq(rpfp->nodes[i]->Bound)) + return false; + expr dvar = ctx.int_const("@depth"); + hash_map subst; + subst[dvar] = ctx.int_val(INT_MAX); + for(unsigned i = 0; i < rpfp->nodes.size(); i++){ + expr fmla = drpfp->nodes[i]->Annotation.Formula; + fmla = drpfp->SubstRec(subst,fmla); + fmla = fmla.simplify(); + rpfp->nodes[i]->Annotation.Formula = fmla; + } + return true; + } + + void UndoDepthBoundRPFP(){ +#if 0 + if(cex.get_tree()){ + // here, need to map the cex back... + } + // also need to map the proof back, but we don't... +#endif + } + }; + Solver *Solver::Create(const std::string &solver_class, RPFP *rpfp){ - Duality *s = alloc(Duality,rpfp); + // Solver *s = alloc(DualityDepthBounded,rpfp); + Solver *s = alloc(Duality,rpfp); return s; } diff --git a/src/muz/base/fixedpoint_params.pyg b/src/muz/base/fixedpoint_params.pyg index 5bfbba6b2..832e3329e 100644 --- a/src/muz/base/fixedpoint_params.pyg +++ b/src/muz/base/fixedpoint_params.pyg @@ -78,6 +78,7 @@ def_module_params('fixedpoint', ('batch_expand', BOOL, False, 'DUALITY: use batch expansion'), ('dump_aig', SYMBOL, '', 'Dump clauses in AIG text format (AAG) to the given file name'), ('conjecture_file', STRING, '', 'DUALITY: save conjectures to file'), + ('enable_restarts', BOOL, False, 'DUALITY: enable restarts'), )) diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 08c57b05e..55f6c3747 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -281,6 +281,7 @@ lbool dl_interface::query(::expr * query) { rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0"); rs->SetOption("batch_expand",m_ctx.get_params().batch_expand() ? "1" : "0"); rs->SetOption("conjecture_file",m_ctx.get_params().conjecture_file()); + rs->SetOption("enable_restarts",m_ctx.get_params().enable_restarts() ? "1" : "0"); #if 0 if(rb != UINT_MAX){ std::ostringstream os; os << rb; From c5f17df310405b2f7718f1eaa93242cfa25e54de Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Wed, 1 Oct 2014 18:15:33 -0700 Subject: [PATCH 025/117] fixing an assert caused by previous change in theory_array_base.cpp --- src/smt/theory_array_base.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index 6325a2a99..b2c17b4e0 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -433,14 +433,16 @@ namespace smt { enode * n = get_enode(i); if (ctx.is_relevant(n)) { enode * r = n->get_root(); - if (!r->is_marked() && is_array_sort(r) && ctx.is_shared(r)) { - TRACE("array_shared", tout << "new shared var: #" << r->get_owner_id() << "\n";); - theory_var r_th_var = r->get_th_var(get_id()); - SASSERT(r_th_var != null_theory_var); - result.push_back(r_th_var); + if (!r->is_marked()){ + if(is_array_sort(r) && ctx.is_shared(r)) { + TRACE("array_shared", tout << "new shared var: #" << r->get_owner_id() << "\n";); + theory_var r_th_var = r->get_th_var(get_id()); + SASSERT(r_th_var != null_theory_var); + result.push_back(r_th_var); + } + r->set_mark(); + to_unmark.push_back(r); } - r->set_mark(); - to_unmark.push_back(r); } } unmark_enodes(to_unmark.size(), to_unmark.c_ptr()); From d54d758f45b745ec129db375364d5a00eef23ce5 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Wed, 1 Oct 2014 18:16:21 -0700 Subject: [PATCH 026/117] getting duality to recover from incompleteness-related failures by restarting --- src/duality/duality_profiling.cpp | 10 ++++++++++ src/duality/duality_solver.cpp | 25 ++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/duality/duality_profiling.cpp b/src/duality/duality_profiling.cpp index d5dac0811..5bcda972a 100755 --- a/src/duality/duality_profiling.cpp +++ b/src/duality/duality_profiling.cpp @@ -125,8 +125,18 @@ namespace Duality { void timer_stop(const char *name){ if(current->name != name || !current->parent){ +#if 0 std::cerr << "imbalanced timer_start and timer_stop"; exit(1); +#endif + // in case we lost a timer stop due to an exception + while(current->name != name && current->parent) + current = current->parent; + if(current->parent){ + current->time += (current_time() - current->start_time); + current = current->parent; + } + return; } current->time += (current_time() - current->start_time); current = current->parent; diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index 49e591be2..bbd1ebe0a 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -2252,22 +2252,27 @@ namespace Duality { int update_count = 0; for(unsigned i = 0; i < expansions.size(); i++){ Node *node = expansions[i]; - tree->SolveSingleNode(top,node); -#ifdef NO_GENERALIZE - node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); -#else try { + tree->SolveSingleNode(top,node); +#ifdef NO_GENERALIZE + node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); +#else if(expansions.size() == 1 && NodeTooComplicated(node)) SimplifyNode(node); else node->Annotation.Formula = tree->RemoveRedundancy(node->Annotation.Formula).simplify(); Generalize(node); +#endif } catch(const RPFP::Bad &){ // bad interpolants can get us here throw DoRestart(); } -#endif + catch(char const *msg){ + // bad interpolants can get us here + reporter->Message(std::string("interpolation failure:") + msg); + throw DoRestart(); + } if(RecordUpdate(node)){ update_count++; total_updates++; @@ -2283,8 +2288,14 @@ namespace Duality { if(update_count == 0){ if(was_sat){ update_failures++; - if(update_failures > 10) - throw Incompleteness(); + if(update_failures > 10){ + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + node->map->Annotation.SetFull(); + reporter->Message("incompleteness: cleared annotation"); + } + throw DoRestart(); + } } reporter->Message("backtracked without learning"); } From d03a4bc306ae59ef27d6508a3670cb7f7fd8e900 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 2 Oct 2014 14:33:42 -0700 Subject: [PATCH 027/117] check cancel flag after bcp. BCP returns in incomplete state after it check's the cancel flag. Propagate returns 'true' in this case so that the main loop exits Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 02ee06985..f3f2d4948 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1615,6 +1615,8 @@ namespace smt { unsigned qhead = m_qhead; if (!bcp()) return false; + if (m_cancel_flag) + return true; SASSERT(!inconsistent()); propagate_relevancy(qhead); if (inconsistent()) From fbb01f369959cfd35ea16495bf64c96728376353 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 2 Oct 2014 23:58:52 -0700 Subject: [PATCH 028/117] prevent usage that mixes E/e notation with division / for numerals Signed-off-by: Nikolaj Bjorner --- src/util/mpq.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/util/mpq.cpp b/src/util/mpq.cpp index eda937029..df4d207a6 100644 --- a/src/util/mpq.cpp +++ b/src/util/mpq.cpp @@ -235,6 +235,9 @@ void mpq_manager::set(mpq & a, char const * val) { SASSERT(str[0] - '0' <= 9); exp = (10*exp) + (str[0] - '0'); } + else if ('/' == str[0]) { + throw default_exception("mixing rational/scientific notation"); + } TRACE("mpq_set", tout << "[exp]: " << exp << ", str[0]: " << (str[0] - '0') << std::endl;); ++str; } From 16445569f1a6cfd3fa04c7227d3d724dd16947c7 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Sat, 4 Oct 2014 16:31:01 -0700 Subject: [PATCH 029/117] fix for quantifier abstraction --- src/muz/transforms/dl_transforms.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/muz/transforms/dl_transforms.cpp b/src/muz/transforms/dl_transforms.cpp index 2cf48d46b..9a4667f2c 100644 --- a/src/muz/transforms/dl_transforms.cpp +++ b/src/muz/transforms/dl_transforms.cpp @@ -71,7 +71,8 @@ namespace datalog { transf.register_plugin(alloc(datalog::mk_quantifier_instantiation, ctx, 32000)); transf.register_plugin(alloc(datalog::mk_bit_blast, ctx, 35000)); - transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); + if (!ctx.get_params().quantify_arrays()) + transf.register_plugin(alloc(datalog::mk_array_blast, ctx, 36000)); transf.register_plugin(alloc(datalog::mk_karr_invariants, ctx, 36010)); if (ctx.get_params().magic()) { transf.register_plugin(alloc(datalog::mk_magic_symbolic, ctx, 36020)); From e8985ff33dcb2d9d2705d632468443abb811ee99 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Sat, 4 Oct 2014 17:17:33 -0700 Subject: [PATCH 030/117] working on transforms in duality --- src/muz/duality/duality_dl_interface.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index 55f6c3747..c7fa0a08f 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -157,7 +157,27 @@ lbool dl_interface::query(::expr * query) { svector< ::symbol> names; vector bounds; // m_ctx.get_rules_as_formulas(rules, names); - m_ctx.get_raw_rule_formulas(rules, names, bounds); + + expr_ref query_ref(m_ctx.get_manager()); + if(****){ + m_ctx.flush_add_rules(); + datalog::rule_manager& rm = m_ctx.get_rule_manager(); + rm.mk_query(query, m_ctx.get_rules()); + apply_default_transformation(m_ctx); + rule_set &rs = m_ctx.get_rules(); + if(m_ctx.get_rules().get_output_predicates().empty()) + query_ref = m_ctx.get_manager().mk_true(); + else { + query_pred = m_ctx.get_rules().get_output_predicate(); + func_decl_ref query_pred(m_ctx.get_manager()); + query_pred = m_ctx.get_rules().get_output_predicate(); + ptr_vector sorts; + unsi + + } + } + else + m_ctx.get_raw_rule_formulas(rules, names, bounds); // get all the rules as clauses std::vector &clauses = _d->clauses; From 6a3f75822d9ee27b35326a83bb1363d648ec6d7d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 4 Oct 2014 18:35:18 -0700 Subject: [PATCH 031/117] fix format bug (issue 126) and smaller nits in sat solver (const annotation, disable elimination of external or already elimianted variables) Signed-off-by: Nikolaj Bjorner --- src/sat/sat_asymm_branch.cpp | 2 +- src/sat/sat_asymm_branch.h | 2 +- src/sat/sat_cleaner.cpp | 2 +- src/sat/sat_cleaner.h | 2 +- src/sat/sat_probing.cpp | 3 ++- src/sat/sat_probing.h | 2 +- src/sat/sat_scc.cpp | 2 +- src/sat/sat_scc.h | 2 +- src/sat/sat_simplifier.cpp | 8 +++++++- src/sat/sat_simplifier.h | 2 +- src/sat/sat_solver.cpp | 4 +--- src/util/cmd_context_types.h | 8 ++++---- 12 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/sat/sat_asymm_branch.cpp b/src/sat/sat_asymm_branch.cpp index b8ac520b2..193bf59f2 100644 --- a/src/sat/sat_asymm_branch.cpp +++ b/src/sat/sat_asymm_branch.cpp @@ -215,7 +215,7 @@ namespace sat { sat_asymm_branch_params::collect_param_descrs(d); } - void asymm_branch::collect_statistics(statistics & st) { + void asymm_branch::collect_statistics(statistics & st) const { st.update("elim literals", m_elim_literals); } diff --git a/src/sat/sat_asymm_branch.h b/src/sat/sat_asymm_branch.h index 6ffd239eb..f10522fab 100644 --- a/src/sat/sat_asymm_branch.h +++ b/src/sat/sat_asymm_branch.h @@ -49,7 +49,7 @@ namespace sat { void updt_params(params_ref const & p); static void collect_param_descrs(param_descrs & d); - void collect_statistics(statistics & st); + void collect_statistics(statistics & st) const; void reset_statistics(); void dec(unsigned c) { m_counter -= c; } diff --git a/src/sat/sat_cleaner.cpp b/src/sat/sat_cleaner.cpp index 4b1ac2c92..959f5e94f 100644 --- a/src/sat/sat_cleaner.cpp +++ b/src/sat/sat_cleaner.cpp @@ -206,7 +206,7 @@ namespace sat { m_elim_literals = 0; } - void cleaner::collect_statistics(statistics & st) { + void cleaner::collect_statistics(statistics & st) const { st.update("elim clauses", m_elim_clauses); st.update("elim literals", m_elim_literals); } diff --git a/src/sat/sat_cleaner.h b/src/sat/sat_cleaner.h index d4306afcd..d22408926 100644 --- a/src/sat/sat_cleaner.h +++ b/src/sat/sat_cleaner.h @@ -42,7 +42,7 @@ namespace sat { bool operator()(bool force = false); - void collect_statistics(statistics & st); + void collect_statistics(statistics & st) const; void reset_statistics(); void dec() { m_cleanup_counter--; } diff --git a/src/sat/sat_probing.cpp b/src/sat/sat_probing.cpp index f9741cd7b..165d39ad8 100644 --- a/src/sat/sat_probing.cpp +++ b/src/sat/sat_probing.cpp @@ -196,6 +196,7 @@ namespace sat { s.propagate(false); // make sure propagation queue is empty if (s.inconsistent()) return true; + SASSERT(s.m_qhead == s.m_trail.size()); CASSERT("probing", s.check_invariant()); if (!force && m_counter > 0) return true; @@ -259,7 +260,7 @@ namespace sat { m_to_assert.finalize(); } - void probing::collect_statistics(statistics & st) { + void probing::collect_statistics(statistics & st) const { st.update("probing assigned", m_num_assigned); } diff --git a/src/sat/sat_probing.h b/src/sat/sat_probing.h index 9f3c1ae87..2061b74bd 100644 --- a/src/sat/sat_probing.h +++ b/src/sat/sat_probing.h @@ -71,7 +71,7 @@ namespace sat { void free_memory(); - void collect_statistics(statistics & st); + void collect_statistics(statistics & st) const; void reset_statistics(); // return the literals implied by l. diff --git a/src/sat/sat_scc.cpp b/src/sat/sat_scc.cpp index 29f3f006f..ffbdb31c6 100644 --- a/src/sat/sat_scc.cpp +++ b/src/sat/sat_scc.cpp @@ -223,7 +223,7 @@ namespace sat { return to_elim.size(); } - void scc::collect_statistics(statistics & st) { + void scc::collect_statistics(statistics & st) const { st.update("elim bool vars", m_num_elim); } diff --git a/src/sat/sat_scc.h b/src/sat/sat_scc.h index c85cc7d42..5f69e11c6 100644 --- a/src/sat/sat_scc.h +++ b/src/sat/sat_scc.h @@ -40,7 +40,7 @@ namespace sat { void updt_params(params_ref const & p); static void collect_param_descrs(param_descrs & d); - void collect_statistics(statistics & st); + void collect_statistics(statistics & st) const; void reset_statistics(); }; }; diff --git a/src/sat/sat_simplifier.cpp b/src/sat/sat_simplifier.cpp index f20ffa7c7..753075b10 100644 --- a/src/sat/sat_simplifier.cpp +++ b/src/sat/sat_simplifier.cpp @@ -918,7 +918,11 @@ namespace sat { void process(literal l) { TRACE("blocked_clause", tout << "processing: " << l << "\n";); model_converter::entry * new_entry = 0; + if (s.is_external(l.var()) || s.was_eliminated(l.var())) + return; + { + m_to_remove.reset(); { clause_use_list & occs = s.m_use_list.get(l); @@ -1339,6 +1343,7 @@ namespace sat { } TRACE("resolution", tout << "found var to eliminate, before: " << before_clauses << " after: " << after_clauses << "\n";); + // eliminate variable model_converter::entry & mc_entry = s.m_mc.mk(model_converter::ELIM_VAR, v); save_clauses(mc_entry, m_pos_cls); @@ -1421,6 +1426,7 @@ namespace sat { }; void simplifier::elim_vars() { + IF_VERBOSE(10, s.display(verbose_stream());); elim_var_report rpt(*this); bool_var_vector vars; order_vars_for_elim(vars); @@ -1466,7 +1472,7 @@ namespace sat { sat_simplifier_params::collect_param_descrs(r); } - void simplifier::collect_statistics(statistics & st) { + void simplifier::collect_statistics(statistics & st) const { st.update("subsumed", m_num_subsumed); st.update("subsumption resolution", m_num_sub_res); st.update("elim literals", m_num_elim_lits); diff --git a/src/sat/sat_simplifier.h b/src/sat/sat_simplifier.h index 96d346598..cb6fa9557 100644 --- a/src/sat/sat_simplifier.h +++ b/src/sat/sat_simplifier.h @@ -180,7 +180,7 @@ namespace sat { void free_memory(); - void collect_statistics(statistics & st); + void collect_statistics(statistics & st) const; void reset_statistics(); }; }; diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index e7dee83ae..f898130af 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -459,9 +459,6 @@ namespace sat { void solver::set_conflict(justification c, literal not_l) { if (m_inconsistent) return; - TRACE("sat_conflict", tout << "conflict\n";); - // int * p = 0; - // *p = 0; m_inconsistent = true; m_conflict = c; m_not_l = not_l; @@ -863,6 +860,7 @@ namespace sat { m_next_simplify = 0; m_stopwatch.reset(); m_stopwatch.start(); + TRACE("sat", display(tout);); } /** diff --git a/src/util/cmd_context_types.h b/src/util/cmd_context_types.h index b0a0226e8..e334dc0d2 100644 --- a/src/util/cmd_context_types.h +++ b/src/util/cmd_context_types.h @@ -55,12 +55,12 @@ class cmd_exception : public default_exception { } public: cmd_exception(char const * msg):default_exception(msg), m_line(-1), m_pos(-1) {} - cmd_exception(std::string const & msg):default_exception(msg.c_str()), m_line(-1), m_pos(-1) {} - cmd_exception(std::string const & msg, int line, int pos):default_exception(msg.c_str()), m_line(line), m_pos(pos) {} + cmd_exception(std::string const & msg):default_exception(msg), m_line(-1), m_pos(-1) {} + cmd_exception(std::string const & msg, int line, int pos):default_exception(msg), m_line(line), m_pos(pos) {} cmd_exception(char const * msg, symbol const & s): - default_exception(compose(msg,s).c_str()),m_line(-1),m_pos(-1) {} + default_exception(compose(msg,s)),m_line(-1),m_pos(-1) {} cmd_exception(char const * msg, symbol const & s, int line, int pos): - default_exception(compose(msg,s).c_str()),m_line(line),m_pos(pos) {} + default_exception(compose(msg,s)),m_line(line),m_pos(pos) {} bool has_pos() const { return m_line >= 0; } int line() const { SASSERT(has_pos()); return m_line; } From ec48f6d129f856f216fc1885593e8d77ab6c89e8 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Sat, 4 Oct 2014 19:07:14 -0700 Subject: [PATCH 032/117] working on transforms for duality --- src/muz/base/dl_context.cpp | 3 +++ src/muz/duality/duality_dl_interface.cpp | 33 +++++++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/muz/base/dl_context.cpp b/src/muz/base/dl_context.cpp index 80af7eeb0..ca7277d07 100644 --- a/src/muz/base/dl_context.cpp +++ b/src/muz/base/dl_context.cpp @@ -985,6 +985,9 @@ namespace datalog { flush_add_rules(); break; case DUALITY_ENGINE: + // this lets us use duality with SAS 2013 abstraction + if(quantify_arrays()) + flush_add_rules(); break; default: UNREACHABLE(); diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index c7fa0a08f..7666b39cf 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -37,6 +37,7 @@ Revision History: #include "fixedpoint_params.hpp" #include "used_vars.h" #include "func_decl_dependencies.h" +#include "dl_transforms.h" // template class symbol_table; @@ -158,22 +159,34 @@ lbool dl_interface::query(::expr * query) { vector bounds; // m_ctx.get_rules_as_formulas(rules, names); + + // If using SAS 2013 abstractiion, we need to perform some transforms expr_ref query_ref(m_ctx.get_manager()); - if(****){ - m_ctx.flush_add_rules(); + if(m_ctx.quantify_arrays()){ datalog::rule_manager& rm = m_ctx.get_rule_manager(); rm.mk_query(query, m_ctx.get_rules()); apply_default_transformation(m_ctx); - rule_set &rs = m_ctx.get_rules(); + datalog::rule_set &rs = m_ctx.get_rules(); if(m_ctx.get_rules().get_output_predicates().empty()) - query_ref = m_ctx.get_manager().mk_true(); + query_ref = m_ctx.get_manager().mk_false(); else { - query_pred = m_ctx.get_rules().get_output_predicate(); - func_decl_ref query_pred(m_ctx.get_manager()); - query_pred = m_ctx.get_rules().get_output_predicate(); - ptr_vector sorts; - unsi - + func_decl_ref query_pred(m_ctx.get_manager()); + query_pred = m_ctx.get_rules().get_output_predicate(); + ptr_vector sorts; + unsigned nargs = query_pred.get()->get_arity(); + expr_ref_vector vars(m_ctx.get_manager()); + for(unsigned i = 0; i < nargs; i++){ + ::sort *s = query_pred.get()->get_domain(i); + vars.push_back(m_ctx.get_manager().mk_var(nargs-1-i,s)); + } + query_ref = m_ctx.get_manager().mk_app(query_pred.get(),nargs,vars.c_ptr()); + query = query_ref.get(); + } + unsigned nrules = rs.get_num_rules(); + for(unsigned i = 0; i < nrules; i++){ + expr_ref f(m_ctx.get_manager()); + rs.get_rule(i)->to_formula(f); + rules.push_back(f); } } else From 4e55f0494212272be80a7242505b1821811b7b13 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 5 Oct 2014 10:41:37 -0700 Subject: [PATCH 033/117] use more efficient encoding of shift operations Signed-off-by: Nikolaj Bjorner --- .../bit_blaster/bit_blaster_tpl_def.h | 101 ++++++++++++------ 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h b/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h index b41aa2238..b579d698e 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h +++ b/src/ast/rewriter/bit_blaster/bit_blaster_tpl_def.h @@ -911,18 +911,34 @@ void bit_blaster_tpl::mk_shl(unsigned sz, expr * const * a_bits, expr * con out_bits.push_back(a_bits[i]); } else { - expr_ref_vector eqs(m()); - mk_eqs(sz, b_bits, eqs); - for (unsigned i = 0; i < sz; i++) { + out_bits.append(sz, a_bits); + + unsigned i = 0; + expr_ref_vector new_out_bits(m()); + for (; i < sz; ++i) { checkpoint(); - expr_ref out(m()); - mk_ite(eqs.get(i), a_bits[0], m().mk_false(), out); - for (unsigned j = 1; j <= i; j++) { + unsigned shift_i = 1 << i; + if (shift_i >= sz) break; + for (unsigned j = 0; j < sz; ++j) { expr_ref new_out(m()); - mk_ite(eqs.get(i - j), a_bits[j], out, new_out); - out = new_out; + expr* a_j = m().mk_false(); + if (shift_i <= j) a_j = out_bits[j-shift_i].get(); + mk_ite(b_bits[i], a_j, out_bits[j].get(), new_out); + new_out_bits.push_back(new_out); } - out_bits.push_back(out); + out_bits.reset(); + out_bits.append(new_out_bits); + new_out_bits.reset(); + } + expr_ref is_large(m()); + is_large = m().mk_false(); + for (; i < sz; ++i) { + mk_or(is_large, b_bits[i], is_large); + } + for (unsigned j = 0; j < sz; ++j) { + expr_ref new_out(m()); + mk_ite(is_large, m().mk_false(), out_bits[j].get(), new_out); + out_bits[j] = new_out; } } } @@ -939,19 +955,32 @@ void bit_blaster_tpl::mk_lshr(unsigned sz, expr * const * a_bits, expr * co out_bits.push_back(m().mk_false()); } else { - expr_ref_vector eqs(m()); - mk_eqs(sz, b_bits, eqs); - out_bits.resize(sz); - for (unsigned i = 0; i < sz; i++) { + out_bits.append(sz, a_bits); + unsigned i = 0; + for (; i < sz; ++i) { checkpoint(); - expr_ref out(m()); - mk_ite(eqs.get(i), a_bits[sz-1], m().mk_false(), out); - for (unsigned j = 1; j <= i; j++) { + expr_ref_vector new_out_bits(m()); + unsigned shift_i = 1 << i; + if (shift_i >= sz) break; + for (unsigned j = 0; j < sz; ++j) { expr_ref new_out(m()); - mk_ite(eqs.get(i - j), a_bits[sz - j - 1], out, new_out); - out = new_out; + expr* a_j = m().mk_false(); + if (shift_i + j < sz) a_j = out_bits[j+shift_i].get(); + mk_ite(b_bits[i], a_j, out_bits[j].get(), new_out); + new_out_bits.push_back(new_out); } - out_bits.set(sz - i - 1, out); + out_bits.reset(); + out_bits.append(new_out_bits); + } + expr_ref is_large(m()); + is_large = m().mk_false(); + for (; i < sz; ++i) { + mk_or(is_large, b_bits[i], is_large); + } + for (unsigned j = 0; j < sz; ++j) { + expr_ref new_out(m()); + mk_ite(is_large, m().mk_false(), out_bits[j].get(), new_out); + out_bits[j] = new_out; } } } @@ -968,20 +997,32 @@ void bit_blaster_tpl::mk_ashr(unsigned sz, expr * const * a_bits, expr * co out_bits.push_back(a_bits[sz-1]); } else { - expr_ref_vector eqs(m()); - mk_eqs(sz, b_bits, eqs); - out_bits.resize(sz); - for (unsigned i = 0; i < sz; i++) { + out_bits.append(sz, a_bits); + unsigned i = 0; + for (; i < sz; ++i) { checkpoint(); - expr_ref out(m()); - out = a_bits[sz-1]; - for (unsigned j = 1; j <= i; j++) { + expr_ref_vector new_out_bits(m()); + unsigned shift_i = 1 << i; + if (shift_i >= sz) break; + for (unsigned j = 0; j < sz; ++j) { expr_ref new_out(m()); - mk_ite(eqs.get(i - j), a_bits[sz - j - 1], out, new_out); - out = new_out; + expr* a_j = a_bits[sz-1]; + if (shift_i + j < sz) a_j = out_bits[j+shift_i].get(); + mk_ite(b_bits[i], a_j, out_bits[j].get(), new_out); + new_out_bits.push_back(new_out); } - TRACE("bit_blaster", tout << (sz - i - 1) << " :\n" << mk_pp(out, m()) << "\n";); - out_bits.set(sz - i - 1, out); + out_bits.reset(); + out_bits.append(new_out_bits); + } + expr_ref is_large(m()); + is_large = m().mk_false(); + for (; i < sz; ++i) { + mk_or(is_large, b_bits[i], is_large); + } + for (unsigned j = 0; j < sz; ++j) { + expr_ref new_out(m()); + mk_ite(is_large, a_bits[sz-1], out_bits[j].get(), new_out); + out_bits[j] = new_out; } } } From cbf470422e501c2596aa7a824cbef009dc61e158 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 5 Oct 2014 12:10:23 -0700 Subject: [PATCH 034/117] remove extra verbose output Signed-off-by: Nikolaj Bjorner --- src/sat/sat_simplifier.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sat/sat_simplifier.cpp b/src/sat/sat_simplifier.cpp index 753075b10..219b9f278 100644 --- a/src/sat/sat_simplifier.cpp +++ b/src/sat/sat_simplifier.cpp @@ -1426,7 +1426,6 @@ namespace sat { }; void simplifier::elim_vars() { - IF_VERBOSE(10, s.display(verbose_stream());); elim_var_report rpt(*this); bool_var_vector vars; order_vars_for_elim(vars); From c6683fd6fa51e48e29cad58f90225f5b5df053fc Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 5 Oct 2014 12:27:57 -0700 Subject: [PATCH 035/117] to fix that timeout of 0 has different interpretations across platforms Signed-off-by: Nikolaj Bjorner --- src/util/scoped_timer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/scoped_timer.cpp b/src/util/scoped_timer.cpp index c4a640009..15891168c 100644 --- a/src/util/scoped_timer.cpp +++ b/src/util/scoped_timer.cpp @@ -129,7 +129,7 @@ struct scoped_timer::imp { WT_EXECUTEINTIMERTHREAD); #elif defined(__APPLE__) && defined(__MACH__) // Mac OS X - m_interval = ms; + m_interval = ms?ms:0xFFFFFFFF; if (pthread_attr_init(&m_attributes) != 0) throw default_exception("failed to initialize timer thread attributes"); if (pthread_cond_init(&m_condition_var, NULL) != 0) From 18e77bd53960b4cbc0fda837c210255981aabd4d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 5 Oct 2014 18:36:15 -0700 Subject: [PATCH 036/117] fix qe for undef scenarios, codeplex issue 130 Signed-off-by: Nikolaj Bjorner --- src/qe/qe.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/qe/qe.cpp b/src/qe/qe.cpp index 770a49c07..e573508bb 100644 --- a/src/qe/qe.cpp +++ b/src/qe/qe.cpp @@ -1449,11 +1449,19 @@ namespace qe { m_solver.assert_expr(m_fml); if (assumption) m_solver.assert_expr(assumption); - bool is_sat = false; - while (l_true == m_solver.check()) { - is_sat = true; + bool is_sat = false; + lbool res = l_true; + while (res == l_true) { + res = m_solver.check(); + if (res == l_true) is_sat = true; final_check(); } + if (res == l_undef) { + free_vars.append(num_vars, vars); + reset(); + m_solver.pop(1); + return; + } if (!is_sat) { fml = m.mk_false(); @@ -1484,12 +1492,13 @@ namespace qe { ); free_vars.append(m_free_vars); - SASSERT(!m_free_vars.empty() || m_solver.inconsistent()); + if (!m_free_vars.empty() || m_solver.inconsistent()) { - if (m_fml.get() != m_subfml.get()) { - scoped_ptr rp = mk_default_expr_replacer(m); - rp->apply_substitution(to_app(m_subfml.get()), fml, m_fml); - fml = m_fml; + if (m_fml.get() != m_subfml.get()) { + scoped_ptr rp = mk_default_expr_replacer(m); + rp->apply_substitution(to_app(m_subfml.get()), fml, m_fml); + fml = m_fml; + } } reset(); m_solver.pop(1); From 7ef1e8a3de0ee0ed6ff146710e75041d7542d463 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 5 Oct 2014 19:04:15 -0700 Subject: [PATCH 037/117] turn friends into inliers to respect namespace for non-operator friends. Operaor friends will stil be in file scope so do not take name-space qualifier Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 2 + src/api/c++/z3++.h | 120 +++++++++++++++++++++++++-------------- 2 files changed, 79 insertions(+), 43 deletions(-) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index 77f7702f2..b348e7d36 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -1,5 +1,7 @@ #include #include"z3++.h" + + using namespace z3; /** diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 8f228cdba..20100d124 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -85,6 +85,8 @@ namespace z3 { friend std::ostream & operator<<(std::ostream & out, exception const & e) { out << e.msg(); return out; } }; + + /** \brief Z3 global configuration object. */ @@ -269,8 +271,9 @@ namespace z3 { object(object const & s):m_ctx(s.m_ctx) {} context & ctx() const { return *m_ctx; } void check_error() const { m_ctx->check_error(); } - friend void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); } + friend void check_context(object const & a, object const & b); }; + inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); } class symbol : public object { Z3_symbol m_sym; @@ -282,7 +285,7 @@ namespace z3 { Z3_symbol_kind kind() const { return Z3_get_symbol_kind(ctx(), m_sym); } std::string str() const { assert(kind() == Z3_STRING_SYMBOL); return Z3_get_symbol_string(ctx(), m_sym); } int to_int() const { assert(kind() == Z3_INT_SYMBOL); return Z3_get_symbol_int(ctx(), m_sym); } - friend std::ostream & operator<<(std::ostream & out, symbol const & s) { + friend std::ostream & operator<<(std::ostream & out, symbol const & s) { if (s.kind() == Z3_INT_SYMBOL) out << "k!" << s.to_int(); else @@ -291,6 +294,7 @@ namespace z3 { } }; + class params : public object { Z3_params m_params; public: @@ -309,7 +313,9 @@ namespace z3 { void set(char const * k, unsigned n) { Z3_params_set_uint(ctx(), m_params, ctx().str_symbol(k), n); } void set(char const * k, double n) { Z3_params_set_double(ctx(), m_params, ctx().str_symbol(k), n); } void set(char const * k, symbol const & s) { Z3_params_set_symbol(ctx(), m_params, ctx().str_symbol(k), s); } - friend std::ostream & operator<<(std::ostream & out, params const & p) { out << Z3_params_to_string(p.ctx(), p); return out; } + friend std::ostream & operator<<(std::ostream & out, params const & p) { + out << Z3_params_to_string(p.ctx(), p); return out; + } }; class ast : public object { @@ -325,14 +331,19 @@ namespace z3 { ast & operator=(ast const & s) { Z3_inc_ref(s.ctx(), s.m_ast); if (m_ast) Z3_dec_ref(ctx(), m_ast); m_ctx = s.m_ctx; m_ast = s.m_ast; return *this; } Z3_ast_kind kind() const { Z3_ast_kind r = Z3_get_ast_kind(ctx(), m_ast); check_error(); return r; } unsigned hash() const { unsigned r = Z3_get_ast_hash(ctx(), m_ast); check_error(); return r; } - friend std::ostream & operator<<(std::ostream & out, ast const & n) { out << Z3_ast_to_string(n.ctx(), n.m_ast); return out; } + friend std::ostream & operator<<(std::ostream & out, ast const & n) { + out << Z3_ast_to_string(n.ctx(), n.m_ast); return out; + } /** \brief Return true if the ASTs are structurally identical. */ - friend bool eq(ast const & a, ast const & b) { return Z3_is_eq_ast(a.ctx(), a, b) != 0; } + friend bool eq(ast const & a, ast const & b); }; + inline bool eq(ast const & a, ast const & b) { return Z3_is_eq_ast(a.ctx(), a, b) != 0; } + + /** \brief A Z3 sort (aka type). Every expression (i.e., formula or term) in Z3 has a sort. */ @@ -570,6 +581,7 @@ namespace z3 { return expr(a.ctx(), r); } + /** \brief Return an expression representing a and b. @@ -585,6 +597,7 @@ namespace z3 { return expr(a.ctx(), r); } + /** \brief Return an expression representing a and b. The C++ Boolean value \c b is automatically converted into a Z3 Boolean constant. @@ -636,21 +649,10 @@ namespace z3 { a.check_error(); return expr(a.ctx(), r); } - friend expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); } - friend expr implies(bool a, expr const & b) { return implies(b.ctx().bool_val(a), b); } + friend expr implies(expr const & a, bool b); + friend expr implies(bool a, expr const & b); - /** - \brief Create the if-then-else expression ite(c, t, e) - - \pre c.is_bool() - */ - friend expr ite(expr const & c, expr const & t, expr const & e) { - check_context(c, t); check_context(c, e); - assert(c.is_bool()); - Z3_ast r = Z3_mk_ite(c.ctx(), c, t, e); - c.check_error(); - return expr(c.ctx(), r); - } + friend expr ite(expr const & c, expr const & t, expr const & e); friend expr distinct(expr_vector const& args); @@ -716,15 +718,9 @@ namespace z3 { /** \brief Power operator */ - friend expr pw(expr const & a, expr const & b) { - assert(a.is_arith() && b.is_arith()); - check_context(a, b); - Z3_ast r = Z3_mk_power(a.ctx(), a, b); - a.check_error(); - return expr(a.ctx(), r); - } - friend expr pw(expr const & a, int b) { return pw(a, a.ctx().num_val(b, a.get_sort())); } - friend expr pw(int a, expr const & b) { return pw(b.ctx().num_val(a, b.get_sort()), b); } + friend expr pw(expr const & a, expr const & b); + friend expr pw(expr const & a, int b); + friend expr pw(int a, expr const & b); friend expr operator/(expr const & a, expr const & b) { check_context(a, b); @@ -891,6 +887,38 @@ namespace z3 { expr substitute(expr_vector const& dst); }; + + inline expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); } + inline expr implies(bool a, expr const & b) { return implies(b.ctx().bool_val(a), b); } + + inline expr pw(expr const & a, expr const & b) { + assert(a.is_arith() && b.is_arith()); + check_context(a, b); + Z3_ast r = Z3_mk_power(a.ctx(), a, b); + a.check_error(); + return expr(a.ctx(), r); + } + inline expr pw(expr const & a, int b) { return pw(a, a.ctx().num_val(b, a.get_sort())); } + inline expr pw(int a, expr const & b) { return pw(b.ctx().num_val(a, b.get_sort()), b); } + + + + + + /** + \brief Create the if-then-else expression ite(c, t, e) + + \pre c.is_bool() + */ + + inline expr ite(expr const & c, expr const & t, expr const & e) { + check_context(c, t); check_context(c, e); + assert(c.is_bool()); + Z3_ast r = Z3_mk_ite(c.ctx(), c, t, e); + c.check_error(); + return expr(c.ctx(), r); + } + /** \brief Wraps a Z3_ast as an expr object. It also checks for errors. @@ -1404,22 +1432,28 @@ namespace z3 { t1.check_error(); return tactic(t1.ctx(), r); } - friend tactic repeat(tactic const & t, unsigned max=UINT_MAX) { - Z3_tactic r = Z3_tactic_repeat(t.ctx(), t, max); - t.check_error(); - return tactic(t.ctx(), r); - } - friend tactic with(tactic const & t, params const & p) { - Z3_tactic r = Z3_tactic_using_params(t.ctx(), t, p); - t.check_error(); - return tactic(t.ctx(), r); - } - friend tactic try_for(tactic const & t, unsigned ms) { - Z3_tactic r = Z3_tactic_try_for(t.ctx(), t, ms); - t.check_error(); - return tactic(t.ctx(), r); - } + friend tactic repeat(tactic const & t, unsigned max=UINT_MAX); + friend tactic with(tactic const & t, params const & p); + friend tactic try_for(tactic const & t, unsigned ms); }; + + inline tactic repeat(tactic const & t, unsigned max) { + Z3_tactic r = Z3_tactic_repeat(t.ctx(), t, max); + t.check_error(); + return tactic(t.ctx(), r); + } + + inline tactic with(tactic const & t, params const & p) { + Z3_tactic r = Z3_tactic_using_params(t.ctx(), t, p); + t.check_error(); + return tactic(t.ctx(), r); + } + inline tactic try_for(tactic const & t, unsigned ms) { + Z3_tactic r = Z3_tactic_try_for(t.ctx(), t, ms); + t.check_error(); + return tactic(t.ctx(), r); + } + class probe : public object { Z3_probe m_probe; From 6d8daacdecc84bafbb7c493aeeccfe5660d19d43 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 6 Oct 2014 08:35:05 -0700 Subject: [PATCH 038/117] fix check for satisfiability before calling final_check Signed-off-by: Nikolaj Bjorner --- src/qe/qe.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qe/qe.cpp b/src/qe/qe.cpp index e573508bb..192d97c3b 100644 --- a/src/qe/qe.cpp +++ b/src/qe/qe.cpp @@ -1451,10 +1451,15 @@ namespace qe { if (assumption) m_solver.assert_expr(assumption); bool is_sat = false; lbool res = l_true; - while (res == l_true) { + while (true) { res = m_solver.check(); - if (res == l_true) is_sat = true; - final_check(); + if (res == l_true) { + is_sat = true; + final_check(); + } + else { + break; + } } if (res == l_undef) { free_vars.append(num_vars, vars); From 929880e4fd1f5f40955ba8caed7ed84eb5bd53a2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 6 Oct 2014 18:06:36 +0100 Subject: [PATCH 039/117] Fix for bogus runtime reports on Linux. Thanks to Vladimir Klebanov for reporting this one. --- src/util/stopwatch.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/util/stopwatch.h b/src/util/stopwatch.h index 661d3762b..b2a397b6e 100644 --- a/src/util/stopwatch.h +++ b/src/util/stopwatch.h @@ -105,7 +105,7 @@ public: mach_timespec_t _stop; clock_get_time(m_host_clock, &_stop); m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull; - m_time += (_stop.tv_nsec - m_start.tv_nsec); + m_time += (_stop.tv_nsec - m_start.tv_nsec); m_running = false; } } @@ -146,7 +146,7 @@ public: void start() { if (!m_running) { - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &m_start); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &m_start); m_running = true; } } @@ -154,9 +154,10 @@ public: void stop() { if (m_running) { struct timespec _stop; - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &_stop); + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &_stop); m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull; - m_time += (_stop.tv_nsec - m_start.tv_nsec); + if (m_time != 0 || _stop.tv_nsec >= m_start.tv_nsec) + m_time += (_stop.tv_nsec - m_start.tv_nsec); m_running = false; } } From 3222ecd992ab24e0dc33ef48d5cc105420e9b79a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 6 Oct 2014 18:09:40 +0100 Subject: [PATCH 040/117] tabs Signed-off-by: Christoph M. Wintersteiger --- src/util/stopwatch.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/util/stopwatch.h b/src/util/stopwatch.h index 661d3762b..b9cf312b2 100644 --- a/src/util/stopwatch.h +++ b/src/util/stopwatch.h @@ -90,7 +90,7 @@ public: ~stopwatch() {} void reset() { - m_time = 0ull; + m_time = 0ull; } void start() { @@ -101,7 +101,7 @@ public: } void stop() { - if (m_running) { + if (m_running) { mach_timespec_t _stop; clock_get_time(m_host_clock, &_stop); m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull; @@ -120,7 +120,7 @@ public: } double get_current_seconds() const { - return get_seconds(); + return get_seconds(); } }; @@ -141,7 +141,7 @@ public: ~stopwatch() {} void reset() { - m_time = 0ull; + m_time = 0ull; } void start() { @@ -152,7 +152,7 @@ public: } void stop() { - if (m_running) { + if (m_running) { struct timespec _stop; clock_gettime(CLOCK_THREAD_CPUTIME_ID, &_stop); m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull; @@ -171,7 +171,7 @@ public: } double get_current_seconds() const { - return get_seconds(); + return get_seconds(); } }; From 8438ac6e219b6ff5d88514a90032644d6b1e4068 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 6 Oct 2014 15:43:24 -0700 Subject: [PATCH 041/117] fix internalization bug when bit2bool is applied to numeral Signed-off-by: Nikolaj Bjorner --- src/smt/theory_bv.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index 8b3021573..6bcae6f60 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -53,6 +53,7 @@ namespace smt { unsigned bv_size = get_bv_size(n); context & ctx = get_context(); literal_vector & bits = m_bits[v]; + bits.reset(); for (unsigned i = 0; i < bv_size; i++) { app * bit = mk_bit2bool(owner, i); ctx.internalize(bit, true); @@ -75,12 +76,14 @@ namespace smt { void theory_bv::mk_bit2bool(app * n) { context & ctx = get_context(); SASSERT(!ctx.b_internalized(n)); - if (!ctx.e_internalized(n->get_arg(0))) { + + expr* first_arg = n->get_arg(0); + + if (!ctx.e_internalized(first_arg)) { // This may happen if bit2bool(x) is in a conflict // clause that is being reinitialized, and x was not reinitialized // yet. - // So, we internalize x (i.e., n->get_arg(0)) - expr * first_arg = n->get_arg(0); + // So, we internalize x (i.e., arg) ctx.internalize(first_arg, false); SASSERT(ctx.e_internalized(first_arg)); // In most cases, when x is internalized, its bits are created. @@ -91,10 +94,27 @@ namespace smt { // This will also force the creation of all bits for x. enode * first_arg_enode = ctx.get_enode(first_arg); get_var(first_arg_enode); - SASSERT(ctx.b_internalized(n)); + // numerals are not blasted into bit2bool, so we do this directly. + if (!ctx.b_internalized(n)) { + rational val; + unsigned sz; + VERIFY(m_util.is_numeral(first_arg, val, sz)); + theory_var v = first_arg_enode->get_th_var(get_id()); + app* owner = first_arg_enode->get_owner(); + for (unsigned i = 0; i < sz; ++i) { + ctx.internalize(mk_bit2bool(owner, i), true); + } + m_bits[v].reset(); + rational bit; + for (unsigned i = 0; i < sz; ++i) { + div(val, rational::power_of_two(i), bit); + mod(bit, rational(2), bit); + m_bits[v].push_back(bit.is_zero()?false_literal:true_literal); + } + } } else { - enode * arg = ctx.get_enode(n->get_arg(0)); + enode * arg = ctx.get_enode(first_arg); // The argument was already internalized, but it may not have a theory variable associated with it. // For example, for ite-terms the method apply_sort_cnstr is not invoked. // See comment in the then-branch. @@ -1041,6 +1061,7 @@ namespace smt { void theory_bv::new_diseq_eh(theory_var v1, theory_var v2) { if (is_bv(v1)) { + SASSERT(m_bits[v1].size() == m_bits[v2].size()); expand_diseq(v1, v2); } } @@ -1381,6 +1402,7 @@ namespace smt { if (v1 != null_theory_var) { // conflict was detected ... v1 and v2 have complementary bits SASSERT(m_bits[v1][it->m_idx] == ~(m_bits[v2][it->m_idx])); + SASSERT(m_bits[v1].size() == m_bits[v2].size()); mk_new_diseq_axiom(v1, v2, it->m_idx); RESET_MERGET_AUX(); return false; From 7fc95aff3cb70e95376bb3ce38b37c028df69c29 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 7 Oct 2014 14:24:28 +0100 Subject: [PATCH 042/117] Minor cleanliness fix. Signed-off-by: Christoph M. Wintersteiger --- src/ast/rewriter/th_rewriter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 5d19c53e3..0e2c8e781 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -73,6 +73,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { m_a_rw.updt_params(p); m_bv_rw.updt_params(p); m_ar_rw.updt_params(p); + m_f_rw.updt_params(p); updt_local_params(p); } From 4ea3ed7e273a0c9170541b43902d2d8723f881f6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 7 Oct 2014 11:00:45 -0700 Subject: [PATCH 043/117] ensure parameters are updated and ensure that global use of auto-config is not obscured by smt.auto-config scoping Signed-off-by: Nikolaj Bjorner --- src/qe/qe.cpp | 25 ++++++++++++++----------- src/qe/qe.h | 7 +++++-- src/qe/qe_sat_tactic.cpp | 9 ++++++--- src/qe/qe_tactic.cpp | 1 + src/smt/params/smt_params.cpp | 3 ++- 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/qe/qe.cpp b/src/qe/qe.cpp index 192d97c3b..d229d8735 100644 --- a/src/qe/qe.cpp +++ b/src/qe/qe.cpp @@ -2238,8 +2238,7 @@ namespace qe { m_params(p), m_trail(m), m_qe(0), - m_assumption(m.mk_true()), - m_use_new_qe(true) + m_assumption(m.mk_true()) { } @@ -2261,12 +2260,6 @@ namespace qe { } void expr_quant_elim::updt_params(params_ref const& p) { - bool r = p.get_bool("use_neq_qe", m_use_new_qe); - if (r != m_use_new_qe) { - dealloc(m_qe); - m_qe = 0; - m_use_new_qe = r; - } init_qe(); m_qe->updt_params(p); } @@ -2274,7 +2267,6 @@ namespace qe { void expr_quant_elim::collect_param_descrs(param_descrs& r) { r.insert("eliminate_variables_as_block", CPK_BOOL, "(default: true) eliminate variables as a block (true) or one at a time (false)"); - // r.insert("use_new_qe", CPK_BOOL, "(default: true) invoke quantifier engine based on abstracted solver"); } void expr_quant_elim::init_qe() { @@ -2504,7 +2496,7 @@ namespace qe { class simplify_solver_context : public i_solver_context { ast_manager& m; - smt_params m_fparams; + smt_params m_fparams; app_ref_vector* m_vars; expr_ref* m_fml; ptr_vector m_contains; @@ -2520,6 +2512,10 @@ namespace qe { add_plugin(mk_arith_plugin(*this, false, m_fparams)); } + void updt_params(params_ref const& p) { + m_fparams.updt_params(p); + } + virtual ~simplify_solver_context() { reset(); } void solve(expr_ref& fml, app_ref_vector& vars) { @@ -2610,6 +2606,10 @@ namespace qe { public: impl(ast_manager& m) : m(m), m_ctx(m) {} + void updt_params(params_ref const& p) { + m_ctx.updt_params(p); + } + bool reduce_quantifier( quantifier * old_q, expr * new_body, @@ -2673,6 +2673,10 @@ namespace qe { return imp->reduce_quantifier(old_q, new_body, new_patterns, new_no_patterns, result, result_pr); } + void simplify_rewriter_cfg::updt_params(params_ref const& p) { + imp->updt_params(p); + } + bool simplify_rewriter_cfg::pre_visit(expr* e) { if (!is_quantifier(e)) return true; quantifier * q = to_quantifier(e); @@ -2680,7 +2684,6 @@ namespace qe { } void simplify_exists(app_ref_vector& vars, expr_ref& fml) { - smt_params params; ast_manager& m = fml.get_manager(); simplify_solver_context ctx(m); ctx.solve(fml, vars); diff --git a/src/qe/qe.h b/src/qe/qe.h index 1697a5cbd..0fd2ff60c 100644 --- a/src/qe/qe.h +++ b/src/qe/qe.h @@ -275,13 +275,12 @@ namespace qe { class expr_quant_elim { ast_manager& m; - smt_params const& m_fparams; + smt_params const& m_fparams; params_ref m_params; expr_ref_vector m_trail; obj_map m_visited; quant_elim* m_qe; expr* m_assumption; - bool m_use_new_qe; public: expr_quant_elim(ast_manager& m, smt_params const& fp, params_ref const& p = params_ref()); ~expr_quant_elim(); @@ -372,6 +371,8 @@ namespace qe { bool pre_visit(expr* e); + void updt_params(params_ref const& p); + }; class simplify_rewriter_star : public rewriter_tpl { @@ -380,6 +381,8 @@ namespace qe { simplify_rewriter_star(ast_manager& m): rewriter_tpl(m, false, m_cfg), m_cfg(m) {} + + void updt_params(params_ref const& p) { m_cfg.updt_params(p); } }; }; diff --git a/src/qe/qe_sat_tactic.cpp b/src/qe/qe_sat_tactic.cpp index b4a1a6a8b..2be32c02d 100644 --- a/src/qe/qe_sat_tactic.cpp +++ b/src/qe/qe_sat_tactic.cpp @@ -74,6 +74,7 @@ namespace qe { is_relevant_default m_is_relevant; mk_atom_default m_mk_atom; th_rewriter m_rewriter; + simplify_rewriter_star m_qe_rw; expr_strong_context_simplifier m_ctx_rewriter; class solver_context : public i_solver_context { @@ -218,6 +219,7 @@ namespace qe { m_Ms(m), m_assignments(m), m_rewriter(m), + m_qe_rw(m), m_ctx_rewriter(m_fparams, m) { m_fparams.m_model = true; } @@ -256,10 +258,9 @@ namespace qe { ptr_vector fmls; goal->get_formulas(fmls); m_fml = m.mk_and(fmls.size(), fmls.c_ptr()); - TRACE("qe", tout << "input: " << mk_pp(m_fml,m) << "\n";); - simplify_rewriter_star rw(m); + TRACE("qe", tout << "input: " << mk_pp(m_fml,m) << "\n";); expr_ref tmp(m); - rw(m_fml, tmp); + m_qe_rw(m_fml, tmp); m_fml = tmp; TRACE("qe", tout << "reduced: " << mk_pp(m_fml,m) << "\n";); skolemize_existential_prefix(); @@ -305,6 +306,8 @@ namespace qe { m_projection_mode_param = p.get_bool("projection_mode", m_projection_mode_param); m_strong_context_simplify_param = p.get_bool("strong_context_simplify", m_strong_context_simplify_param); m_ctx_simplify_local_param = p.get_bool("strong_context_simplify_local", m_ctx_simplify_local_param); + m_fparams.updt_params(p); + m_qe_rw.updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { diff --git a/src/qe/qe_tactic.cpp b/src/qe/qe_tactic.cpp index 5b522e041..8819d704b 100644 --- a/src/qe/qe_tactic.cpp +++ b/src/qe/qe_tactic.cpp @@ -36,6 +36,7 @@ class qe_tactic : public tactic { } void updt_params(params_ref const & p) { + m_fparams.updt_params(p); m_fparams.m_nlquant_elim = p.get_bool("qe_nonlinear", false); m_qe.updt_params(p); } diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index f1c407dc7..18619c8ec 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -19,10 +19,11 @@ Revision History: #include"smt_params.h" #include"smt_params_helper.hpp" #include"model_params.hpp" +#include"gparams.h" void smt_params::updt_local_params(params_ref const & _p) { smt_params_helper p(_p); - m_auto_config = p.auto_config(); + m_auto_config = p.auto_config() && gparams::get_value("auto_config") == "true"; // auto-config is not scoped by smt in gparams. m_random_seed = p.random_seed(); m_relevancy_lvl = p.relevancy(); m_ematching = p.ematching(); From d6964226c7f5d85f443becbf7e9c2d7144d1059f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 7 Oct 2014 15:38:44 -0700 Subject: [PATCH 044/117] indentation Signed-off-by: Nikolaj Bjorner --- src/smt/smt_context.h | 2 +- src/smt/smt_quantifier.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 7940b17be..a9fc5c091 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -71,7 +71,7 @@ namespace smt { protected: ast_manager & m_manager; - smt_params & m_fparams; + smt_params & m_fparams; params_ref m_params; setup m_setup; volatile bool m_cancel_flag; diff --git a/src/smt/smt_quantifier.cpp b/src/smt/smt_quantifier.cpp index e9b0e069a..b76fb6c74 100644 --- a/src/smt/smt_quantifier.cpp +++ b/src/smt/smt_quantifier.cpp @@ -453,9 +453,9 @@ namespace smt { instantiated. */ virtual void add(quantifier * q) { - if (m_fparams->m_mbqi && mbqi_enabled(q)) { - m_model_finder->register_quantifier(q); - } + if (m_fparams->m_mbqi && mbqi_enabled(q)) { + m_model_finder->register_quantifier(q); + } } virtual void del(quantifier * q) { From 335f9a9be1b1bbd19b229459d77920cb0f6a6729 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 8 Oct 2014 10:55:24 -0700 Subject: [PATCH 045/117] add parameter validation to tactic parameters Signed-off-by: Nikolaj Bjorner --- src/tactic/tactical.cpp | 5 ++- src/util/params.cpp | 67 ++++++++++++++++++++++++++++++++++++----- src/util/params.h | 1 + 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 1e0b07e9d..87974ea60 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -1229,6 +1229,9 @@ class using_params_tactical : public unary_tactical { params_ref m_params; public: using_params_tactical(tactic * t, params_ref const & p):unary_tactical(t), m_params(p) { + param_descrs r; + collect_param_descrs(r); + p.validate(r); t->updt_params(p); } @@ -1276,7 +1279,7 @@ public: model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { - if (m_p->operator()(*(in.get())).is_true()) + if (m_p->operator()(*(in.get())).is_true()) m_t1->operator()(in, result, mc, pc, core); else m_t2->operator()(in, result, mc, pc, core); diff --git a/src/util/params.cpp b/src/util/params.cpp index 4aff0de92..130b18cc9 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -302,10 +302,19 @@ public: svector::const_iterator end = m_entries.end(); for (; it != end; ++it) { param_kind expected = p.get_kind(it->first); - if (expected == CPK_INVALID) - throw default_exception("unknown parameter '%s'", it->first.str().c_str()); - if (it->second.m_kind != expected) - throw default_exception("parameter kind mismatch '%s'", it->first.str().c_str()); + if (expected == CPK_INVALID) { + std::stringstream strm; + strm << "unknown parameter '" << it->first.str() << "'\n"; + strm << "Legal parameters are:\n"; + p.display(strm, 2, false, false); + throw default_exception(strm.str()); + } + if (it->second.m_kind != expected) { + std::stringstream strm; + strm << "Parameter " << it->first.str() << " was given argument of type "; + strm << it->second.m_kind << ", expected " << expected; + throw default_exception(strm.str()); + } } } @@ -347,11 +356,11 @@ public: out << "(params"; svector::const_iterator it = m_entries.begin(); svector::const_iterator end = m_entries.end(); - for (; it != end; ++it) { - out << " " << it->first; + for (; it != end; ++it) { + out << " " << it->first; switch (it->second.m_kind) { case CPK_BOOL: - out << " " << it->second.m_bool_value; + out << " " << (it->second.m_bool_value?"true":"false"); break; case CPK_UINT: out << " " <second.m_uint_value; @@ -376,6 +385,41 @@ public: out << ")"; } + void display_smt2(std::ostream & out, char const* module, param_descrs& descrs) const { + svector::const_iterator it = m_entries.begin(); + svector::const_iterator end = m_entries.end(); + for (; it != end; ++it) { + if (!descrs.contains(it->first)) continue; + out << "(set-option :"; + out << module << "."; + out << it->first; + switch (it->second.m_kind) { + case CPK_BOOL: + out << " " << (it->second.m_bool_value?"true":"false"); + break; + case CPK_UINT: + out << " " <second.m_uint_value; + break; + case CPK_DOUBLE: + out << " " << it->second.m_double_value; + break; + case CPK_NUMERAL: + out << " " << *(it->second.m_rat_value); + break; + case CPK_SYMBOL: + out << " " << symbol::mk_symbol_from_c_ptr(it->second.m_sym_value); + break; + case CPK_STRING: + out << " " << it->second.m_str_value; + break; + default: + UNREACHABLE(); + break; + } + out << ")\n"; + } + } + void display(std::ostream & out, symbol const & k) const { svector::const_iterator it = m_entries.begin(); svector::const_iterator end = m_entries.end(); @@ -423,10 +467,17 @@ params_ref::params_ref(params_ref const & p): void params_ref::display(std::ostream & out) const { if (m_params) m_params->display(out); - else + else out << "(params)"; } +void params_ref::display_smt2(std::ostream& out, char const* module, param_descrs& descrs) const { + if (m_params) + m_params->display_smt2(out, module, descrs); + +} + + void params_ref::display(std::ostream & out, char const * k) const { display(out, symbol(k)); } diff --git a/src/util/params.h b/src/util/params.h index 15be825b0..06be486bb 100644 --- a/src/util/params.h +++ b/src/util/params.h @@ -90,6 +90,7 @@ public: void set_sym(char const * k, symbol const & v); void display(std::ostream & out) const; + void display_smt2(std::ostream& out, char const* module, param_descrs& module_desc) const; void validate(param_descrs const & p) const; From b03a9d3f0a58ac962d04792423aa1d2db56fec84 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 8 Oct 2014 21:01:27 +0100 Subject: [PATCH 046/117] Interpolation API: infrastructure fixes and .NET API Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_project.py | 2 +- scripts/update_api.py | 38 +- src/api/api_ast.cpp | 2 +- src/api/api_interp.cpp | 1200 ++++++++++++------------ src/api/dotnet/Constructor.cs | 6 +- src/api/dotnet/Context.cs | 2 +- src/api/dotnet/EnumSort.cs | 2 +- src/api/dotnet/Expr.cs | 10 +- src/api/dotnet/InterpolationContext.cs | 206 ++++ src/api/dotnet/Microsoft.Z3.csproj | 9 +- src/api/dotnet/TupleSort.cs | 3 +- src/api/python/z3.py | 14 +- src/api/z3.h | 1 + src/api/z3_api.h | 318 ------- src/api/z3_interp.h | 359 +++++++ 15 files changed, 1223 insertions(+), 949 deletions(-) create mode 100644 src/api/dotnet/InterpolationContext.cs create mode 100644 src/api/z3_interp.h diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 6f8fe1f7f..170124bd8 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -75,7 +75,7 @@ def init_project_def(): # dll_name='foci2', # export_files=['foci2stub.cpp']) # add_lib('interp', ['solver','foci2']) - API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h'] + API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_interp.h'] add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure', 'interp'], includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files) add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3') diff --git a/scripts/update_api.py b/scripts/update_api.py index 97dacb44b..791c23ddd 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -123,6 +123,7 @@ SYMBOL = 9 PRINT_MODE = 10 ERROR_CODE = 11 DOUBLE = 12 +UINT_PTR = 13 FIRST_OBJ_ID = 100 @@ -131,28 +132,28 @@ def is_obj(ty): Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double', STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol', - PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code', + PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code', UINT_PTR : 'unsigned*' } Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong', UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double', STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol', - PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint', + PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint', UINT_PTR : 'ctypes.POINTER(ctypes.c_uint)' } # Mapping to .NET types Type2Dotnet = { VOID : 'void', VOID_PTR : 'IntPtr', INT : 'int', UINT : 'uint', INT64 : 'Int64', UINT64 : 'UInt64', DOUBLE : 'double', STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr', - PRINT_MODE : 'uint', ERROR_CODE : 'uint' } + PRINT_MODE : 'uint', ERROR_CODE : 'uint', UINT_PTR : 'uint[]'} # Mapping to Java types Type2Java = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', STRING : 'String', STRING_PTR : 'StringPtr', - BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int' } + BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int', UINT_PTR : 'int[]'} Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', INT64 : 'jlong', UINT64 : 'jlong', DOUBLE : 'jdouble', STRING : 'jstring', STRING_PTR : 'jobject', - BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint' } + BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint', UINT_PTR : 'jlong'} next_type_id = FIRST_OBJ_ID @@ -259,7 +260,7 @@ def param2dotnet(p): if k == INOUT_ARRAY: return "[In, Out] %s[]" % type2dotnet(param_type(p)) if k == OUT_ARRAY: - return "[Out] %s[]" % type2dotnet(param_type(p)) + return "[Out] out %s[]" % type2dotnet(param_type(p)) else: return type2dotnet(param_type(p)) @@ -466,6 +467,8 @@ def mk_dotnet_wrappers(): dotnet.write('out '); else: dotnet.write('ref ') + elif param_kind(param) == OUT_ARRAY: + dotnet.write('out '); dotnet.write('a%d' % i) i = i + 1 dotnet.write(');\n'); @@ -953,20 +956,33 @@ def def_API(name, result, params): log_c.write(" Au(a%s);\n" % sz) exe_c.write("in.get_uint_array(%s)" % i) else: - error ("unsupported parameter for %s, %s" % (name, p)) + error ("unsupported parameter for %s, %s" % (ty, name, p)) elif kind == OUT_ARRAY: sz = param_array_capacity_pos(p) - log_c.write(" for (unsigned i = 0; i < a%s; i++) { " % sz) + sz_p = params[sz] + sz_p_k = param_kind(sz_p) + tstr = type2str(ty) + if sz_p_k == OUT or sz_p_k == INOUT: + sz_e = ("(*a%s)" % sz) + tstr = tstr + '*' + else: + sz_e = ("a%s" % sz) + log_c.write(" for (unsigned i = 0; i < %s; i++) { " % sz_e) if is_obj(ty): log_c.write("P(0);") log_c.write(" }\n") - log_c.write(" Ap(a%s);\n" % sz) - exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (type2str(ty), i)) + log_c.write(" Ap(%s);\n" % sz_e) + exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (tstr, i)) elif ty == UINT: log_c.write("U(0);") log_c.write(" }\n") - log_c.write(" Au(a%s);\n" % sz) + log_c.write(" Au(%s);\n" % sz_e) exe_c.write("in.get_uint_array(%s)" % i) + elif ty == UINT_PTR: + log_c.write("P(0);") + log_c.write(" }\n") + log_c.write(" Ap(%s);\n" % sz_e) + exe_c.write("reinterpret_cast<%s>(in.get_obj_array(%s))" % (tstr, i)) else: error ("unsupported parameter for %s, %s" % (name, p)) else: diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 715732be6..c2864ca2d 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -208,7 +208,7 @@ extern "C" { MK_BINARY(Z3_mk_xor, mk_c(c)->get_basic_fid(), OP_XOR, SKIP); MK_NARY(Z3_mk_and, mk_c(c)->get_basic_fid(), OP_AND, SKIP); MK_NARY(Z3_mk_or, mk_c(c)->get_basic_fid(), OP_OR, SKIP); - MK_UNARY(Z3_mk_interp, mk_c(c)->get_basic_fid(), OP_INTERP, SKIP); + MK_UNARY(Z3_mk_interpolant, mk_c(c)->get_basic_fid(), OP_INTERP, SKIP); Z3_ast mk_ite_core(Z3_context c, Z3_ast t1, Z3_ast t2, Z3_ast t3) { expr * result = mk_c(c)->m().mk_ite(to_expr(t1), to_expr(t2), to_expr(t3)); diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index e06ad5192..8740e99a5 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -3,14 +3,14 @@ Copyright (c) 2011 Microsoft Corporation Module Name: - api_interp.cpp +api_interp.cpp Abstract: - API for interpolation +API for interpolation Author: - Ken McMillan +Ken McMillan Revision History: @@ -45,669 +45,669 @@ using namespace stl_ext; // WARNING: don't make a hash_map with this if the range type // has a destructor: you'll get an address dependency!!! namespace stl_ext { - template <> - class hash { - public: - size_t operator()(const Z3_ast p) const { - return (size_t) p; - } - }; + template <> + class hash < Z3_ast > { + public: + size_t operator()(const Z3_ast p) const { + return (size_t)p; + } + }; } typedef interpolation_options_struct *Z3_interpolation_options; extern "C" { - Z3_context Z3_mk_interpolation_context(Z3_config cfg){ - if(!cfg) cfg = Z3_mk_config(); - Z3_set_param_value(cfg, "PROOF", "true"); - Z3_set_param_value(cfg, "MODEL", "true"); - // Z3_set_param_value(cfg, "PRE_SIMPLIFIER","false"); - // Z3_set_param_value(cfg, "SIMPLIFY_CLAUSES","false"); - - Z3_context ctx = Z3_mk_context(cfg); - Z3_del_config(cfg); - return ctx; - } - - void Z3_interpolate_proof(Z3_context ctx, - Z3_ast proof, - int num, - Z3_ast *cnsts, - unsigned *parents, - Z3_params options, - Z3_ast *interps, - int num_theory, - Z3_ast *theory - ){ + Z3_context Z3_mk_interpolation_context(Z3_config cfg){ + if (!cfg) cfg = Z3_mk_config(); + Z3_set_param_value(cfg, "PROOF", "true"); + Z3_set_param_value(cfg, "MODEL", "true"); + // Z3_set_param_value(cfg, "PRE_SIMPLIFIER","false"); + // Z3_set_param_value(cfg, "SIMPLIFY_CLAUSES","false"); - if(num > 1){ // if we have interpolants to compute - - ptr_vector pre_cnsts_vec(num); // get constraints in a vector - for(int i = 0; i < num; i++){ - ast *a = to_ast(cnsts[i]); - pre_cnsts_vec[i] = a; - } - - ::vector pre_parents_vec; // get parents in a vector - if(parents){ - pre_parents_vec.resize(num); - for(int i = 0; i < num; i++) - pre_parents_vec[i] = parents[i]; + Z3_context ctx = Z3_mk_context(cfg); + Z3_del_config(cfg); + return ctx; + } + + void Z3_interpolate_proof(Z3_context ctx, + Z3_ast proof, + int num, + Z3_ast *cnsts, + unsigned *parents, + Z3_params options, + Z3_ast *interps, + int num_theory, + Z3_ast *theory) + { + + if (num > 1){ // if we have interpolants to compute + + ptr_vector pre_cnsts_vec(num); // get constraints in a vector + for (int i = 0; i < num; i++){ + ast *a = to_ast(cnsts[i]); + pre_cnsts_vec[i] = a; + } + + ::vector pre_parents_vec; // get parents in a vector + if (parents){ + pre_parents_vec.resize(num); + for (int i = 0; i < num; i++) + pre_parents_vec[i] = parents[i]; + } + + ptr_vector theory_vec; // get background theory in a vector + if (theory){ + theory_vec.resize(num_theory); + for (int i = 0; i < num_theory; i++) + theory_vec[i] = to_ast(theory[i]); + } + + ptr_vector interpolants(num - 1); // make space for result + + ast_manager &_m = mk_c(ctx)->m(); + iz3interpolate(_m, + to_ast(proof), + pre_cnsts_vec, + pre_parents_vec, + interpolants, + theory_vec, + 0); // ignore params for now FIXME + + // copy result back + for (unsigned i = 0; i < interpolants.size(); i++){ + mk_c(ctx)->save_ast_trail(interpolants[i]); + interps[i] = of_ast(interpolants[i]); + _m.dec_ref(interpolants[i]); + } } - - ptr_vector theory_vec; // get background theory in a vector - if(theory){ - theory_vec.resize(num_theory); - for(int i = 0; i < num_theory; i++) - theory_vec[i] = to_ast(theory[i]); - } - - ptr_vector interpolants(num-1); // make space for result - - ast_manager &_m = mk_c(ctx)->m(); - iz3interpolate(_m, - to_ast(proof), - pre_cnsts_vec, - pre_parents_vec, - interpolants, - theory_vec, - 0); // ignore params for now FIXME + } - // copy result back - for(unsigned i = 0; i < interpolants.size(); i++){ - mk_c(ctx)->save_ast_trail(interpolants[i]); - interps[i] = of_ast(interpolants[i]); - _m.dec_ref(interpolants[i]); - } - } - } + Z3_lbool Z3_interpolate(Z3_context ctx, + unsigned num, + Z3_ast *cnsts, + unsigned *parents, + Z3_params options, + Z3_ast *interps, + Z3_model *model, + Z3_literals *labels, + unsigned incremental, + unsigned num_theory, + Z3_ast *theory + ){ - Z3_lbool Z3_interpolate(Z3_context ctx, - int num, - Z3_ast *cnsts, - unsigned *parents, - Z3_params options, - Z3_ast *interps, - Z3_model *model, - Z3_literals *labels, - int incremental, - int num_theory, - Z3_ast *theory - ){ - - profiling::timer_start("Solve"); + profiling::timer_start("Solve"); - if(!incremental){ + if (!incremental){ - profiling::timer_start("Z3 assert"); + profiling::timer_start("Z3 assert"); - Z3_push(ctx); // so we can rewind later - - for(int i = 0; i < num; i++) - Z3_assert_cnstr(ctx,cnsts[i]); // assert all the constraints + Z3_push(ctx); // so we can rewind later - if(theory){ - for(int i = 0; i < num_theory; i++) - Z3_assert_cnstr(ctx,theory[i]); - } + for (int i = 0; i < num; i++) + Z3_assert_cnstr(ctx, cnsts[i]); // assert all the constraints - profiling::timer_stop("Z3 assert"); + if (theory){ + for (int i = 0; i < num_theory; i++) + Z3_assert_cnstr(ctx, theory[i]); + } + + profiling::timer_stop("Z3 assert"); + } + + + // Get a proof of unsat + + Z3_ast proof; + Z3_lbool result; + + profiling::timer_start("Z3 solving"); + result = Z3_check_assumptions(ctx, 0, 0, model, &proof, 0, 0); + profiling::timer_stop("Z3 solving"); + + switch (result) { + case Z3_L_FALSE: + + Z3_interpolate_proof(ctx, + proof, + num, + cnsts, + parents, + options, + interps, + num_theory, + theory); + + if (!incremental) + for (int i = 0; i < num - 1; i++) + Z3_persist_ast(ctx, interps[i], 1); + break; + + case Z3_L_UNDEF: + if (labels) + *labels = Z3_get_relevant_labels(ctx); + break; + + case Z3_L_TRUE: + if (labels) + *labels = Z3_get_relevant_labels(ctx); + break; + } + + profiling::timer_start("Z3 pop"); + if (!incremental) + Z3_pop(ctx, 1); + profiling::timer_stop("Z3 pop"); + + profiling::timer_stop("Solve"); + + return result; + + } + + static std::ostringstream itp_err; + + int Z3_check_interpolant(Z3_context ctx, + unsigned num, + Z3_ast *cnsts, + unsigned *parents, + Z3_ast *itp, + Z3_string *error, + unsigned num_theory, + Z3_ast *theory){ + + ast_manager &_m = mk_c(ctx)->m(); + itp_err.clear(); + + // need a solver -- make one here, but how? + params_ref p = params_ref::get_empty(); //FIXME + scoped_ptr sf(mk_smt_solver_factory()); + scoped_ptr sp((*(sf))(_m, p, false, true, false, symbol("AUFLIA"))); + + ptr_vector cnsts_vec(num); // get constraints in a vector + for (int i = 0; i < num; i++){ + ast *a = to_ast(cnsts[i]); + cnsts_vec[i] = a; + } + + ptr_vector itp_vec(num); // get interpolants in a vector + for (int i = 0; i < num - 1; i++){ + ast *a = to_ast(itp[i]); + itp_vec[i] = a; + } + + ::vector parents_vec; // get parents in a vector + if (parents){ + parents_vec.resize(num); + for (int i = 0; i < num; i++) + parents_vec[i] = parents[i]; + } + + ptr_vector theory_vec; // get background theory in a vector + if (theory){ + theory_vec.resize(num_theory); + for (int i = 0; i < num_theory; i++) + theory_vec[i] = to_ast(theory[i]); + } + + bool res = iz3check(_m, + sp.get(), + itp_err, + cnsts_vec, + parents_vec, + itp_vec, + theory_vec); + + *error = res ? 0 : itp_err.str().c_str(); + return res; } - // Get a proof of unsat - - Z3_ast proof; - Z3_lbool result; - - profiling::timer_start("Z3 solving"); - result = Z3_check_assumptions(ctx, 0, 0, model, &proof, 0, 0); - profiling::timer_stop("Z3 solving"); - - switch (result) { - case Z3_L_FALSE: - - Z3_interpolate_proof(ctx, - proof, - num, - cnsts, - parents, - options, - interps, - num_theory, - theory); + static std::string Z3_profile_string; - if(!incremental) - for(int i = 0; i < num-1; i++) - Z3_persist_ast(ctx,interps[i],1); - break; - - case Z3_L_UNDEF: - if(labels) - *labels = Z3_get_relevant_labels(ctx); - break; - - case Z3_L_TRUE: - if(labels) - *labels = Z3_get_relevant_labels(ctx); - break; + Z3_string Z3_interpolation_profile(Z3_context ctx){ + std::ostringstream f; + profiling::print(f); + Z3_profile_string = f.str(); + return Z3_profile_string.c_str(); } - profiling::timer_start("Z3 pop"); - if(!incremental) - Z3_pop(ctx,1); - profiling::timer_stop("Z3 pop"); - profiling::timer_stop("Solve"); - - return result; - - } - - static std::ostringstream itp_err; - - int Z3_check_interpolant(Z3_context ctx, - int num, - Z3_ast *cnsts, - int *parents, - Z3_ast *itp, - const char **error, - int num_theory, - Z3_ast *theory){ - - ast_manager &_m = mk_c(ctx)->m(); - itp_err.clear(); - - // need a solver -- make one here, but how? - params_ref p = params_ref::get_empty(); //FIXME - scoped_ptr sf(mk_smt_solver_factory()); - scoped_ptr sp((*(sf))(_m, p, false, true, false, symbol("AUFLIA"))); - - ptr_vector cnsts_vec(num); // get constraints in a vector - for(int i = 0; i < num; i++){ - ast *a = to_ast(cnsts[i]); - cnsts_vec[i] = a; - } - - ptr_vector itp_vec(num); // get interpolants in a vector - for(int i = 0; i < num-1; i++){ - ast *a = to_ast(itp[i]); - itp_vec[i] = a; + Z3_interpolation_options + Z3_mk_interpolation_options(){ + return (Z3_interpolation_options) new interpolation_options_struct; } - ::vector parents_vec; // get parents in a vector - if(parents){ - parents_vec.resize(num); - for(int i = 0; i < num; i++) - parents_vec[i] = parents[i]; - } - - ptr_vector theory_vec; // get background theory in a vector - if(theory){ - theory_vec.resize(num_theory); - for(int i = 0; i < num_theory; i++) - theory_vec[i] = to_ast(theory[i]); - } - - bool res = iz3check(_m, - sp.get(), - itp_err, - cnsts_vec, - parents_vec, - itp_vec, - theory_vec); - - *error = res ? 0 : itp_err.str().c_str(); - return res; - } - - - static std::string Z3_profile_string; - - Z3_string Z3_interpolation_profile(Z3_context ctx){ - std::ostringstream f; - profiling::print(f); - Z3_profile_string = f.str(); - return Z3_profile_string.c_str(); - } - - - Z3_interpolation_options - Z3_mk_interpolation_options(){ - return (Z3_interpolation_options) new interpolation_options_struct; - } - - void - Z3_del_interpolation_options(Z3_interpolation_options opts){ - delete opts; - } - - void - Z3_set_interpolation_option(Z3_interpolation_options opts, - Z3_string name, - Z3_string value){ - opts->map[name] = value; - } - - Z3_ast_vector Z3_API Z3_get_interpolant(__in Z3_context c, __in Z3_ast pf, __in Z3_ast pat, __in Z3_params p){ - Z3_TRY; - LOG_Z3_get_interpolant(c, pf, pat, p); - RESET_ERROR_CODE(); - - Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m()); - mk_c(c)->save_object(v); - - ast *_pf = to_ast(pf); - ast *_pat = to_ast(pat); - - ptr_vector interp; - ptr_vector cnsts; // to throw away - - ast_manager &_m = mk_c(c)->m(); - - iz3interpolate(_m, - _pf, - cnsts, - _pat, - interp, - (interpolation_options_struct *) 0 // ignore params for now - ); - - // copy result back - for(unsigned i = 0; i < interp.size(); i++){ - v->m_ast_vector.push_back(interp[i]); - _m.dec_ref(interp[i]); - } - RETURN_Z3(of_ast_vector(v)); - Z3_CATCH_RETURN(0); - } - - Z3_lbool Z3_API Z3_compute_interpolant(__in Z3_context c, __in Z3_ast pat, __in Z3_params p, __out Z3_ast_vector *out_interp, __out Z3_model *model){ - Z3_TRY; - LOG_Z3_compute_interpolant(c, pat, p, out_interp, model); - RESET_ERROR_CODE(); - - - // params_ref &_p = to_params(p)->m_params; - params_ref _p; - _p.set_bool("proof", true); // this is currently useless - - scoped_proof_mode spm(mk_c(c)->m(),PGM_FINE); - scoped_ptr sf = mk_smt_solver_factory(); - scoped_ptr m_solver((*sf)(mk_c(c)->m(), _p, true, true, true, ::symbol::null)); - m_solver.get()->updt_params(_p); // why do we have to do this? - - ast *_pat = to_ast(pat); - - ptr_vector interp; - ptr_vector cnsts; // to throw away - - ast_manager &_m = mk_c(c)->m(); - - model_ref m; - lbool _status = iz3interpolate(_m, - *(m_solver.get()), - _pat, - cnsts, - interp, - m, - 0 // ignore params for now - ); - - Z3_lbool status = of_lbool(_status); - - Z3_ast_vector_ref *v = 0; - *model = 0; - - if(_status == l_false){ - // copy result back - v = alloc(Z3_ast_vector_ref, mk_c(c)->m()); - mk_c(c)->save_object(v); - for(unsigned i = 0; i < interp.size(); i++){ - v->m_ast_vector.push_back(interp[i]); - _m.dec_ref(interp[i]); - } - } - else { - model_ref _m; - m_solver.get()->get_model(_m); - Z3_model_ref *crap = alloc(Z3_model_ref); - crap->m_model = _m.get(); - mk_c(c)->save_object(crap); - *model = of_model(crap); + void + Z3_del_interpolation_options(Z3_interpolation_options opts){ + delete opts; } - *out_interp = of_ast_vector(v); - - return status; - Z3_CATCH_RETURN(Z3_L_UNDEF); - } + void + Z3_set_interpolation_option(Z3_interpolation_options opts, + Z3_string name, + Z3_string value){ + opts->map[name] = value; + } + + Z3_ast_vector Z3_API Z3_get_interpolant(__in Z3_context c, __in Z3_ast pf, __in Z3_ast pat, __in Z3_params p){ + Z3_TRY; + LOG_Z3_get_interpolant(c, pf, pat, p); + RESET_ERROR_CODE(); + + Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, mk_c(c)->m()); + mk_c(c)->save_object(v); + + ast *_pf = to_ast(pf); + ast *_pat = to_ast(pat); + + ptr_vector interp; + ptr_vector cnsts; // to throw away + + ast_manager &_m = mk_c(c)->m(); + + iz3interpolate(_m, + _pf, + cnsts, + _pat, + interp, + (interpolation_options_struct *)0 // ignore params for now + ); + + // copy result back + for (unsigned i = 0; i < interp.size(); i++){ + v->m_ast_vector.push_back(interp[i]); + _m.dec_ref(interp[i]); + } + RETURN_Z3(of_ast_vector(v)); + Z3_CATCH_RETURN(0); + } + + Z3_lbool Z3_API Z3_compute_interpolant(__in Z3_context c, __in Z3_ast pat, __in Z3_params p, __out Z3_ast_vector *out_interp, __out Z3_model *model){ + Z3_TRY; + LOG_Z3_compute_interpolant(c, pat, p, out_interp, model); + RESET_ERROR_CODE(); + + + // params_ref &_p = to_params(p)->m_params; + params_ref _p; + _p.set_bool("proof", true); // this is currently useless + + scoped_proof_mode spm(mk_c(c)->m(), PGM_FINE); + scoped_ptr sf = mk_smt_solver_factory(); + scoped_ptr m_solver((*sf)(mk_c(c)->m(), _p, true, true, true, ::symbol::null)); + m_solver.get()->updt_params(_p); // why do we have to do this? + + ast *_pat = to_ast(pat); + + ptr_vector interp; + ptr_vector cnsts; // to throw away + + ast_manager &_m = mk_c(c)->m(); + + model_ref m; + lbool _status = iz3interpolate(_m, + *(m_solver.get()), + _pat, + cnsts, + interp, + m, + 0 // ignore params for now + ); + + Z3_lbool status = of_lbool(_status); + + Z3_ast_vector_ref *v = 0; + *model = 0; + + if (_status == l_false){ + // copy result back + v = alloc(Z3_ast_vector_ref, mk_c(c)->m()); + mk_c(c)->save_object(v); + for (unsigned i = 0; i < interp.size(); i++){ + v->m_ast_vector.push_back(interp[i]); + _m.dec_ref(interp[i]); + } + } + else { + model_ref _m; + m_solver.get()->get_model(_m); + Z3_model_ref *crap = alloc(Z3_model_ref); + crap->m_model = _m.get(); + mk_c(c)->save_object(crap); + *model = of_model(crap); + } + + *out_interp = of_ast_vector(v); + + return status; + Z3_CATCH_RETURN(Z3_L_UNDEF); + } }; static void tokenize(const std::string &str, std::vector &tokens){ - for(unsigned i = 0; i < str.size();){ - if(str[i] == ' '){i++; continue;} - unsigned beg = i; - while(i < str.size() && str[i] != ' ')i++; - if(i > beg) - tokens.push_back(str.substr(beg,i-beg)); - } + for (unsigned i = 0; i < str.size();){ + if (str[i] == ' '){ i++; continue; } + unsigned beg = i; + while (i < str.size() && str[i] != ' ')i++; + if (i > beg) + tokens.push_back(str.substr(beg, i - beg)); + } } -static void get_file_params(const char *filename, hash_map ¶ms){ - std::ifstream f(filename); - if(f){ - std::string first_line; - std::getline(f,first_line); - // std::cout << "first line: '" << first_line << "'" << std::endl; - if(first_line.size() >= 2 && first_line[0] == ';' && first_line[1] == '!'){ - std::vector tokens; - tokenize(first_line.substr(2,first_line.size()-2),tokens); - for(unsigned i = 0; i < tokens.size(); i++){ - std::string &tok = tokens[i]; - size_t eqpos = tok.find('='); - if(eqpos != std::string::npos){ - std::string left = tok.substr(0,eqpos); - std::string right = tok.substr(eqpos+1,tok.size()-eqpos-1); - params[left] = right; +static void get_file_params(const char *filename, hash_map ¶ms){ + std::ifstream f(filename); + if (f){ + std::string first_line; + std::getline(f, first_line); + // std::cout << "first line: '" << first_line << "'" << std::endl; + if (first_line.size() >= 2 && first_line[0] == ';' && first_line[1] == '!'){ + std::vector tokens; + tokenize(first_line.substr(2, first_line.size() - 2), tokens); + for (unsigned i = 0; i < tokens.size(); i++){ + std::string &tok = tokens[i]; + size_t eqpos = tok.find('='); + if (eqpos != std::string::npos){ + std::string left = tok.substr(0, eqpos); + std::string right = tok.substr(eqpos + 1, tok.size() - eqpos - 1); + params[left] = right; + } + } } - } + f.close(); } - f.close(); - } } extern "C" { #if 0 - static void iZ3_write_seq(Z3_context ctx, int num, Z3_ast *cnsts, const char *filename, int num_theory, Z3_ast *theory){ - int num_fmlas = num+num_theory; - std::vector fmlas(num_fmlas); - if(num_theory) - std::copy(theory,theory+num_theory,fmlas.begin()); - for(int i = 0; i < num_theory; i++) - fmlas[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),fmlas[i]); - std::copy(cnsts,cnsts+num,fmlas.begin()+num_theory); - Z3_string smt = Z3_benchmark_to_smtlib_string(ctx,"none","AUFLIA","unknown","",num_fmlas-1,&fmlas[0],fmlas[num_fmlas-1]); - std::ofstream f(filename); - if(num_theory) - f << ";! THEORY=" << num_theory << "\n"; - f << smt; - f.close(); - } + static void iZ3_write_seq(Z3_context ctx, int num, Z3_ast *cnsts, const char *filename, int num_theory, Z3_ast *theory){ + int num_fmlas = num+num_theory; + std::vector fmlas(num_fmlas); + if(num_theory) + std::copy(theory,theory+num_theory,fmlas.begin()); + for(int i = 0; i < num_theory; i++) + fmlas[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),fmlas[i]); + std::copy(cnsts,cnsts+num,fmlas.begin()+num_theory); + Z3_string smt = Z3_benchmark_to_smtlib_string(ctx,"none","AUFLIA","unknown","",num_fmlas-1,&fmlas[0],fmlas[num_fmlas-1]); + std::ofstream f(filename); + if(num_theory) + f << ";! THEORY=" << num_theory << "\n"; + f << smt; + f.close(); + } - void Z3_write_interpolation_problem(Z3_context ctx, int num, Z3_ast *cnsts, int *parents, const char *filename, int num_theory, Z3_ast *theory){ - if(!parents){ - iZ3_write_seq(ctx,num,cnsts,filename,num_theory,theory); - return; + void Z3_write_interpolation_problem(Z3_context ctx, int num, Z3_ast *cnsts, unsigned *parents, const char *filename, int num_theory, Z3_ast *theory){ + if(!parents){ + iZ3_write_seq(ctx,num,cnsts,filename,num_theory,theory); + return; + } + std::vector tcnsts(num); + hash_map syms; + for(int j = 0; j < num - 1; j++){ + std::ostringstream oss; + oss << "$P" << j; + std::string name = oss.str(); + Z3_symbol s = Z3_mk_string_symbol(ctx, name.c_str()); + Z3_ast symbol = Z3_mk_const(ctx, s, Z3_mk_bool_sort(ctx)); + syms[j] = symbol; + tcnsts[j] = Z3_mk_implies(ctx,cnsts[j],symbol); + } + tcnsts[num-1] = Z3_mk_implies(ctx,cnsts[num-1],Z3_mk_false(ctx)); + for(int j = num-2; j >= 0; j--){ + int parent = parents[j]; + // assert(parent >= 0 && parent < num); + tcnsts[parent] = Z3_mk_implies(ctx,syms[j],tcnsts[parent]); + } + iZ3_write_seq(ctx,num,&tcnsts[0],filename,num_theory,theory); } - std::vector tcnsts(num); - hash_map syms; - for(int j = 0; j < num - 1; j++){ - std::ostringstream oss; - oss << "$P" << j; - std::string name = oss.str(); - Z3_symbol s = Z3_mk_string_symbol(ctx, name.c_str()); - Z3_ast symbol = Z3_mk_const(ctx, s, Z3_mk_bool_sort(ctx)); - syms[j] = symbol; - tcnsts[j] = Z3_mk_implies(ctx,cnsts[j],symbol); - } - tcnsts[num-1] = Z3_mk_implies(ctx,cnsts[num-1],Z3_mk_false(ctx)); - for(int j = num-2; j >= 0; j--){ - int parent = parents[j]; - // assert(parent >= 0 && parent < num); - tcnsts[parent] = Z3_mk_implies(ctx,syms[j],tcnsts[parent]); - } - iZ3_write_seq(ctx,num,&tcnsts[0],filename,num_theory,theory); - } #else - static Z3_ast and_vec(Z3_context ctx,svector &c){ - return (c.size() > 1) ? Z3_mk_and(ctx,c.size(),&c[0]) : c[0]; - } - - static Z3_ast parents_vector_to_tree(Z3_context ctx, int num, Z3_ast *cnsts, int *parents){ - Z3_ast res; - if(!parents){ - res = Z3_mk_interp(ctx,cnsts[0]); - for(int i = 1; i < num-1; i++){ - Z3_ast bar[2] = {res,cnsts[i]}; - res = Z3_mk_interp(ctx,Z3_mk_and(ctx,2,bar)); - } - if(num > 1){ - Z3_ast bar[2] = {res,cnsts[num-1]}; - res = Z3_mk_and(ctx,2,bar); - } + static Z3_ast and_vec(Z3_context ctx, svector &c){ + return (c.size() > 1) ? Z3_mk_and(ctx, c.size(), &c[0]) : c[0]; } - else { - std::vector > chs(num); - for(int i = 0; i < num-1; i++){ - svector &c = chs[i]; - c.push_back(cnsts[i]); - Z3_ast foo = Z3_mk_interp(ctx,and_vec(ctx,c)); - chs[parents[i]].push_back(foo); - } - { - svector &c = chs[num-1]; - c.push_back(cnsts[num-1]); - res = and_vec(ctx,c); - } - } - Z3_inc_ref(ctx,res); - return res; - } - void Z3_write_interpolation_problem(Z3_context ctx, int num, Z3_ast *cnsts, int *parents, const char *filename, int num_theory, Z3_ast *theory){ - std::ofstream f(filename); - if(num > 0){ - ptr_vector cnsts_vec(num); // get constraints in a vector - for(int i = 0; i < num; i++){ - expr *a = to_expr(cnsts[i]); - cnsts_vec[i] = a; + static Z3_ast parents_vector_to_tree(Z3_context ctx, int num, Z3_ast *cnsts, unsigned *parents){ + Z3_ast res; + if (!parents){ + res = Z3_mk_interpolant(ctx, cnsts[0]); + for (int i = 1; i < num - 1; i++){ + Z3_ast bar[2] = { res, cnsts[i] }; + res = Z3_mk_interpolant(ctx, Z3_mk_and(ctx, 2, bar)); + } + if (num > 1){ + Z3_ast bar[2] = { res, cnsts[num - 1] }; + res = Z3_mk_and(ctx, 2, bar); + } + } + else { + std::vector > chs(num); + for (int i = 0; i < num - 1; i++){ + svector &c = chs[i]; + c.push_back(cnsts[i]); + Z3_ast foo = Z3_mk_interpolant(ctx, and_vec(ctx, c)); + chs[parents[i]].push_back(foo); + } + { + svector &c = chs[num - 1]; + c.push_back(cnsts[num - 1]); + res = and_vec(ctx, c); } - Z3_ast tree = parents_vector_to_tree(ctx,num,cnsts,parents); - for(int i = 0; i < num_theory; i++){ - expr *a = to_expr(theory[i]); - cnsts_vec.push_back(a); - } - iz3pp(mk_c(ctx)->m(),cnsts_vec,to_expr(tree),f); - Z3_dec_ref(ctx,tree); + } + Z3_inc_ref(ctx, res); + return res; } - f.close(); + + void Z3_write_interpolation_problem(Z3_context ctx, unsigned num, Z3_ast *cnsts, unsigned *parents, const char *filename, unsigned num_theory, Z3_ast *theory){ + std::ofstream f(filename); + if (num > 0){ + ptr_vector cnsts_vec(num); // get constraints in a vector + for (int i = 0; i < num; i++){ + expr *a = to_expr(cnsts[i]); + cnsts_vec[i] = a; + } + Z3_ast tree = parents_vector_to_tree(ctx, num, cnsts, parents); + for (int i = 0; i < num_theory; i++){ + expr *a = to_expr(theory[i]); + cnsts_vec.push_back(a); + } + iz3pp(mk_c(ctx)->m(), cnsts_vec, to_expr(tree), f); + Z3_dec_ref(ctx, tree); + } + f.close(); #if 0 - - if(!parents){ - iZ3_write_seq(ctx,num,cnsts,filename,num_theory,theory); - return; - } - std::vector tcnsts(num); - hash_map syms; - for(int j = 0; j < num - 1; j++){ - std::ostringstream oss; - oss << "$P" << j; - std::string name = oss.str(); - Z3_symbol s = Z3_mk_string_symbol(ctx, name.c_str()); - Z3_ast symbol = Z3_mk_const(ctx, s, Z3_mk_bool_sort(ctx)); - syms[j] = symbol; - tcnsts[j] = Z3_mk_implies(ctx,cnsts[j],symbol); - } - tcnsts[num-1] = Z3_mk_implies(ctx,cnsts[num-1],Z3_mk_false(ctx)); - for(int j = num-2; j >= 0; j--){ - int parent = parents[j]; - // assert(parent >= 0 && parent < num); - tcnsts[parent] = Z3_mk_implies(ctx,syms[j],tcnsts[parent]); - } - iZ3_write_seq(ctx,num,&tcnsts[0],filename,num_theory,theory); + + if(!parents){ + iZ3_write_seq(ctx,num,cnsts,filename,num_theory,theory); + return; + } + std::vector tcnsts(num); + hash_map syms; + for(int j = 0; j < num - 1; j++){ + std::ostringstream oss; + oss << "$P" << j; + std::string name = oss.str(); + Z3_symbol s = Z3_mk_string_symbol(ctx, name.c_str()); + Z3_ast symbol = Z3_mk_const(ctx, s, Z3_mk_bool_sort(ctx)); + syms[j] = symbol; + tcnsts[j] = Z3_mk_implies(ctx,cnsts[j],symbol); + } + tcnsts[num-1] = Z3_mk_implies(ctx,cnsts[num-1],Z3_mk_false(ctx)); + for(int j = num-2; j >= 0; j--){ + int parent = parents[j]; + // assert(parent >= 0 && parent < num); + tcnsts[parent] = Z3_mk_implies(ctx,syms[j],tcnsts[parent]); + } + iZ3_write_seq(ctx,num,&tcnsts[0],filename,num_theory,theory); #endif - } + } #endif - static std::vector read_cnsts; - static std::vector read_parents; - static std::ostringstream read_error; - static std::string read_msg; - static std::vector read_theory; + static std::vector read_cnsts; + static std::vector read_parents; + static std::ostringstream read_error; + static std::string read_msg; + static std::vector read_theory; - static bool iZ3_parse(Z3_context ctx, const char *filename, const char **error, svector &assertions){ - read_error.clear(); - try { - std::string foo(filename); - if(foo.size() >= 5 && foo.substr(foo.size()-5) == ".smt2"){ - Z3_ast ass = Z3_parse_smtlib2_file(ctx, filename, 0, 0, 0, 0, 0, 0); - Z3_app app = Z3_to_app(ctx,ass); - int nconjs = Z3_get_app_num_args(ctx,app); - assertions.resize(nconjs); - for(int k = 0; k < nconjs; k++) - assertions[k] = Z3_get_app_arg(ctx,app,k); - } - else { - Z3_parse_smtlib_file(ctx, filename, 0, 0, 0, 0, 0, 0); - int numa = Z3_get_smtlib_num_assumptions(ctx); - int numf = Z3_get_smtlib_num_formulas(ctx); - int num = numa + numf; - - assertions.resize(num); - for(int j = 0; j < num; j++){ - if(j < numa) - assertions[j] = Z3_get_smtlib_assumption(ctx,j); - else - assertions[j] = Z3_get_smtlib_formula(ctx,j-numa); - } - } - } - catch(...) { - read_error << "SMTLIB parse error: " << Z3_get_smtlib_error(ctx); - read_msg = read_error.str(); - *error = read_msg.c_str(); - return false; - } - Z3_set_error_handler(ctx, 0); - return true; - } - + static bool iZ3_parse(Z3_context ctx, const char *filename, const char **error, svector &assertions){ + read_error.clear(); + try { + std::string foo(filename); + if (foo.size() >= 5 && foo.substr(foo.size() - 5) == ".smt2"){ + Z3_ast ass = Z3_parse_smtlib2_file(ctx, filename, 0, 0, 0, 0, 0, 0); + Z3_app app = Z3_to_app(ctx, ass); + int nconjs = Z3_get_app_num_args(ctx, app); + assertions.resize(nconjs); + for (int k = 0; k < nconjs; k++) + assertions[k] = Z3_get_app_arg(ctx, app, k); + } + else { + Z3_parse_smtlib_file(ctx, filename, 0, 0, 0, 0, 0, 0); + int numa = Z3_get_smtlib_num_assumptions(ctx); + int numf = Z3_get_smtlib_num_formulas(ctx); + int num = numa + numf; - int Z3_read_interpolation_problem(Z3_context ctx, int *_num, Z3_ast **cnsts, int **parents, const char *filename, const char **error, int *ret_num_theory, Z3_ast **theory ){ - - hash_map file_params; - get_file_params(filename,file_params); - - unsigned num_theory = 0; - if(file_params.find("THEORY") != file_params.end()) - num_theory = atoi(file_params["THEORY"].c_str()); - - svector assertions; - if(!iZ3_parse(ctx,filename,error,assertions)) - return false; - - if(num_theory > assertions.size()) - num_theory = assertions.size(); - unsigned num = assertions.size() - num_theory; - - read_cnsts.resize(num); - read_parents.resize(num); - read_theory.resize(num_theory); - - for(unsigned j = 0; j < num_theory; j++) - read_theory[j] = assertions[j]; - for(unsigned j = 0; j < num; j++) - read_cnsts[j] = assertions[j+num_theory]; - - if(ret_num_theory) - *ret_num_theory = num_theory; - if(theory) - *theory = &read_theory[0]; - - if(!parents){ - *_num = num; - *cnsts = &read_cnsts[0]; - return true; + assertions.resize(num); + for (int j = 0; j < num; j++){ + if (j < numa) + assertions[j] = Z3_get_smtlib_assumption(ctx, j); + else + assertions[j] = Z3_get_smtlib_formula(ctx, j - numa); + } + } + } + catch (...) { + read_error << "SMTLIB parse error: " << Z3_get_smtlib_error(ctx); + read_msg = read_error.str(); + *error = read_msg.c_str(); + return false; + } + Z3_set_error_handler(ctx, 0); + return true; } - for(unsigned j = 0; j < num; j++) - read_parents[j] = SHRT_MAX; - - hash_map pred_map; - for(unsigned j = 0; j < num; j++){ - Z3_ast lhs = 0, rhs = read_cnsts[j]; + int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast **cnsts, unsigned **parents, const char *filename, const char **error, unsigned *ret_num_theory, Z3_ast **theory){ - if(Z3_get_decl_kind(ctx,Z3_get_app_decl(ctx,Z3_to_app(ctx,rhs))) == Z3_OP_IMPLIES){ - Z3_app app1 = Z3_to_app(ctx,rhs); - Z3_ast lhs1 = Z3_get_app_arg(ctx,app1,0); - Z3_ast rhs1 = Z3_get_app_arg(ctx,app1,1); - if(Z3_get_decl_kind(ctx,Z3_get_app_decl(ctx,Z3_to_app(ctx,lhs1))) == Z3_OP_AND){ - Z3_app app2 = Z3_to_app(ctx,lhs1); - int nconjs = Z3_get_app_num_args(ctx,app2); - for(int k = nconjs - 1; k >= 0; --k) - rhs1 = Z3_mk_implies(ctx,Z3_get_app_arg(ctx,app2,k),rhs1); - rhs = rhs1; - } - } + hash_map file_params; + get_file_params(filename, file_params); + + unsigned num_theory = 0; + if (file_params.find("THEORY") != file_params.end()) + num_theory = atoi(file_params["THEORY"].c_str()); + + svector assertions; + if (!iZ3_parse(ctx, filename, error, assertions)) + return false; + + if (num_theory > assertions.size()) + num_theory = assertions.size(); + unsigned num = assertions.size() - num_theory; + + read_cnsts.resize(num); + read_parents.resize(num); + read_theory.resize(num_theory); + + for (unsigned j = 0; j < num_theory; j++) + read_theory[j] = assertions[j]; + for (unsigned j = 0; j < num; j++) + read_cnsts[j] = assertions[j + num_theory]; + + if (ret_num_theory) + *ret_num_theory = num_theory; + if (theory) + *theory = &read_theory[0]; + + if (!parents){ + *_num = num; + *cnsts = &read_cnsts[0]; + return true; + } + + for (unsigned j = 0; j < num; j++) + read_parents[j] = SHRT_MAX; + + hash_map pred_map; + + for (unsigned j = 0; j < num; j++){ + Z3_ast lhs = 0, rhs = read_cnsts[j]; + + if (Z3_get_decl_kind(ctx, Z3_get_app_decl(ctx, Z3_to_app(ctx, rhs))) == Z3_OP_IMPLIES){ + Z3_app app1 = Z3_to_app(ctx, rhs); + Z3_ast lhs1 = Z3_get_app_arg(ctx, app1, 0); + Z3_ast rhs1 = Z3_get_app_arg(ctx, app1, 1); + if (Z3_get_decl_kind(ctx, Z3_get_app_decl(ctx, Z3_to_app(ctx, lhs1))) == Z3_OP_AND){ + Z3_app app2 = Z3_to_app(ctx, lhs1); + int nconjs = Z3_get_app_num_args(ctx, app2); + for (int k = nconjs - 1; k >= 0; --k) + rhs1 = Z3_mk_implies(ctx, Z3_get_app_arg(ctx, app2, k), rhs1); + rhs = rhs1; + } + } + + while (1){ + Z3_app app = Z3_to_app(ctx, rhs); + Z3_func_decl func = Z3_get_app_decl(ctx, app); + Z3_decl_kind dk = Z3_get_decl_kind(ctx, func); + if (dk == Z3_OP_IMPLIES){ + if (lhs){ + Z3_ast child = lhs; + if (pred_map.find(child) == pred_map.end()){ + read_error << "formula " << j + 1 << ": unknown: " << Z3_ast_to_string(ctx, child); + goto fail; + } + int child_num = pred_map[child]; + if (read_parents[child_num] != SHRT_MAX){ + read_error << "formula " << j + 1 << ": multiple reference: " << Z3_ast_to_string(ctx, child); + goto fail; + } + read_parents[child_num] = j; + } + lhs = Z3_get_app_arg(ctx, app, 0); + rhs = Z3_get_app_arg(ctx, app, 1); + } + else { + if (!lhs){ + read_error << "formula " << j + 1 << ": should be (implies {children} fmla parent)"; + goto fail; + } + read_cnsts[j] = lhs; + Z3_ast name = rhs; + if (pred_map.find(name) != pred_map.end()){ + read_error << "formula " << j + 1 << ": duplicate symbol"; + goto fail; + } + pred_map[name] = j; + break; + } + } + } + + for (unsigned j = 0; j < num - 1; j++) + if (read_parents[j] == SHRT_MIN){ + read_error << "formula " << j + 1 << ": unreferenced"; + goto fail; + } + + *_num = num; + *cnsts = &read_cnsts[0]; + *parents = &read_parents[0]; + return true; + + fail: + read_msg = read_error.str(); + *error = read_msg.c_str(); + return false; - while(1){ - Z3_app app = Z3_to_app(ctx,rhs); - Z3_func_decl func = Z3_get_app_decl(ctx,app); - Z3_decl_kind dk = Z3_get_decl_kind(ctx,func); - if(dk == Z3_OP_IMPLIES){ - if(lhs){ - Z3_ast child = lhs; - if(pred_map.find(child) == pred_map.end()){ - read_error << "formula " << j+1 << ": unknown: " << Z3_ast_to_string(ctx,child); - goto fail; - } - int child_num = pred_map[child]; - if(read_parents[child_num] != SHRT_MAX){ - read_error << "formula " << j+1 << ": multiple reference: " << Z3_ast_to_string(ctx,child); - goto fail; - } - read_parents[child_num] = j; - } - lhs = Z3_get_app_arg(ctx,app,0); - rhs = Z3_get_app_arg(ctx,app,1); - } - else { - if(!lhs){ - read_error << "formula " << j+1 << ": should be (implies {children} fmla parent)"; - goto fail; - } - read_cnsts[j] = lhs; - Z3_ast name = rhs; - if(pred_map.find(name) != pred_map.end()){ - read_error << "formula " << j+1 << ": duplicate symbol"; - goto fail; - } - pred_map[name] = j; - break; - } - } } - - for(unsigned j = 0; j < num-1; j++) - if(read_parents[j] == SHRT_MIN){ - read_error << "formula " << j+1 << ": unreferenced"; - goto fail; - } - - *_num = num; - *cnsts = &read_cnsts[0]; - *parents = &read_parents[0]; - return true; - - fail: - read_msg = read_error.str(); - *error = read_msg.c_str(); - return false; - - } } diff --git a/src/api/dotnet/Constructor.cs b/src/api/dotnet/Constructor.cs index 527b8bc13..8d478dd85 100644 --- a/src/api/dotnet/Constructor.cs +++ b/src/api/dotnet/Constructor.cs @@ -50,7 +50,7 @@ namespace Microsoft.Z3 IntPtr constructor = IntPtr.Zero; IntPtr tester = IntPtr.Zero; IntPtr[] accessors = new IntPtr[n]; - Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors); + Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors); return new FuncDecl(Context, constructor); } } @@ -66,7 +66,7 @@ namespace Microsoft.Z3 IntPtr constructor = IntPtr.Zero; IntPtr tester = IntPtr.Zero; IntPtr[] accessors = new IntPtr[n]; - Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors); + Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors); return new FuncDecl(Context, tester); } } @@ -82,7 +82,7 @@ namespace Microsoft.Z3 IntPtr constructor = IntPtr.Zero; IntPtr tester = IntPtr.Zero; IntPtr[] accessors = new IntPtr[n]; - Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors); + Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors); FuncDecl[] t = new FuncDecl[n]; for (uint i = 0; i < n; i++) t[i] = new FuncDecl(Context, accessors[i]); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 2b88cbab7..a9e25de4f 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -424,7 +424,7 @@ namespace Microsoft.Z3 n_constr[i] = cla[i].NativeObject; } IntPtr[] n_res = new IntPtr[n]; - Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); + Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), out n_res, n_constr); DatatypeSort[] res = new DatatypeSort[n]; for (uint i = 0; i < n; i++) res[i] = new DatatypeSort(this, n_res[i]); diff --git a/src/api/dotnet/EnumSort.cs b/src/api/dotnet/EnumSort.cs index e62043078..db3d5123f 100644 --- a/src/api/dotnet/EnumSort.cs +++ b/src/api/dotnet/EnumSort.cs @@ -88,7 +88,7 @@ namespace Microsoft.Z3 IntPtr[] n_constdecls = new IntPtr[n]; IntPtr[] n_testers = new IntPtr[n]; NativeObject = Native.Z3_mk_enumeration_sort(ctx.nCtx, name.NativeObject, (uint)n, - Symbol.ArrayToNative(enumNames), n_constdecls, n_testers); + Symbol.ArrayToNative(enumNames), out n_constdecls, out n_testers); } #endregion }; diff --git a/src/api/dotnet/Expr.cs b/src/api/dotnet/Expr.cs index c8fdfb51f..f4a63a61b 100644 --- a/src/api/dotnet/Expr.cs +++ b/src/api/dotnet/Expr.cs @@ -323,6 +323,14 @@ namespace Microsoft.Z3 #endregion + #region Interpolation + /// + /// Indicates whether the term is marked for interpolation. + /// + /// + public bool IsInterpolant { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_INTERP; } } + #endregion + #region Arithmetic Terms /// /// Indicates whether the term is of integer sort. @@ -791,7 +799,7 @@ namespace Microsoft.Z3 /// /// A label literal has a set of string parameters. It takes no arguments. public bool IsLabelLit { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_LABEL_LIT; } } - #endregion + #endregion #region Proof Terms /// diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs new file mode 100644 index 000000000..559a1bfc7 --- /dev/null +++ b/src/api/dotnet/InterpolationContext.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics.Contracts; +using System.Runtime.InteropServices; + +namespace Microsoft.Z3 +{ + /// + /// The InterpolationContext is suitable for generation of interpolants. + /// + /// For more information on interpolation please refer + /// too the C/C++ API, which is well documented. + [ContractVerification(true)] + class InterpolationContext : Context + { + + /// + /// Constructor. + /// + public InterpolationContext() : base() { } + + /// + /// Constructor. + /// + /// + public InterpolationContext(Dictionary settings) : base(settings) { } + + #region Terms + /// + /// Create an expression that marks a formula position for interpolation. + /// + public BoolExpr MkInterpolant(BoolExpr a) + { + Contract.Requires(a != null); + Contract.Ensures(Contract.Result() != null); + + CheckContextMatch(a); + return new BoolExpr(this, Native.Z3_mk_interpolant(nCtx, a.NativeObject)); + } + #endregion + + /// + /// Computes an interpolant. + /// + /// For more information on interpolation please refer + /// too the function Z3_get_interpolant in the C/C++ API, which is + /// well documented. + Expr[] GetInterpolant(Expr pf, Expr pat, Params p) + { + Contract.Requires(pf != null); + Contract.Requires(pat != null); + Contract.Requires(p != null); + Contract.Ensures(Contract.Result() != null); + + CheckContextMatch(pf); + CheckContextMatch(pat); + CheckContextMatch(p); + + ASTVector seq = new ASTVector(this, Native.Z3_get_interpolant(nCtx, pf.NativeObject, pat.NativeObject, p.NativeObject)); + uint n = seq.Size; + Expr[] res = new Expr[n]; + for (uint i = 0; i < n; i++) + res[i] = Expr.Create(this, seq[i].NativeObject); + return res; + } + + /// + /// Computes an interpolant. + /// + /// For more information on interpolation please refer + /// too the function Z3_compute_interpolant in the C/C++ API, which is + /// well documented. + Z3_lbool ComputeInterpolant(Expr pat, Params p, out ASTVector interp, out Model model) + { + Contract.Requires(pat != null); + Contract.Requires(p != null); + Contract.Ensures(Contract.ValueAtReturn(out interp) != null); + Contract.Ensures(Contract.ValueAtReturn(out model) != null); + + CheckContextMatch(pat); + CheckContextMatch(p); + + IntPtr i = IntPtr.Zero, m = IntPtr.Zero; + int r = Native.Z3_compute_interpolant(nCtx, pat.NativeObject, p.NativeObject, ref i, ref m); + interp = new ASTVector(this, i); + model = new Model(this, m); + return (Z3_lbool)r; + } + + /// + /// Computes an interpolant. + /// + /// For more information on interpolation please refer + /// too the function Z3_compute_interpolant in the C/C++ API, which is + /// well documented. + Z3_lbool Interpolate(Expr[] cnsts, uint[] parents, Params options, bool incremental, Expr[] theory, out Expr[] interps, out Model model) + { + Contract.Requires(cnsts != null); + Contract.Requires(parents != null); + Contract.Requires(cnsts.Length == parents.Length); + Contract.Ensures(Contract.ValueAtReturn(out interps) != null); + Contract.Ensures(Contract.ValueAtReturn(out model) != null); + + CheckContextMatch(cnsts); + CheckContextMatch(theory); + + uint sz = (uint)cnsts.Length; + + IntPtr[] ni = new IntPtr[sz - 1]; + IntPtr nm = IntPtr.Zero; + IntPtr z = IntPtr.Zero; + + int r = Native.Z3_interpolate(nCtx, + sz, Expr.ArrayToNative(cnsts), parents, + options.NativeObject, + out ni, + ref nm, + ref z, // Z3_lterals are deprecated. + (uint)(incremental ? 1 : 0), + (uint)theory.Length, Expr.ArrayToNative(theory)); + + interps = new Expr[sz - 1]; + for (uint i = 0; i < sz - 1; i++) + interps[i] = Expr.Create(this, ni[i]); + + model = new Model(this, nm); + + return (Z3_lbool)r; + } + + /// + /// Return a string summarizing cumulative time used for interpolation. + /// + /// For more information on interpolation please refer + /// too the function Z3_interpolation_profile in the C/C++ API, which is + /// well documented. + public string InterpolationProfile() + { + return Native.Z3_interpolation_profile(nCtx); + } + + /// + /// Checks the correctness of an interpolant. + /// + /// For more information on interpolation please refer + /// too the function Z3_check_interpolant in the C/C++ API, which is + /// well documented. + public int CheckInterpolant(Expr[] cnsts, uint[] parents, Expr[] interps, out string error, Expr[] theory) + { + Contract.Requires(cnsts.Length == parents.Length); + Contract.Requires(cnsts.Length == interps.Length+1); + IntPtr n_err_str; + int r = Native.Z3_check_interpolant(nCtx, + (uint)cnsts.Length, + Expr.ArrayToNative(cnsts), + parents, + Expr.ArrayToNative(interps), + out n_err_str, + (uint)theory.Length, + Expr.ArrayToNative(theory)); + error = Marshal.PtrToStringAnsi(n_err_str); + return r; + } + + /// + /// Reads an interpolation problem from a file. + /// + /// For more information on interpolation please refer + /// too the function Z3_read_interpolation_problem in the C/C++ API, which is + /// well documented. + public int ReadInterpolationProblem(string filename, out Expr[] cnsts, out uint[] parents, out string error, out Expr[] theory) + { + uint num = 0, num_theory = 0; + IntPtr[] n_cnsts; + IntPtr[] n_theory; + IntPtr n_err_str; + uint[][] n_parents; + int r = Native.Z3_read_interpolation_problem(nCtx, ref num, out n_cnsts, out n_parents, filename, out n_err_str, ref num_theory, out n_theory); + error = Marshal.PtrToStringAnsi(n_err_str); + cnsts = new Expr[num]; + parents = new uint[num]; + theory = new Expr[num_theory]; + for (int i = 0; i < num; i++) + { + cnsts[i] = Expr.Create(this, n_cnsts[i]); + parents[i] = n_parents[0][i]; + } + for (int i = 0; i < num_theory; i++) + theory[i] = Expr.Create(this, n_theory[i]); + return r; + } + + /// + /// Writes an interpolation problem to a file. + /// + /// For more information on interpolation please refer + /// too the function Z3_write_interpolation_problem in the C/C++ API, which is + /// well documented. + public void WriteInterpolationProblem(string filename, Expr[] cnsts, int[] parents, string error, Expr[] theory) + { + Contract.Requires(cnsts.Length == parents.Length); + } + } +} diff --git a/src/api/dotnet/Microsoft.Z3.csproj b/src/api/dotnet/Microsoft.Z3.csproj index 0a062054d..cc7d3c0c5 100644 --- a/src/api/dotnet/Microsoft.Z3.csproj +++ b/src/api/dotnet/Microsoft.Z3.csproj @@ -19,12 +19,12 @@ true full false - ..\Debug\ + ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ DEBUG;TRACE prompt 4 true - ..\Debug\Microsoft.Z3.XML + C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML False False True @@ -254,7 +254,7 @@ true - bin\x86\Debug\ + ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ DEBUG;TRACE true full @@ -266,7 +266,7 @@ MinimumRecommendedRules.ruleset ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - bin\x86\Debug\Microsoft.Z3.XML + C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML bin\x86\Release\ @@ -352,6 +352,7 @@ + diff --git a/src/api/dotnet/TupleSort.cs b/src/api/dotnet/TupleSort.cs index 1e4af5cd7..7d0b6a853 100644 --- a/src/api/dotnet/TupleSort.cs +++ b/src/api/dotnet/TupleSort.cs @@ -74,9 +74,10 @@ namespace Microsoft.Z3 Contract.Requires(name != null); IntPtr t = IntPtr.Zero; + IntPtr[] f; NativeObject = Native.Z3_mk_tuple_sort(ctx.nCtx, name.NativeObject, numFields, Symbol.ArrayToNative(fieldNames), AST.ArrayToNative(fieldSorts), - ref t, new IntPtr[numFields]); + ref t, out f); } #endregion }; diff --git a/src/api/python/z3.py b/src/api/python/z3.py index b6cceeb8e..1a5565ab5 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -7253,19 +7253,19 @@ def parse_smt2_file(f, sorts={}, decls={}, ctx=None): dsz, dnames, ddecls = _dict2darray(decls, ctx) return _to_expr_ref(Z3_parse_smtlib2_file(ctx.ref(), f, ssz, snames, ssorts, dsz, dnames, ddecls), ctx) -def Interp(a,ctx=None): +def Interpolant(a,ctx=None): """Create an interpolation operator. The argument is an interpolation pattern (see tree_interpolant). >>> x = Int('x') - >>> print Interp(x>0) + >>> print Interpolant(x>0) interp(x > 0) """ ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx)) s = BoolSort(ctx) a = s.cast(a) - return BoolRef(Z3_mk_interp(ctx.ref(), a.as_ast()), ctx) + return BoolRef(Z3_mk_interpolant(ctx.ref(), a.as_ast()), ctx) def tree_interpolant(pat,p=None,ctx=None): """Compute interpolant for a tree of formulas. @@ -7304,10 +7304,10 @@ def tree_interpolant(pat,p=None,ctx=None): >>> x = Int('x') >>> y = Int('y') - >>> print tree_interpolant(And(Interp(x < 0), Interp(y > 2), x == y)) + >>> print tree_interpolant(And(Interpolant(x < 0), Interpolant(y > 2), x == y)) [Not(x >= 0), Not(y <= 2)] - >>> g = And(Interp(x<0),x<2) + >>> g = And(Interpolant(x<0),x<2) >>> try: ... print tree_interpolant(g).sexpr() ... except ModelRef as m: @@ -7346,7 +7346,7 @@ def binary_interpolant(a,b,p=None,ctx=None): print binary_interpolant(x<0,x>2) Not(x >= 0) """ - f = And(Interp(a),b) + f = And(Interpolant(a),b) return tree_interpolant(f,p,ctx)[0] def sequence_interpolant(v,p=None,ctx=None): @@ -7375,6 +7375,6 @@ def sequence_interpolant(v,p=None,ctx=None): """ f = v[0] for i in range(1,len(v)): - f = And(Interp(f),v[i]) + f = And(Interpolant(f),v[i]) return tree_interpolant(f,p,ctx) diff --git a/src/api/z3.h b/src/api/z3.h index db8becafd..2ebc20977 100644 --- a/src/api/z3.h +++ b/src/api/z3.h @@ -27,6 +27,7 @@ Notes: #include"z3_algebraic.h" #include"z3_polynomial.h" #include"z3_rcf.h" +#include"z3_interp.h" #undef __in #undef __out diff --git a/src/api/z3_api.h b/src/api/z3_api.h index b561b6bf1..41ccf532e 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -2116,17 +2116,7 @@ END_MLAPI_EXCLUDE def_API('Z3_mk_not', AST, (_in(CONTEXT), _in(AST))) */ Z3_ast Z3_API Z3_mk_not(__in Z3_context c, __in Z3_ast a); - - /** - \brief \mlh mk_interp c a \endmlh - Create an AST node marking a formula position for interpolation. - The node \c a must have Boolean sort. - - def_API('Z3_mk_interp', AST, (_in(CONTEXT), _in(AST))) - */ - Z3_ast Z3_API Z3_mk_interp(__in Z3_context c, __in Z3_ast a); - /** \brief \mlh mk_ite c t1 t2 t2 \endmlh Create an AST node representing an if-then-else: ite(t1, t2, @@ -7700,314 +7690,6 @@ END_MLAPI_EXCLUDE Z3_ast Z3_API Z3_get_context_assignment(__in Z3_context c); /*@}*/ - - /** - @name Interpolation - */ - /*@{*/ - - /** \brief This function generates a Z3 context suitable for generation of - interpolants. Formulas can be generated as abstract syntx trees in - this context using the Z3 C API. - - Interpolants are also generated as AST's in this context. - - If cfg is non-null, it will be used as the base configuration - for the Z3 context. This makes it possible to set Z3 options - to be used during interpolation. This feature should be used - with some caution however, as it may be that certain Z3 options - are incompatible with interpolation. - - def_API('Z3_mk_interpolation_context', CONTEXT, (_in(CONFIG),)) - - */ - - Z3_context Z3_API Z3_mk_interpolation_context(__in Z3_config cfg); - - /** Compute an interpolant from a refutation. This takes a proof of - "false" from a set of formulas C, and an interpolation - pattern. The pattern pat is a formula combining the formulas in C - using logical conjunction and the "interp" operator (see - #Z3_mk_interp). This interp operator is logically the identity - operator. It marks the sub-formulas of the pattern for which interpolants should - be computed. The interpolant is a map sigma from marked subformulas to - formulas, such that, for each marked subformula phi of pat (where phi sigma - is phi with sigma(psi) substituted for each subformula psi of phi such that - psi in dom(sigma)): - - 1) phi sigma implies sigma(phi), and - - 2) sigma(phi) is in the common uninterpreted vocabulary between - the formulas of C occurring in phi and those not occurring in - phi - - and moreover pat sigma implies false. In the simplest case - an interpolant for the pattern "(and (interp A) B)" maps A - to an interpolant for A /\ B. - - The return value is a vector of formulas representing sigma. The - vector contains sigma(phi) for each marked subformula of pat, in - pre-order traversal. This means that subformulas of phi occur before phi - in the vector. Also, subformulas that occur multiply in pat will - occur multiply in the result vector. - - In particular, calling Z3_get_interpolant on a pattern of the - form (interp ... (interp (and (interp A_1) A_2)) ... A_N) will - result in a sequence interpolant for A_1, A_2,... A_N. - - Neglecting interp markers, the pattern must be a conjunction of - formulas in C, the set of premises of the proof. Otherwise an - error is flagged. - - Any premises of the proof not present in the pattern are - treated as "background theory". Predicate and function symbols - occurring in the background theory are treated as interpreted and - thus always allowed in the interpolant. - - Interpolant may not necessarily be computable from all - proofs. To be sure an interpolant can be computed, the proof - must be generated by an SMT solver for which interpoaltion is - supported, and the premises must be expressed using only - theories and operators for which interpolation is supported. - - Currently, the only SMT solver that is supported is the legacy - SMT solver. Such a solver is available as the default solver in - #Z3_context objects produced by #Z3_mk_interpolation_context. - Currently, the theories supported are equality with - uninterpreted functions, linear integer arithmetic, and the - theory of arrays (in SMT-LIB terms, this is AUFLIA). - Quantifiers are allowed. Use of any other operators (including - "labels") may result in failure to compute an interpolant from a - proof. - - Parameters: - - \param c logical context. - \param pf a refutation from premises (assertions) C - \param pat an interpolation pattern over C - \param p parameters - - def_API('Z3_get_interpolant', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(PARAMS))) - */ - - Z3_ast_vector Z3_API Z3_get_interpolant(__in Z3_context c, __in Z3_ast pf, __in Z3_ast pat, __in Z3_params p); - - /* Compute an interpolant for an unsatisfiable conjunction of formulas. - - This takes as an argument an interpolation pattern as in - #Z3_get_interpolant. This is a conjunction, some subformulas of - which are marked with the "interp" operator (see #Z3_mk_interp). - - The conjunction is first checked for unsatisfiability. The result - of this check is returned in the out parameter "status". If the result - is unsat, an interpolant is computed from the refutation as in #Z3_get_interpolant - and returned as a vector of formulas. Otherwise the return value is - an empty formula. - - See #Z3_get_interpolant for a discussion of supported theories. - - The advantage of this function over #Z3_get_interpolant is that - it is not necessary to create a suitable SMT solver and generate - a proof. The disadvantage is that it is not possible to use the - solver incrementally. - - Parameters: - - \param c logical context. - \param pat an interpolation pattern - \param p parameters for solver creation - \param status returns the status of the sat check - \param model returns model if satisfiable - - Return value: status of SAT check - - def_API('Z3_compute_interpolant', INT, (_in(CONTEXT), _in(AST), _in(PARAMS), _out(AST_VECTOR), _out(MODEL))) - */ - - Z3_lbool Z3_API Z3_compute_interpolant(__in Z3_context c, __in Z3_ast pat, __in Z3_params p, __out Z3_ast_vector *interp, __out Z3_model *model); - - -/** Constant reprepresenting a root of a formula tree for tree interpolation */ -#define IZ3_ROOT SHRT_MAX - -/** This function uses Z3 to determine satisfiability of a set of - constraints. If UNSAT, an interpolant is returned, based on the - refutation generated by Z3. If SAT, a model is returned. - - If "parents" is non-null, computes a tree interpolant. The tree is - defined by the array "parents". This array maps each formula in - the tree to its parent, where formulas are indicated by their - integer index in "cnsts". The parent of formula n must have index - greater than n. The last formula is the root of the tree. Its - parent entry should be the constant IZ3_ROOT. - - If "parents" is null, computes a sequence interpolant. - - \param ctx The Z3 context. Must be generated by iz3_mk_context - \param num The number of constraints in the sequence - \param cnsts Array of constraints (AST's in context ctx) - \param parents The parents vector defining the tree structure - \param options Interpolation options (may be NULL) - \param interps Array to return interpolants (size at least num-1, may be NULL) - \param model Returns a Z3 model if constraints SAT (may be NULL) - \param labels Returns relevant labels if SAT (may be NULL) - \param incremental - - VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3 - context ctx. The model and interpolants returned are also - in this context. - - The return code is as in Z3_check_assumptions, that is, - - Z3_L_FALSE = constraints UNSAT (interpolants returned) - Z3_L_TRUE = constraints SAT (model returned) - Z3_L_UNDEF = Z3 produced no result, or interpolation not possible - - Currently, this function supports integer and boolean variables, - as well as arrays over these types, with linear arithmetic, - uninterpreted functions and quantifiers over integers (that is - AUFLIA). Interpolants are produced in AUFLIA. However, some - uses of array operations may cause quantifiers to appear in the - interpolants even when there are no quantifiers in the input formulas. - Although quantifiers may appear in the input formulas, Z3 may give up in - this case, returning Z3_L_UNDEF. - - If "incremental" is true, cnsts must contain exactly the set of - formulas that are currently asserted in the context. If false, - there must be no formulas currently asserted in the context. - Setting "incremental" to true makes it posisble to incrementally - add and remove constraints from the context until the context - becomes UNSAT, at which point an interpolant is computed. Caution - must be used, however. Before popping the context, if you wish to - keep the interolant formulas, you *must* preserve them by using - Z3_persist_ast. Also, if you want to simplify the interpolant - formulas using Z3_simplify, you must first pop all of the - assertions in the context (or use a different context). Otherwise, - the formulas will be simplified *relative* to these constraints, - which is almost certainly not what you want. - - - Current limitations on tree interpolants. In a tree interpolation - problem, each constant (0-ary function symbol) must occur only - along one path from root to leaf. Function symbols (of arity > 0) - are considered to have global scope (i.e., may appear in any - interpolant formula). - - - */ - - - Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx, - __in int num, - __in_ecount(num) Z3_ast *cnsts, - __in_ecount(num) unsigned *parents, - __in Z3_params options, - __out_ecount(num-1) Z3_ast *interps, - __out Z3_model *model, - __out Z3_literals *labels, - __in int incremental, - __in int num_theory, - __in_ecount(num_theory) Z3_ast *theory); - - /** Return a string summarizing cumulative time used for - interpolation. This string is purely for entertainment purposes - and has no semantics. - - \param ctx The context (currently ignored) - - def_API('Z3_interpolation_profile', STRING, (_in(CONTEXT),)) - */ - - Z3_string Z3_API Z3_interpolation_profile(__in Z3_context ctx); - - /** - \brief Read an interpolation problem from file. - - \param ctx The Z3 context. This resets the error handler of ctx. - \param filename The file name to read. - \param num Returns length of sequence. - \param cnsts Returns sequence of formulas (do not free) - \param parents Returns the parents vector (or NULL for sequence) - \param error Returns an error message in case of failure (do not free the string) - - Returns true on success. - - File formats: Currently two formats are supported, based on - SMT-LIB2. For sequence interpolants, the sequence of constraints is - represented by the sequence of "assert" commands in the file. - - For tree interpolants, one symbol of type bool is associated to - each vertex of the tree. For each vertex v there is an "assert" - of the form: - - (implies (and c1 ... cn f) v) - - where c1 .. cn are the children of v (which must precede v in the file) - and f is the formula assiciated to node v. The last formula in the - file is the root vertex, and is represented by the predicate "false". - - A solution to a tree interpolation problem can be thought of as a - valuation of the vertices that makes all the implications true - where each value is represented using the common symbols between - the formulas in the subtree and the remainder of the formulas. - - */ - - - int Z3_API Z3_read_interpolation_problem(__in Z3_context ctx, - __out int *num, - __out_ecount(*num) Z3_ast **cnsts, - __out_ecount(*num) int **parents, - __in const char *filename, - __out const char **error, - __out int *num_theory, - __out_ecount(*num_theory) Z3_ast **theory); - - - - /** Check the correctness of an interpolant. The Z3 context must - have no constraints asserted when this call is made. That means - that after interpolating, you must first fully pop the Z3 - context before calling this. See Z3_interpolate for meaning of parameters. - - \param ctx The Z3 context. Must be generated by Z3_mk_interpolation_context - \param num The number of constraints in the sequence - \param cnsts Array of constraints (AST's in context ctx) - \param parents The parents vector (or NULL for sequence) - \param interps The interpolant to check - \param error Returns an error message if interpolant incorrect (do not free the string) - - Return value is Z3_L_TRUE if interpolant is verified, Z3_L_FALSE if - incorrect, and Z3_L_UNDEF if unknown. - - */ - - int Z3_API Z3_check_interpolant(Z3_context ctx, int num, Z3_ast *cnsts, int *parents, Z3_ast *interps, const char **error, - int num_theory, Z3_ast *theory); - - /** Write an interpolation problem to file suitable for reading with - Z3_read_interpolation_problem. The output file is a sequence - of SMT-LIB2 format commands, suitable for reading with command-line Z3 - or other interpolating solvers. - - \param ctx The Z3 context. Must be generated by z3_mk_interpolation_context - \param num The number of constraints in the sequence - \param cnsts Array of constraints - \param parents The parents vector (or NULL for sequence) - \param filename The file name to write - - */ - - void Z3_API Z3_write_interpolation_problem(Z3_context ctx, - int num, - Z3_ast *cnsts, - int *parents, - const char *filename, - int num_theory, - Z3_ast *theory); - - - #endif diff --git a/src/api/z3_interp.h b/src/api/z3_interp.h new file mode 100644 index 000000000..1aac13b6e --- /dev/null +++ b/src/api/z3_interp.h @@ -0,0 +1,359 @@ +/*++ +Copyright (c) 2014 Microsoft Corporation + +Module Name: + + z3_interp.h + +Abstract: + + API for interpolation + +Author: + + Kenneth McMillan (kenmcmil) + +Notes: + +--*/ +#ifndef _Z3_INTERPOLATION_H_ +#define _Z3_INTERPOLATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + /** + @name Interpolation + */ + /*@{*/ + + /** + \brief \mlh mk_interp c a \endmlh + Create an AST node marking a formula position for interpolation. + + The node \c a must have Boolean sort. + + def_API('Z3_mk_interpolant', AST, (_in(CONTEXT), _in(AST))) + */ + Z3_ast Z3_API Z3_mk_interpolant(__in Z3_context c, __in Z3_ast a); + + + /** \brief This function generates a Z3 context suitable for generation of + interpolants. Formulas can be generated as abstract syntax trees in + this context using the Z3 C API. + + Interpolants are also generated as AST's in this context. + + If cfg is non-null, it will be used as the base configuration + for the Z3 context. This makes it possible to set Z3 options + to be used during interpolation. This feature should be used + with some caution however, as it may be that certain Z3 options + are incompatible with interpolation. + + def_API('Z3_mk_interpolation_context', CONTEXT, (_in(CONFIG),)) + + */ + + Z3_context Z3_API Z3_mk_interpolation_context(__in Z3_config cfg); + + /** Compute an interpolant from a refutation. This takes a proof of + "false" from a set of formulas C, and an interpolation + pattern. The pattern pat is a formula combining the formulas in C + using logical conjunction and the "interp" operator (see + #Z3_mk_interpolant). This interp operator is logically the identity + operator. It marks the sub-formulas of the pattern for which interpolants should + be computed. The interpolant is a map sigma from marked subformulas to + formulas, such that, for each marked subformula phi of pat (where phi sigma + is phi with sigma(psi) substituted for each subformula psi of phi such that + psi in dom(sigma)): + + 1) phi sigma implies sigma(phi), and + + 2) sigma(phi) is in the common uninterpreted vocabulary between + the formulas of C occurring in phi and those not occurring in + phi + + and moreover pat sigma implies false. In the simplest case + an interpolant for the pattern "(and (interp A) B)" maps A + to an interpolant for A /\ B. + + The return value is a vector of formulas representing sigma. The + vector contains sigma(phi) for each marked subformula of pat, in + pre-order traversal. This means that subformulas of phi occur before phi + in the vector. Also, subformulas that occur multiply in pat will + occur multiply in the result vector. + + In particular, calling Z3_get_interpolant on a pattern of the + form (interp ... (interp (and (interp A_1) A_2)) ... A_N) will + result in a sequence interpolant for A_1, A_2,... A_N. + + Neglecting interp markers, the pattern must be a conjunction of + formulas in C, the set of premises of the proof. Otherwise an + error is flagged. + + Any premises of the proof not present in the pattern are + treated as "background theory". Predicate and function symbols + occurring in the background theory are treated as interpreted and + thus always allowed in the interpolant. + + Interpolant may not necessarily be computable from all + proofs. To be sure an interpolant can be computed, the proof + must be generated by an SMT solver for which interpoaltion is + supported, and the premises must be expressed using only + theories and operators for which interpolation is supported. + + Currently, the only SMT solver that is supported is the legacy + SMT solver. Such a solver is available as the default solver in + #Z3_context objects produced by #Z3_mk_interpolation_context. + Currently, the theories supported are equality with + uninterpreted functions, linear integer arithmetic, and the + theory of arrays (in SMT-LIB terms, this is AUFLIA). + Quantifiers are allowed. Use of any other operators (including + "labels") may result in failure to compute an interpolant from a + proof. + + Parameters: + + \param c logical context. + \param pf a refutation from premises (assertions) C + \param pat an interpolation pattern over C + \param p parameters + + def_API('Z3_get_interpolant', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(PARAMS))) + */ + + Z3_ast_vector Z3_API Z3_get_interpolant(__in Z3_context c, __in Z3_ast pf, __in Z3_ast pat, __in Z3_params p); + + /* Compute an interpolant for an unsatisfiable conjunction of formulas. + + This takes as an argument an interpolation pattern as in + #Z3_get_interpolant. This is a conjunction, some subformulas of + which are marked with the "interp" operator (see #Z3_mk_interpolant). + + The conjunction is first checked for unsatisfiability. The result + of this check is returned in the out parameter "status". If the result + is unsat, an interpolant is computed from the refutation as in #Z3_get_interpolant + and returned as a vector of formulas. Otherwise the return value is + an empty formula. + + See #Z3_get_interpolant for a discussion of supported theories. + + The advantage of this function over #Z3_get_interpolant is that + it is not necessary to create a suitable SMT solver and generate + a proof. The disadvantage is that it is not possible to use the + solver incrementally. + + Parameters: + + \param c logical context. + \param pat an interpolation pattern + \param p parameters for solver creation + \param status returns the status of the sat check + \param model returns model if satisfiable + + Return value: status of SAT check + + def_API('Z3_compute_interpolant', INT, (_in(CONTEXT), _in(AST), _in(PARAMS), _out(AST_VECTOR), _out(MODEL))) + */ + + Z3_lbool Z3_API Z3_compute_interpolant(__in Z3_context c, + __in Z3_ast pat, + __in Z3_params p, + __out Z3_ast_vector *interp, + __out Z3_model *model); + + + /** Constant reprepresenting a root of a formula tree for tree interpolation */ +#define IZ3_ROOT SHRT_MAX + + /** This function uses Z3 to determine satisfiability of a set of + constraints. If UNSAT, an interpolant is returned, based on the + refutation generated by Z3. If SAT, a model is returned. + + If "parents" is non-null, computes a tree interpolant. The tree is + defined by the array "parents". This array maps each formula in + the tree to its parent, where formulas are indicated by their + integer index in "cnsts". The parent of formula n must have index + greater than n. The last formula is the root of the tree. Its + parent entry should be the constant IZ3_ROOT. + + If "parents" is null, computes a sequence interpolant. + + \param ctx The Z3 context. Must be generated by iz3_mk_context + \param num The number of constraints in the sequence + \param cnsts Array of constraints (AST's in context ctx) + \param parents The parents vector defining the tree structure + \param options Interpolation options (may be NULL) + \param interps Array to return interpolants (size at least num-1, may be NULL) + \param model Returns a Z3 model if constraints SAT (may be NULL) + \param labels Returns relevant labels if SAT (may be NULL) + \param incremental + + VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3 + context ctx. The model and interpolants returned are also + in this context. + + The return code is as in Z3_check_assumptions, that is, + + Z3_L_FALSE = constraints UNSAT (interpolants returned) + Z3_L_TRUE = constraints SAT (model returned) + Z3_L_UNDEF = Z3 produced no result, or interpolation not possible + + Currently, this function supports integer and boolean variables, + as well as arrays over these types, with linear arithmetic, + uninterpreted functions and quantifiers over integers (that is + AUFLIA). Interpolants are produced in AULIA. However, some + uses of array operations may cause quantifiers to appear in the + interpolants even when there are no quantifiers in the input formulas. + Although quantifiers may appear in the input formulas, Z3 may give up in + this case, returning Z3_L_UNDEF. + + If "incremental" is true, cnsts must contain exactly the set of + formulas that are currently asserted in the context. If false, + there must be no formulas currently asserted in the context. + Setting "incremental" to true makes it posisble to incrementally + add and remove constraints from the context until the context + becomes UNSAT, at which point an interpolant is computed. Caution + must be used, however. Before popping the context, if you wish to + keep the interolant formulas, you *must* preserve them by using + Z3_persist_ast. Also, if you want to simplify the interpolant + formulas using Z3_simplify, you must first pop all of the + assertions in the context (or use a different context). Otherwise, + the formulas will be simplified *relative* to these constraints, + which is almost certainly not what you want. + + + Current limitations on tree interpolants. In a tree interpolation + problem, each constant (0-ary function symbol) must occur only + along one path from root to leaf. Function symbols (of arity > 0) + are considered to have global scope (i.e., may appear in any + interpolant formula). + + def_API('Z3_interpolate', BOOL, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(PARAMS), _out_array(1, AST), _out(MODEL), _out(LITERALS), _in(UINT), _in(UINT), _in_array(9, AST))) + */ + + Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx, + __in unsigned num, + __in_ecount(num) Z3_ast *cnsts, + __in_ecount(num) unsigned *parents, + __in Z3_params options, + __out_ecount(num - 1) Z3_ast *interps, + __out Z3_model *model, + __out Z3_literals *labels, + __in unsigned incremental, + __in unsigned num_theory, + __in_ecount(num_theory) Z3_ast *theory); + + /** Return a string summarizing cumulative time used for + interpolation. This string is purely for entertainment purposes + and has no semantics. + + \param ctx The context (currently ignored) + + + def_API('Z3_interpolation_profile', STRING, (_in(CONTEXT),)) + */ + + Z3_string Z3_API Z3_interpolation_profile(__in Z3_context ctx); + + /** + \brief Read an interpolation problem from file. + + \param ctx The Z3 context. This resets the error handler of ctx. + \param filename The file name to read. + \param num Returns length of sequence. + \param cnsts Returns sequence of formulas (do not free) + \param parents Returns the parents vector (or NULL for sequence) + \param error Returns an error message in case of failure (do not free the string) + + Returns true on success. + + File formats: Currently two formats are supported, based on + SMT-LIB2. For sequence interpolants, the sequence of constraints is + represented by the sequence of "assert" commands in the file. + + For tree interpolants, one symbol of type bool is associated to + each vertex of the tree. For each vertex v there is an "assert" + of the form: + + (implies (and c1 ... cn f) v) + + where c1 .. cn are the children of v (which must precede v in the file) + and f is the formula assiciated to node v. The last formula in the + file is the root vertex, and is represented by the predicate "false". + + A solution to a tree interpolation problem can be thought of as a + valuation of the vertices that makes all the implications true + where each value is represented using the common symbols between + the formulas in the subtree and the remainder of the formulas. + + def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out_array(1, AST), _out_array(1, UINT_PTR), _in(STRING), _out(STRING), _out(UINT), _out_array(6, AST))) + + */ + + int Z3_API Z3_read_interpolation_problem(__in Z3_context ctx, + __out unsigned *num, + __out_ecount(*num) Z3_ast **cnsts, + __out_ecount(*num) unsigned **parents, + __in Z3_string filename, + __out Z3_string *error, + __out unsigned *num_theory, + __out_ecount(*num_theory) Z3_ast **theory); + + + + /** Check the correctness of an interpolant. The Z3 context must + have no constraints asserted when this call is made. That means + that after interpolating, you must first fully pop the Z3 + context before calling this. See Z3_interpolate for meaning of parameters. + + \param ctx The Z3 context. Must be generated by Z3_mk_interpolation_context + \param num The number of constraints in the sequence + \param cnsts Array of constraints (AST's in context ctx) + \param parents The parents vector (or NULL for sequence) + \param interps The interpolant to check + \param error Returns an error message if interpolant incorrect (do not free the string) + + Return value is Z3_L_TRUE if interpolant is verified, Z3_L_FALSE if + incorrect, and Z3_L_UNDEF if unknown. + + def_API('Z3_check_interpolant', INT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in_array(1, AST), _out(STRING), _in(UINT), _in_array(6, AST))) + */ + + int Z3_API Z3_check_interpolant(__in Z3_context ctx, + __in unsigned num, + __in_ecount(num) Z3_ast *cnsts, + __in_ecount(num) unsigned *parents, + __in_ecount(num - 1) Z3_ast *interps, + __out Z3_string *error, + __in unsigned num_theory, + __in_ecount(num_theory) Z3_ast *theory); + + /** Write an interpolation problem to file suitable for reading with + Z3_read_interpolation_problem. The output file is a sequence + of SMT-LIB2 format commands, suitable for reading with command-line Z3 + or other interpolating solvers. + + \param ctx The Z3 context. Must be generated by z3_mk_interpolation_context + \param num The number of constraints in the sequence + \param cnsts Array of constraints + \param parents The parents vector (or NULL for sequence) + \param filename The file name to write + + def_API('Z3_write_interpolation_problem', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(STRING), _in(UINT), _in_array(5, AST))) + */ + + void Z3_API Z3_write_interpolation_problem(__in Z3_context ctx, + __in unsigned num, + __in_ecount(num) Z3_ast *cnsts, + __in_ecount(num) unsigned *parents, + __in Z3_string filename, + __in unsigned num_theory, + __in_ecount(num_theory) Z3_ast *theory); + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif From b8b5c4d5b4576621a65d98ad09f60ca26de8dac8 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 8 Oct 2014 13:21:34 -0700 Subject: [PATCH 047/117] disable blanket validation Signed-off-by: Nikolaj Bjorner --- src/tactic/tactical.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 87974ea60..168965c17 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -1229,9 +1229,9 @@ class using_params_tactical : public unary_tactical { params_ref m_params; public: using_params_tactical(tactic * t, params_ref const & p):unary_tactical(t), m_params(p) { - param_descrs r; - collect_param_descrs(r); - p.validate(r); + //param_descrs r; + //collect_param_descrs(r); + //p.validate(r); t->updt_params(p); } From 8cf21dc2426b8be12915b8dfd59784fff87a5e14 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 8 Oct 2014 13:47:55 -0700 Subject: [PATCH 048/117] fix tactic parameter checking to API, deal with compiler warnings in api_interp Signed-off-by: Nikolaj Bjorner --- src/api/api_interp.cpp | 26 ++++++++++++++++---------- src/api/api_tactic.cpp | 3 +++ src/api/python/z3.py | 2 +- src/tactic/tactical.cpp | 3 --- src/util/params.cpp | 3 ++- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 8740e99a5..0bfb2d077 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -145,11 +145,11 @@ extern "C" { Z3_push(ctx); // so we can rewind later - for (int i = 0; i < num; i++) + for (unsigned i = 0; i < num; i++) Z3_assert_cnstr(ctx, cnsts[i]); // assert all the constraints if (theory){ - for (int i = 0; i < num_theory; i++) + for (unsigned i = 0; i < num_theory; i++) Z3_assert_cnstr(ctx, theory[i]); } @@ -180,7 +180,7 @@ extern "C" { theory); if (!incremental) - for (int i = 0; i < num - 1; i++) + for (unsigned i = 0; i < num - 1; i++) Z3_persist_ast(ctx, interps[i], 1); break; @@ -226,13 +226,13 @@ extern "C" { scoped_ptr sp((*(sf))(_m, p, false, true, false, symbol("AUFLIA"))); ptr_vector cnsts_vec(num); // get constraints in a vector - for (int i = 0; i < num; i++){ + for (unsigned i = 0; i < num; i++){ ast *a = to_ast(cnsts[i]); cnsts_vec[i] = a; } ptr_vector itp_vec(num); // get interpolants in a vector - for (int i = 0; i < num - 1; i++){ + for (unsigned i = 0; i < num - 1; i++){ ast *a = to_ast(itp[i]); itp_vec[i] = a; } @@ -240,14 +240,14 @@ extern "C" { ::vector parents_vec; // get parents in a vector if (parents){ parents_vec.resize(num); - for (int i = 0; i < num; i++) + for (unsigned i = 0; i < num; i++) parents_vec[i] = parents[i]; } ptr_vector theory_vec; // get background theory in a vector if (theory){ theory_vec.resize(num_theory); - for (int i = 0; i < num_theory; i++) + for (unsigned i = 0; i < num_theory; i++) theory_vec[i] = to_ast(theory[i]); } @@ -506,16 +506,22 @@ extern "C" { void Z3_write_interpolation_problem(Z3_context ctx, unsigned num, Z3_ast *cnsts, unsigned *parents, const char *filename, unsigned num_theory, Z3_ast *theory){ std::ofstream f(filename); if (num > 0){ +#if 0 + // Suggested shorthand: + ptr_vector cnsts_vec; + cnsts_vec.append(num, to_exprs(cnsts)); + cnsts_vec.append(num_theory, to_exprs(theory)); +#endif ptr_vector cnsts_vec(num); // get constraints in a vector - for (int i = 0; i < num; i++){ + for (unsigned i = 0; i < num; i++){ expr *a = to_expr(cnsts[i]); cnsts_vec[i] = a; } - Z3_ast tree = parents_vector_to_tree(ctx, num, cnsts, parents); - for (int i = 0; i < num_theory; i++){ + for (unsigned i = 0; i < num_theory; i++){ expr *a = to_expr(theory[i]); cnsts_vec.push_back(a); } + Z3_ast tree = parents_vector_to_tree(ctx, num, cnsts, parents); iz3pp(mk_c(ctx)->m(), cnsts_vec, to_expr(tree), f); Z3_dec_ref(ctx, tree); } diff --git a/src/api/api_tactic.cpp b/src/api/api_tactic.cpp index 911360047..7dce33971 100644 --- a/src/api/api_tactic.cpp +++ b/src/api/api_tactic.cpp @@ -222,6 +222,9 @@ extern "C" { Z3_TRY; LOG_Z3_tactic_using_params(c, t, p); RESET_ERROR_CODE(); + param_descrs r; + to_tactic_ref(t)->collect_param_descrs(r); + to_param_ref(p).validate(r); tactic * new_t = using_params(to_tactic_ref(t), to_param_ref(p)); RETURN_TACTIC(new_t); Z3_CATCH_RETURN(0); diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 1a5565ab5..82ba85472 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -4448,7 +4448,7 @@ def args2params(arguments, keywords, ctx=None): A ':' is added to the keywords, and '_' is replaced with '-' >>> args2params(['model', True, 'relevancy', 2], {'elim_and' : True}) - (params model 1 relevancy 2 elim_and 1) + (params model true relevancy 2 elim_and true) """ if __debug__: _z3_assert(len(arguments) % 2 == 0, "Argument list must have an even number of elements.") diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 168965c17..cfb4ec194 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -1229,9 +1229,6 @@ class using_params_tactical : public unary_tactical { params_ref m_params; public: using_params_tactical(tactic * t, params_ref const & p):unary_tactical(t), m_params(p) { - //param_descrs r; - //collect_param_descrs(r); - //p.validate(r); t->updt_params(p); } diff --git a/src/util/params.cpp b/src/util/params.cpp index 130b18cc9..a2609f840 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -309,7 +309,8 @@ public: p.display(strm, 2, false, false); throw default_exception(strm.str()); } - if (it->second.m_kind != expected) { + if (it->second.m_kind != expected && + !(it->second.m_kind == CPK_UINT && expected == CPK_NUMERAL)) { std::stringstream strm; strm << "Parameter " << it->first.str() << " was given argument of type "; strm << it->second.m_kind << ", expected " << expected; From bbdc8b33e0ab4153b2f3782f01025cf355a080df Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Wed, 8 Oct 2014 13:56:46 -0700 Subject: [PATCH 049/117] prevent creating some useless solvers in duality --- src/duality/duality_solver.cpp | 29 ++++++++++++++++-------- src/muz/duality/duality_dl_interface.cpp | 21 +---------------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index bbd1ebe0a..69759f9bb 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -802,6 +802,15 @@ namespace Duality { annot.Simplify(); } + bool NodeSolutionFromIndSetFull(Node *node){ + std::vector &insts = insts_of_node[node]; + for(unsigned j = 0; j < insts.size(); j++) + if(indset->Contains(insts[j])) + if(insts[j]->Annotation.IsFull()) + return true; + return false; + } + bool recursionBounded; /** See if the solution might be bounded. */ @@ -1453,16 +1462,18 @@ namespace Duality { slvr.pop(1); delete checker; #else - RPFP_caching::scoped_solver_for_edge ssfe(gen_cands_rpfp,edge,true /* models */, true /*axioms*/); - gen_cands_rpfp->Push(); - Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp); - if(gen_cands_rpfp->Check(root) != unsat){ - Candidate candidate; - ExtractCandidateFromCex(edge,gen_cands_rpfp,root,candidate); - reporter->InductionFailure(edge,candidate.Children); - candidates.push_back(candidate); + if(!NodeSolutionFromIndSetFull(edge->Parent)){ + RPFP_caching::scoped_solver_for_edge ssfe(gen_cands_rpfp,edge,true /* models */, true /*axioms*/); + gen_cands_rpfp->Push(); + Node *root = CheckerForEdgeClone(edge,gen_cands_rpfp); + if(gen_cands_rpfp->Check(root) != unsat){ + Candidate candidate; + ExtractCandidateFromCex(edge,gen_cands_rpfp,root,candidate); + reporter->InductionFailure(edge,candidate.Children); + candidates.push_back(candidate); + } + gen_cands_rpfp->Pop(1); } - gen_cands_rpfp->Pop(1); #endif } updated_nodes.clear(); diff --git a/src/muz/duality/duality_dl_interface.cpp b/src/muz/duality/duality_dl_interface.cpp index c7fa0a08f..9a6d0c633 100755 --- a/src/muz/duality/duality_dl_interface.cpp +++ b/src/muz/duality/duality_dl_interface.cpp @@ -158,26 +158,7 @@ lbool dl_interface::query(::expr * query) { vector bounds; // m_ctx.get_rules_as_formulas(rules, names); - expr_ref query_ref(m_ctx.get_manager()); - if(****){ - m_ctx.flush_add_rules(); - datalog::rule_manager& rm = m_ctx.get_rule_manager(); - rm.mk_query(query, m_ctx.get_rules()); - apply_default_transformation(m_ctx); - rule_set &rs = m_ctx.get_rules(); - if(m_ctx.get_rules().get_output_predicates().empty()) - query_ref = m_ctx.get_manager().mk_true(); - else { - query_pred = m_ctx.get_rules().get_output_predicate(); - func_decl_ref query_pred(m_ctx.get_manager()); - query_pred = m_ctx.get_rules().get_output_predicate(); - ptr_vector sorts; - unsi - - } - } - else - m_ctx.get_raw_rule_formulas(rules, names, bounds); + m_ctx.get_raw_rule_formulas(rules, names, bounds); // get all the rules as clauses std::vector &clauses = _d->clauses; From f0c63e56f3389cfa05d76509b3d77702eeab878e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 8 Oct 2014 16:27:40 -0700 Subject: [PATCH 050/117] make module parameter validation and adjustment more flexible: you can use both module qualifiers and unqualified parameters from the API at local scope Signed-off-by: Nikolaj Bjorner --- scripts/mk_util.py | 2 +- src/util/params.cpp | 66 +++++++++++++++++++++++++++++++++++---------- src/util/params.h | 7 ++--- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 411fdd1e1..4641a7b1b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1801,7 +1801,7 @@ def def_module_params(module_name, export, params, class_name=None, description= out.write(' {}\n') out.write(' static void collect_param_descrs(param_descrs & d) {\n') for param in params: - out.write(' d.insert("%s", %s, "%s", "%s");\n' % (param[0], TYPE2CPK[param[1]], param[3], pyg_default(param))) + out.write(' d.insert("%s", %s, "%s", "%s","%s");\n' % (param[0], TYPE2CPK[param[1]], param[3], pyg_default(param), module_name)) out.write(' }\n') if export: out.write(' /*\n') diff --git a/src/util/params.cpp b/src/util/params.cpp index a2609f840..cbb2b2acc 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -51,31 +51,34 @@ struct param_descrs::imp { param_kind m_kind; char const * m_descr; char const * m_default; + char const * m_module; - info(param_kind k, char const * descr, char const * def): + info(param_kind k, char const * descr, char const * def, char const* module): m_kind(k), m_descr(descr), - m_default(def) { + m_default(def), + m_module(module) { } info(): m_kind(CPK_INVALID), m_descr(0), - m_default(0) { + m_default(0), + m_module(0) { } }; dictionary m_info; svector m_names; - void insert(symbol const & name, param_kind k, char const * descr, char const * def) { + void insert(symbol const & name, param_kind k, char const * descr, char const * def, char const* module) { SASSERT(!name.is_numerical()); info i; if (m_info.find(name, i)) { SASSERT(i.m_kind == k); return; } - m_info.insert(name, info(k, descr, def)); + m_info.insert(name, info(k, descr, def, module)); m_names.push_back(name); } @@ -94,6 +97,13 @@ struct param_descrs::imp { return CPK_INVALID; } + char const* get_module(symbol const& name) const { + info i; + if (m_info.find(name, i)) + return i.m_module; + return 0; + } + char const * get_descr(symbol const & name) const { info i; if (m_info.find(name, i)) @@ -162,7 +172,7 @@ struct param_descrs::imp { dictionary::iterator it = other.m_imp->m_info.begin(); dictionary::iterator end = other.m_imp->m_info.end(); for (; it != end; ++it) { - insert(it->m_key, it->m_value.m_kind, it->m_value.m_descr, it->m_value.m_default); + insert(it->m_key, it->m_value.m_kind, it->m_value.m_descr, it->m_value.m_default, it->m_value.m_module); } } @@ -180,12 +190,12 @@ void param_descrs::copy(param_descrs & other) { m_imp->copy(other); } -void param_descrs::insert(symbol const & name, param_kind k, char const * descr, char const * def) { - m_imp->insert(name, k, descr, def); +void param_descrs::insert(symbol const & name, param_kind k, char const * descr, char const * def, char const* module) { + m_imp->insert(name, k, descr, def, module); } -void param_descrs::insert(char const * name, param_kind k, char const * descr, char const * def) { - insert(symbol(name), k, descr, def); +void param_descrs::insert(char const * name, param_kind k, char const * descr, char const * def, char const* module) { + insert(symbol(name), k, descr, def, module); } bool param_descrs::contains(char const * name) const { @@ -236,6 +246,10 @@ symbol param_descrs::get_param_name(unsigned i) const { return m_imp->get_param_name(i); } +char const* param_descrs::get_module(symbol const& name) const { + return m_imp->get_module(name); +} + void param_descrs::display(std::ostream & out, unsigned indent, bool smt2_style, bool include_descr) const { return m_imp->display(out, indent, smt2_style, include_descr); } @@ -297,11 +311,35 @@ public: void reset(symbol const & k); void reset(char const * k); - void validate(param_descrs const & p) const { - svector::const_iterator it = m_entries.begin(); - svector::const_iterator end = m_entries.end(); + bool split_name(symbol const& name, symbol & prefix, symbol & suffix) { + if (name.is_numerical()) return false; + char const* str = name.bare_str(); + char const* period = strchr(str,'.'); + if (!period) return false; + svector prefix_((unsigned)(period-str), str); + prefix_.push_back(0); + prefix = symbol(prefix_.c_ptr()); + suffix = symbol(period + 1); + return true; + } + + void validate(param_descrs const & p) { + svector::iterator it = m_entries.begin(); + svector::iterator end = m_entries.end(); + symbol suffix, prefix; for (; it != end; ++it) { param_kind expected = p.get_kind(it->first); + if (expected == CPK_INVALID && split_name(it->first, prefix, suffix)) { + expected = p.get_kind(suffix); + if (expected != CPK_INVALID) { + if (symbol(p.get_module(suffix)) == prefix) { + it->first = suffix; + } + else { + expected = CPK_INVALID; + } + } + } if (expected == CPK_INVALID) { std::stringstream strm; strm << "unknown parameter '" << it->first.str() << "'\n"; @@ -490,7 +528,7 @@ void params_ref::display(std::ostream & out, symbol const & k) const { out << "default"; } -void params_ref::validate(param_descrs const & p) const { +void params_ref::validate(param_descrs const & p) { if (m_params) m_params->validate(p); } diff --git a/src/util/params.h b/src/util/params.h index 06be486bb..f11374775 100644 --- a/src/util/params.h +++ b/src/util/params.h @@ -92,7 +92,7 @@ public: void display(std::ostream & out) const; void display_smt2(std::ostream& out, char const* module, param_descrs& module_desc) const; - void validate(param_descrs const & p) const; + void validate(param_descrs const & p); /* \brief Display the value of the given parameter. @@ -115,8 +115,8 @@ public: param_descrs(); ~param_descrs(); void copy(param_descrs & other); - void insert(char const * name, param_kind k, char const * descr, char const * def = 0); - void insert(symbol const & name, param_kind k, char const * descr, char const * def = 0); + void insert(char const * name, param_kind k, char const * descr, char const * def = 0, char const* module = 0); + void insert(symbol const & name, param_kind k, char const * descr, char const * def = 0, char const* module = 0); bool contains(char const * name) const; bool contains(symbol const & name) const; void erase(char const * name); @@ -130,6 +130,7 @@ public: void display(std::ostream & out, unsigned indent = 0, bool smt2_style=false, bool include_descr=true) const; unsigned size() const; symbol get_param_name(unsigned idx) const; + char const * get_module(symbol const& name) const; }; void insert_max_memory(param_descrs & r); From 503ad78bf38ce770c9dbd9e95ee657aaa6f509df Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 9 Oct 2014 18:08:07 +0100 Subject: [PATCH 051/117] Interpolation API bugfixes Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 17 +-- src/api/api_interp.cpp | 177 +++++++++++++------------ src/api/dotnet/InterpolationContext.cs | 63 ++------- src/api/z3_api.h | 18 ++- src/api/z3_interp.h | 106 ++------------- 5 files changed, 126 insertions(+), 255 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 791c23ddd..09c4fbe1c 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -123,7 +123,6 @@ SYMBOL = 9 PRINT_MODE = 10 ERROR_CODE = 11 DOUBLE = 12 -UINT_PTR = 13 FIRST_OBJ_ID = 100 @@ -132,28 +131,28 @@ def is_obj(ty): Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double', STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol', - PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code', UINT_PTR : 'unsigned*' + PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code' } Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong', UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double', STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol', - PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint', UINT_PTR : 'ctypes.POINTER(ctypes.c_uint)' + PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint' } # Mapping to .NET types Type2Dotnet = { VOID : 'void', VOID_PTR : 'IntPtr', INT : 'int', UINT : 'uint', INT64 : 'Int64', UINT64 : 'UInt64', DOUBLE : 'double', STRING : 'string', STRING_PTR : 'byte**', BOOL : 'int', SYMBOL : 'IntPtr', - PRINT_MODE : 'uint', ERROR_CODE : 'uint', UINT_PTR : 'uint[]'} + PRINT_MODE : 'uint', ERROR_CODE : 'uint' } # Mapping to Java types Type2Java = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', STRING : 'String', STRING_PTR : 'StringPtr', - BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int', UINT_PTR : 'int[]'} + BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int'} Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', INT64 : 'jlong', UINT64 : 'jlong', DOUBLE : 'jdouble', STRING : 'jstring', STRING_PTR : 'jobject', - BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint', UINT_PTR : 'jlong'} + BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} next_type_id = FIRST_OBJ_ID @@ -964,7 +963,6 @@ def def_API(name, result, params): tstr = type2str(ty) if sz_p_k == OUT or sz_p_k == INOUT: sz_e = ("(*a%s)" % sz) - tstr = tstr + '*' else: sz_e = ("a%s" % sz) log_c.write(" for (unsigned i = 0; i < %s; i++) { " % sz_e) @@ -978,11 +976,6 @@ def def_API(name, result, params): log_c.write(" }\n") log_c.write(" Au(%s);\n" % sz_e) exe_c.write("in.get_uint_array(%s)" % i) - elif ty == UINT_PTR: - log_c.write("P(0);") - log_c.write(" }\n") - log_c.write(" Ap(%s);\n" % sz_e) - exe_c.write("reinterpret_cast<%s>(in.get_obj_array(%s))" % (tstr, i)) else: error ("unsupported parameter for %s, %s" % (name, p)) else: diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 0bfb2d077..3e9ddc8a3 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -123,89 +123,6 @@ extern "C" { } } - Z3_lbool Z3_interpolate(Z3_context ctx, - unsigned num, - Z3_ast *cnsts, - unsigned *parents, - Z3_params options, - Z3_ast *interps, - Z3_model *model, - Z3_literals *labels, - unsigned incremental, - unsigned num_theory, - Z3_ast *theory - ){ - - - profiling::timer_start("Solve"); - - if (!incremental){ - - profiling::timer_start("Z3 assert"); - - Z3_push(ctx); // so we can rewind later - - for (unsigned i = 0; i < num; i++) - Z3_assert_cnstr(ctx, cnsts[i]); // assert all the constraints - - if (theory){ - for (unsigned i = 0; i < num_theory; i++) - Z3_assert_cnstr(ctx, theory[i]); - } - - profiling::timer_stop("Z3 assert"); - } - - - // Get a proof of unsat - - Z3_ast proof; - Z3_lbool result; - - profiling::timer_start("Z3 solving"); - result = Z3_check_assumptions(ctx, 0, 0, model, &proof, 0, 0); - profiling::timer_stop("Z3 solving"); - - switch (result) { - case Z3_L_FALSE: - - Z3_interpolate_proof(ctx, - proof, - num, - cnsts, - parents, - options, - interps, - num_theory, - theory); - - if (!incremental) - for (unsigned i = 0; i < num - 1; i++) - Z3_persist_ast(ctx, interps[i], 1); - break; - - case Z3_L_UNDEF: - if (labels) - *labels = Z3_get_relevant_labels(ctx); - break; - - case Z3_L_TRUE: - if (labels) - *labels = Z3_get_relevant_labels(ctx); - break; - } - - profiling::timer_start("Z3 pop"); - if (!incremental) - Z3_pop(ctx, 1); - profiling::timer_stop("Z3 pop"); - - profiling::timer_stop("Solve"); - - return result; - - } - static std::ostringstream itp_err; int Z3_check_interpolant(Z3_context ctx, @@ -603,7 +520,7 @@ extern "C" { } - int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast **cnsts, unsigned **parents, const char *filename, const char **error, unsigned *ret_num_theory, Z3_ast **theory){ + int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast cnsts[], unsigned parents[], const char *filename, Z3_string_ptr error, unsigned *ret_num_theory, Z3_ast theory[]){ hash_map file_params; get_file_params(filename, file_params); @@ -632,11 +549,11 @@ extern "C" { if (ret_num_theory) *ret_num_theory = num_theory; if (theory) - *theory = &read_theory[0]; + theory = &read_theory[0]; if (!parents){ *_num = num; - *cnsts = &read_cnsts[0]; + cnsts = &read_cnsts[0]; return true; } @@ -706,8 +623,8 @@ extern "C" { } *_num = num; - *cnsts = &read_cnsts[0]; - *parents = &read_parents[0]; + cnsts = &read_cnsts[0]; + parents = &read_parents[0]; return true; fail: @@ -717,3 +634,87 @@ extern "C" { } } + + +#if 0 +/** Constant reprepresenting a root of a formula tree for tree interpolation */ +#define IZ3_ROOT SHRT_MAX + +/** This function uses Z3 to determine satisfiability of a set of +constraints. If UNSAT, an interpolant is returned, based on the +refutation generated by Z3. If SAT, a model is returned. + +If "parents" is non-null, computes a tree interpolant. The tree is +defined by the array "parents". This array maps each formula in +the tree to its parent, where formulas are indicated by their +integer index in "cnsts". The parent of formula n must have index +greater than n. The last formula is the root of the tree. Its +parent entry should be the constant IZ3_ROOT. + +If "parents" is null, computes a sequence interpolant. + +\param ctx The Z3 context. Must be generated by iz3_mk_context +\param num The number of constraints in the sequence +\param cnsts Array of constraints (AST's in context ctx) +\param parents The parents vector defining the tree structure +\param options Interpolation options (may be NULL) +\param interps Array to return interpolants (size at least num-1, may be NULL) +\param model Returns a Z3 model if constraints SAT (may be NULL) +\param labels Returns relevant labels if SAT (may be NULL) +\param incremental + +VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3 +context ctx. The model and interpolants returned are also +in this context. + +The return code is as in Z3_check_assumptions, that is, + +Z3_L_FALSE = constraints UNSAT (interpolants returned) +Z3_L_TRUE = constraints SAT (model returned) +Z3_L_UNDEF = Z3 produced no result, or interpolation not possible + +Currently, this function supports integer and boolean variables, +as well as arrays over these types, with linear arithmetic, +uninterpreted functions and quantifiers over integers (that is +AUFLIA). Interpolants are produced in AULIA. However, some +uses of array operations may cause quantifiers to appear in the +interpolants even when there are no quantifiers in the input formulas. +Although quantifiers may appear in the input formulas, Z3 may give up in +this case, returning Z3_L_UNDEF. + +If "incremental" is true, cnsts must contain exactly the set of +formulas that are currently asserted in the context. If false, +there must be no formulas currently asserted in the context. +Setting "incremental" to true makes it posisble to incrementally +add and remove constraints from the context until the context +becomes UNSAT, at which point an interpolant is computed. Caution +must be used, however. Before popping the context, if you wish to +keep the interolant formulas, you *must* preserve them by using +Z3_persist_ast. Also, if you want to simplify the interpolant +formulas using Z3_simplify, you must first pop all of the +assertions in the context (or use a different context). Otherwise, +the formulas will be simplified *relative* to these constraints, +which is almost certainly not what you want. + + +Current limitations on tree interpolants. In a tree interpolation +problem, each constant (0-ary function symbol) must occur only +along one path from root to leaf. Function symbols (of arity > 0) +are considered to have global scope (i.e., may appear in any +interpolant formula). + +def_API('Z3_interpolate', BOOL, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(PARAMS), _out_array(1, AST), _out(MODEL), _out(LITERALS), _in(UINT), _in(UINT), _in_array(9, AST))) +*/ + +Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx, + __in unsigned num, + __in_ecount(num) Z3_ast *cnsts, + __in_ecount(num) unsigned *parents, + __in Z3_params options, + __out_ecount(num - 1) Z3_ast *interps, + __out Z3_model *model, + __out Z3_literals *labels, + __in unsigned incremental, + __in unsigned num_theory, + __in_ecount(num_theory) Z3_ast *theory); +#endif \ No newline at end of file diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs index 559a1bfc7..075ea29e8 100644 --- a/src/api/dotnet/InterpolationContext.cs +++ b/src/api/dotnet/InterpolationContext.cs @@ -89,47 +89,6 @@ namespace Microsoft.Z3 return (Z3_lbool)r; } - /// - /// Computes an interpolant. - /// - /// For more information on interpolation please refer - /// too the function Z3_compute_interpolant in the C/C++ API, which is - /// well documented. - Z3_lbool Interpolate(Expr[] cnsts, uint[] parents, Params options, bool incremental, Expr[] theory, out Expr[] interps, out Model model) - { - Contract.Requires(cnsts != null); - Contract.Requires(parents != null); - Contract.Requires(cnsts.Length == parents.Length); - Contract.Ensures(Contract.ValueAtReturn(out interps) != null); - Contract.Ensures(Contract.ValueAtReturn(out model) != null); - - CheckContextMatch(cnsts); - CheckContextMatch(theory); - - uint sz = (uint)cnsts.Length; - - IntPtr[] ni = new IntPtr[sz - 1]; - IntPtr nm = IntPtr.Zero; - IntPtr z = IntPtr.Zero; - - int r = Native.Z3_interpolate(nCtx, - sz, Expr.ArrayToNative(cnsts), parents, - options.NativeObject, - out ni, - ref nm, - ref z, // Z3_lterals are deprecated. - (uint)(incremental ? 1 : 0), - (uint)theory.Length, Expr.ArrayToNative(theory)); - - interps = new Expr[sz - 1]; - for (uint i = 0; i < sz - 1; i++) - interps[i] = Expr.Create(this, ni[i]); - - model = new Model(this, nm); - - return (Z3_lbool)r; - } - /// /// Return a string summarizing cumulative time used for interpolation. /// @@ -150,7 +109,7 @@ namespace Microsoft.Z3 public int CheckInterpolant(Expr[] cnsts, uint[] parents, Expr[] interps, out string error, Expr[] theory) { Contract.Requires(cnsts.Length == parents.Length); - Contract.Requires(cnsts.Length == interps.Length+1); + Contract.Requires(cnsts.Length == interps.Length + 1); IntPtr n_err_str; int r = Native.Z3_check_interpolant(nCtx, (uint)cnsts.Length, @@ -170,25 +129,27 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the function Z3_read_interpolation_problem in the C/C++ API, which is /// well documented. - public int ReadInterpolationProblem(string filename, out Expr[] cnsts, out uint[] parents, out string error, out Expr[] theory) + public int ReadInterpolationProblem(string filename, out Expr[] cnsts, ref uint[] parents, out string error, out Expr[] theory) { uint num = 0, num_theory = 0; - IntPtr[] n_cnsts; - IntPtr[] n_theory; + IntPtr n_cnsts = new IntPtr(); + IntPtr n_theory = new IntPtr(); IntPtr n_err_str; - uint[][] n_parents; - int r = Native.Z3_read_interpolation_problem(nCtx, ref num, out n_cnsts, out n_parents, filename, out n_err_str, ref num_theory, out n_theory); + int r = Native.Z3_read_interpolation_problem(nCtx, ref num, ref n_cnsts, out parents, filename, out n_err_str, ref num_theory, ref n_theory); error = Marshal.PtrToStringAnsi(n_err_str); cnsts = new Expr[num]; parents = new uint[num]; - theory = new Expr[num_theory]; + theory = new Expr[num_theory]; for (int i = 0; i < num; i++) { - cnsts[i] = Expr.Create(this, n_cnsts[i]); - parents[i] = n_parents[0][i]; + IntPtr ce = new IntPtr(n_cnsts.ToInt64() + (IntPtr.Size * i)); + cnsts[i] = Expr.Create(this, ce); } for (int i = 0; i < num_theory; i++) - theory[i] = Expr.Create(this, n_theory[i]); + { + IntPtr te = new IntPtr(n_theory.ToInt64() + (IntPtr.Size * i)); + theory[i] = Expr.Create(this, te); + } return r; } diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 41ccf532e..04e2d38af 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1779,7 +1779,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_tuple_sort(__in Z3_context c, __in Z3_symbol mk_tuple_name, __in unsigned num_fields, - __in_ecount(num_fields) Z3_symbol const field_names[], + __in_ecount(num_fields) Z3_symbol const field_names[], __in_ecount(num_fields) Z3_sort const field_sorts[], __out Z3_func_decl * mk_tuple_decl, __out_ecount(num_fields) Z3_func_decl proj_decl[]); @@ -4907,8 +4907,7 @@ END_MLAPI_EXCLUDE __in_ecount(num_sorts) Z3_sort const sorts[], __in unsigned num_decls, __in_ecount(num_decls) Z3_symbol const decl_names[], - __in_ecount(num_decls) Z3_func_decl const decls[] - ); + __in_ecount(num_decls) Z3_func_decl const decls[]); /** \brief Similar to #Z3_parse_smtlib2_string, but reads the benchmark from a file. @@ -4917,13 +4916,12 @@ END_MLAPI_EXCLUDE */ Z3_ast Z3_API Z3_parse_smtlib2_file(__in Z3_context c, __in Z3_string file_name, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol const sort_names[], - __in_ecount(num_sorts) Z3_sort const sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol const decl_names[], - __in_ecount(num_decls) Z3_func_decl const decls[] - ); + __in unsigned num_sorts, + __in_ecount(num_sorts) Z3_symbol const sort_names[], + __in_ecount(num_sorts) Z3_sort const sorts[], + __in unsigned num_decls, + __in_ecount(num_decls) Z3_symbol const decl_names[], + __in_ecount(num_decls) Z3_func_decl const decls[]); #ifdef ML4only #include diff --git a/src/api/z3_interp.h b/src/api/z3_interp.h index 1aac13b6e..88ba83e2d 100644 --- a/src/api/z3_interp.h +++ b/src/api/z3_interp.h @@ -163,88 +163,6 @@ extern "C" { __out Z3_ast_vector *interp, __out Z3_model *model); - - /** Constant reprepresenting a root of a formula tree for tree interpolation */ -#define IZ3_ROOT SHRT_MAX - - /** This function uses Z3 to determine satisfiability of a set of - constraints. If UNSAT, an interpolant is returned, based on the - refutation generated by Z3. If SAT, a model is returned. - - If "parents" is non-null, computes a tree interpolant. The tree is - defined by the array "parents". This array maps each formula in - the tree to its parent, where formulas are indicated by their - integer index in "cnsts". The parent of formula n must have index - greater than n. The last formula is the root of the tree. Its - parent entry should be the constant IZ3_ROOT. - - If "parents" is null, computes a sequence interpolant. - - \param ctx The Z3 context. Must be generated by iz3_mk_context - \param num The number of constraints in the sequence - \param cnsts Array of constraints (AST's in context ctx) - \param parents The parents vector defining the tree structure - \param options Interpolation options (may be NULL) - \param interps Array to return interpolants (size at least num-1, may be NULL) - \param model Returns a Z3 model if constraints SAT (may be NULL) - \param labels Returns relevant labels if SAT (may be NULL) - \param incremental - - VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3 - context ctx. The model and interpolants returned are also - in this context. - - The return code is as in Z3_check_assumptions, that is, - - Z3_L_FALSE = constraints UNSAT (interpolants returned) - Z3_L_TRUE = constraints SAT (model returned) - Z3_L_UNDEF = Z3 produced no result, or interpolation not possible - - Currently, this function supports integer and boolean variables, - as well as arrays over these types, with linear arithmetic, - uninterpreted functions and quantifiers over integers (that is - AUFLIA). Interpolants are produced in AULIA. However, some - uses of array operations may cause quantifiers to appear in the - interpolants even when there are no quantifiers in the input formulas. - Although quantifiers may appear in the input formulas, Z3 may give up in - this case, returning Z3_L_UNDEF. - - If "incremental" is true, cnsts must contain exactly the set of - formulas that are currently asserted in the context. If false, - there must be no formulas currently asserted in the context. - Setting "incremental" to true makes it posisble to incrementally - add and remove constraints from the context until the context - becomes UNSAT, at which point an interpolant is computed. Caution - must be used, however. Before popping the context, if you wish to - keep the interolant formulas, you *must* preserve them by using - Z3_persist_ast. Also, if you want to simplify the interpolant - formulas using Z3_simplify, you must first pop all of the - assertions in the context (or use a different context). Otherwise, - the formulas will be simplified *relative* to these constraints, - which is almost certainly not what you want. - - - Current limitations on tree interpolants. In a tree interpolation - problem, each constant (0-ary function symbol) must occur only - along one path from root to leaf. Function symbols (of arity > 0) - are considered to have global scope (i.e., may appear in any - interpolant formula). - - def_API('Z3_interpolate', BOOL, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(PARAMS), _out_array(1, AST), _out(MODEL), _out(LITERALS), _in(UINT), _in(UINT), _in_array(9, AST))) - */ - - Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx, - __in unsigned num, - __in_ecount(num) Z3_ast *cnsts, - __in_ecount(num) unsigned *parents, - __in Z3_params options, - __out_ecount(num - 1) Z3_ast *interps, - __out Z3_model *model, - __out Z3_literals *labels, - __in unsigned incremental, - __in unsigned num_theory, - __in_ecount(num_theory) Z3_ast *theory); - /** Return a string summarizing cumulative time used for interpolation. This string is purely for entertainment purposes and has no semantics. @@ -288,18 +206,18 @@ extern "C" { where each value is represented using the common symbols between the formulas in the subtree and the remainder of the formulas. - def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out_array(1, AST), _out_array(1, UINT_PTR), _in(STRING), _out(STRING), _out(UINT), _out_array(6, AST))) + def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out(AST), _out_array(1, UINT), _in(STRING), _out(STRING), _out(UINT), _out(AST))) */ int Z3_API Z3_read_interpolation_problem(__in Z3_context ctx, __out unsigned *num, - __out_ecount(*num) Z3_ast **cnsts, - __out_ecount(*num) unsigned **parents, + __out Z3_ast *cnsts, + __out unsigned parents[], __in Z3_string filename, - __out Z3_string *error, + __out_opt Z3_string_ptr error, __out unsigned *num_theory, - __out_ecount(*num_theory) Z3_ast **theory); + __out Z3_ast theory[]); @@ -323,12 +241,12 @@ extern "C" { int Z3_API Z3_check_interpolant(__in Z3_context ctx, __in unsigned num, - __in_ecount(num) Z3_ast *cnsts, - __in_ecount(num) unsigned *parents, + __in_ecount(num) Z3_ast cnsts[], + __in_ecount(num) unsigned parents[], __in_ecount(num - 1) Z3_ast *interps, - __out Z3_string *error, + __out_opt Z3_string_ptr error, __in unsigned num_theory, - __in_ecount(num_theory) Z3_ast *theory); + __in_ecount(num_theory) Z3_ast theory[]); /** Write an interpolation problem to file suitable for reading with Z3_read_interpolation_problem. The output file is a sequence @@ -346,11 +264,11 @@ extern "C" { void Z3_API Z3_write_interpolation_problem(__in Z3_context ctx, __in unsigned num, - __in_ecount(num) Z3_ast *cnsts, - __in_ecount(num) unsigned *parents, + __in_ecount(num) Z3_ast cnsts[], + __in_ecount(num) unsigned parents[], __in Z3_string filename, __in unsigned num_theory, - __in_ecount(num_theory) Z3_ast *theory); + __in_ecount(num_theory) Z3_ast theory[]); #ifdef __cplusplus }; From 1c1351a0644cfa567becd8447568617b05d02600 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 9 Oct 2014 18:11:42 +0100 Subject: [PATCH 052/117] Interpolation .NET API bugfixes Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/InterpolationContext.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs index 075ea29e8..fbedadffe 100644 --- a/src/api/dotnet/InterpolationContext.cs +++ b/src/api/dotnet/InterpolationContext.cs @@ -159,9 +159,10 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the function Z3_write_interpolation_problem in the C/C++ API, which is /// well documented. - public void WriteInterpolationProblem(string filename, Expr[] cnsts, int[] parents, string error, Expr[] theory) + public void WriteInterpolationProblem(string filename, Expr[] cnsts, uint[] parents, string error, Expr[] theory) { Contract.Requires(cnsts.Length == parents.Length); + Native.Z3_write_interpolation_problem(nCtx, (uint)cnsts.Length, Expr.ArrayToNative(cnsts), parents, error, (uint)theory.Length, Expr.ArrayToNative(theory)); } } } From bcd2d935a99526b561033aff09bcd90b666318aa Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 9 Oct 2014 10:18:46 -0700 Subject: [PATCH 053/117] enable modular parameters from the parser Signed-off-by: Nikolaj Bjorner --- src/cmd_context/tactic_cmds.cpp | 2 +- src/util/params.cpp | 57 ++++++++++++++++++++------------- src/util/params.h | 1 + 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/cmd_context/tactic_cmds.cpp b/src/cmd_context/tactic_cmds.cpp index 27014bca9..75d56928e 100644 --- a/src/cmd_context/tactic_cmds.cpp +++ b/src/cmd_context/tactic_cmds.cpp @@ -500,7 +500,7 @@ static tactic * mk_using_params(cmd_context & ctx, sexpr * n) { symbol param_name = symbol(norm_param_name(c->get_symbol()).c_str()); c = n->get_child(i); i++; - switch (descrs.get_kind(param_name)) { + switch (descrs.get_kind_in_module(param_name)) { case CPK_INVALID: throw cmd_exception("invalid using-params combinator, unknown parameter ", param_name, c->get_line(), c->get_pos()); case CPK_BOOL: diff --git a/src/util/params.cpp b/src/util/params.cpp index cbb2b2acc..b869f8e3d 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -97,6 +97,35 @@ struct param_descrs::imp { return CPK_INVALID; } + bool split_name(symbol const& name, symbol & prefix, symbol & suffix) const { + if (name.is_numerical()) return false; + char const* str = name.bare_str(); + char const* period = strchr(str,'.'); + if (!period) return false; + svector prefix_((unsigned)(period-str), str); + prefix_.push_back(0); + prefix = symbol(prefix_.c_ptr()); + suffix = symbol(period + 1); + return true; + } + + param_kind get_kind_in_module(symbol & name) const { + param_kind k = get_kind(name); + symbol prefix, suffix; + if (k == CPK_INVALID && split_name(name, prefix, suffix)) { + k = get_kind(suffix); + if (k != CPK_INVALID) { + if (symbol(get_module(suffix)) == prefix) { + name = suffix; + } + else { + k = CPK_INVALID; + } + } + } + return k; + } + char const* get_module(symbol const& name) const { info i; if (m_info.find(name, i)) @@ -230,6 +259,10 @@ void param_descrs::erase(char const * name) { erase(symbol(name)); } +param_kind param_descrs::get_kind_in_module(symbol & name) const { + return m_imp->get_kind_in_module(name); +} + param_kind param_descrs::get_kind(symbol const & name) const { return m_imp->get_kind(name); } @@ -311,35 +344,13 @@ public: void reset(symbol const & k); void reset(char const * k); - bool split_name(symbol const& name, symbol & prefix, symbol & suffix) { - if (name.is_numerical()) return false; - char const* str = name.bare_str(); - char const* period = strchr(str,'.'); - if (!period) return false; - svector prefix_((unsigned)(period-str), str); - prefix_.push_back(0); - prefix = symbol(prefix_.c_ptr()); - suffix = symbol(period + 1); - return true; - } void validate(param_descrs const & p) { svector::iterator it = m_entries.begin(); svector::iterator end = m_entries.end(); symbol suffix, prefix; for (; it != end; ++it) { - param_kind expected = p.get_kind(it->first); - if (expected == CPK_INVALID && split_name(it->first, prefix, suffix)) { - expected = p.get_kind(suffix); - if (expected != CPK_INVALID) { - if (symbol(p.get_module(suffix)) == prefix) { - it->first = suffix; - } - else { - expected = CPK_INVALID; - } - } - } + param_kind expected = p.get_kind_in_module(it->first); if (expected == CPK_INVALID) { std::stringstream strm; strm << "unknown parameter '" << it->first.str() << "'\n"; diff --git a/src/util/params.h b/src/util/params.h index f11374775..e4a2b3693 100644 --- a/src/util/params.h +++ b/src/util/params.h @@ -123,6 +123,7 @@ public: void erase(symbol const & name); param_kind get_kind(char const * name) const; param_kind get_kind(symbol const & name) const; + param_kind get_kind_in_module(symbol & name) const; char const * get_descr(char const * name) const; char const * get_descr(symbol const & name) const; char const * get_default(char const * name) const; From 9b8406c7171b0687a2cb048020374d272965e16b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 10 Oct 2014 11:41:21 +0100 Subject: [PATCH 054/117] Resolved interpolation API issues. Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 40 ++++++++++++++++++++++---- src/api/api_interp.cpp | 10 +++---- src/api/dotnet/InterpolationContext.cs | 18 ++++-------- src/api/z3_interp.h | 8 +++--- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 09c4fbe1c..2ffd95e3d 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -108,6 +108,7 @@ INOUT = 2 IN_ARRAY = 3 OUT_ARRAY = 4 INOUT_ARRAY = 5 +OUT_MANAGED_ARRAY = 6 # Primitive Types VOID = 0 @@ -224,6 +225,10 @@ def _out_array2(cap, sz, ty): def _inout_array(sz, ty): return (INOUT_ARRAY, ty, sz, sz); +def _out_managed_array(sz,ty): + return (OUT_MANAGED_ARRAY, ty, 0, sz) + + def param_kind(p): return p[0] @@ -254,11 +259,11 @@ def param2dotnet(p): return "out IntPtr" else: return "[In, Out] ref %s" % type2dotnet(param_type(p)) - if k == IN_ARRAY: + elif k == IN_ARRAY: return "[In] %s[]" % type2dotnet(param_type(p)) - if k == INOUT_ARRAY: + elif k == INOUT_ARRAY: return "[In, Out] %s[]" % type2dotnet(param_type(p)) - if k == OUT_ARRAY: + elif k == OUT_ARRAY or k == OUT_MANAGED_ARRAY: return "[Out] out %s[]" % type2dotnet(param_type(p)) else: return type2dotnet(param_type(p)) @@ -268,7 +273,7 @@ def param2java(p): if k == OUT: if param_type(p) == INT or param_type(p) == UINT: return "IntPtr" - elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID: + elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) == VOID_PTR or param_type(p) >= FIRST_OBJ_ID: return "LongPtr" elif param_type(p) == STRING: return "StringPtr" @@ -466,7 +471,7 @@ def mk_dotnet_wrappers(): dotnet.write('out '); else: dotnet.write('ref ') - elif param_kind(param) == OUT_ARRAY: + elif param_kind(param) == OUT_ARRAY or param_kind(param) == OUT_MANAGED_ARRAY: dotnet.write('out '); dotnet.write('a%d' % i) i = i + 1 @@ -678,9 +683,11 @@ def mk_java(): if param_type(param) == INT or param_type(param) == UINT: java_wrapper.write(' jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) else: - java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) + java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i)) elif k == IN and param_type(param) == STRING: java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i)) + elif k == OUT_MANAGED_ARRAY: + java_wrapper.write(' %s * _a%s = 0;\n' % (type2str(param_type(param)), i)) i = i + 1 # invoke procedure java_wrapper.write(' ') @@ -699,6 +706,8 @@ def mk_java(): java_wrapper.write('&_a%s' % i) elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: java_wrapper.write('_a%s' % i) + elif k == OUT_MANAGED_ARRAY: + java_wrapper.write('&_a%s' % i) elif k == IN and param_type(param) == STRING: java_wrapper.write('_a%s' % i) else: @@ -734,6 +743,8 @@ def mk_java(): java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n') java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i)) java_wrapper.write(' }\n') + elif k == OUT_MANAGED_ARRAY: + java_wrapper.write(' *(jlong**)a%s = (jlong*)_a%s;\n' % (i, i)) i = i + 1 # return if result == STRING: @@ -934,6 +945,9 @@ def def_API(name, result, params): elif ty == INT64: log_c.write(" I(0);\n") exe_c.write("in.get_int64_addr(%s)" % i) + elif ty == VOID_PTR: + log_c.write(" P(0);\n") + exe_c.write("in.get_obj_addr(%s)" % i) else: error("unsupported parameter for %s, %s" % (name, p)) elif kind == IN_ARRAY or kind == INOUT_ARRAY: @@ -978,6 +992,20 @@ def def_API(name, result, params): exe_c.write("in.get_uint_array(%s)" % i) else: error ("unsupported parameter for %s, %s" % (name, p)) + elif kind == OUT_MANAGED_ARRAY: + sz = param_array_size_pos(p) + sz_p = params[sz] + sz_p_k = param_kind(sz_p) + tstr = type2str(ty) + if sz_p_k == OUT or sz_p_k == INOUT: + sz_e = ("(*a%s)" % sz) + else: + sz_e = ("a%s" % sz) + log_c.write(" for (unsigned i = 0; i < %s; i++) { " % sz_e) + log_c.write("P(0);") + log_c.write(" }\n") + log_c.write(" Ap(%s);\n" % sz_e) + exe_c.write("reinterpret_cast<%s**>(in.get_obj_array(%s))" % (tstr, i)) else: error ("unsupported parameter for %s, %s" % (name, p)) i = i + 1 diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 3e9ddc8a3..dbf68da38 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -520,7 +520,7 @@ extern "C" { } - int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast cnsts[], unsigned parents[], const char *filename, Z3_string_ptr error, unsigned *ret_num_theory, Z3_ast theory[]){ + int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast *cnsts[], unsigned *parents[], const char *filename, Z3_string_ptr error, unsigned *ret_num_theory, Z3_ast *theory[]){ hash_map file_params; get_file_params(filename, file_params); @@ -549,11 +549,11 @@ extern "C" { if (ret_num_theory) *ret_num_theory = num_theory; if (theory) - theory = &read_theory[0]; + *theory = &read_theory[0]; if (!parents){ *_num = num; - cnsts = &read_cnsts[0]; + *cnsts = &read_cnsts[0]; return true; } @@ -623,8 +623,8 @@ extern "C" { } *_num = num; - cnsts = &read_cnsts[0]; - parents = &read_parents[0]; + *cnsts = &read_cnsts[0]; + *parents = &read_parents[0]; return true; fail: diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs index fbedadffe..8ba5fe773 100644 --- a/src/api/dotnet/InterpolationContext.cs +++ b/src/api/dotnet/InterpolationContext.cs @@ -129,27 +129,21 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the function Z3_read_interpolation_problem in the C/C++ API, which is /// well documented. - public int ReadInterpolationProblem(string filename, out Expr[] cnsts, ref uint[] parents, out string error, out Expr[] theory) + public int ReadInterpolationProblem(string filename, out Expr[] cnsts, out uint[] parents, out string error, out Expr[] theory) { uint num = 0, num_theory = 0; - IntPtr n_cnsts = new IntPtr(); - IntPtr n_theory = new IntPtr(); + IntPtr[] n_cnsts; + IntPtr[] n_theory; IntPtr n_err_str; - int r = Native.Z3_read_interpolation_problem(nCtx, ref num, ref n_cnsts, out parents, filename, out n_err_str, ref num_theory, ref n_theory); + int r = Native.Z3_read_interpolation_problem(nCtx, ref num, out n_cnsts, out parents, filename, out n_err_str, ref num_theory, out n_theory); error = Marshal.PtrToStringAnsi(n_err_str); cnsts = new Expr[num]; parents = new uint[num]; theory = new Expr[num_theory]; for (int i = 0; i < num; i++) - { - IntPtr ce = new IntPtr(n_cnsts.ToInt64() + (IntPtr.Size * i)); - cnsts[i] = Expr.Create(this, ce); - } + cnsts[i] = Expr.Create(this, n_cnsts[i]); for (int i = 0; i < num_theory; i++) - { - IntPtr te = new IntPtr(n_theory.ToInt64() + (IntPtr.Size * i)); - theory[i] = Expr.Create(this, te); - } + theory[i] = Expr.Create(this, n_theory[i]); return r; } diff --git a/src/api/z3_interp.h b/src/api/z3_interp.h index 88ba83e2d..729851988 100644 --- a/src/api/z3_interp.h +++ b/src/api/z3_interp.h @@ -206,18 +206,18 @@ extern "C" { where each value is represented using the common symbols between the formulas in the subtree and the remainder of the formulas. - def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out(AST), _out_array(1, UINT), _in(STRING), _out(STRING), _out(UINT), _out(AST))) + def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out_managed_array(1, AST), _out_managed_array(1, UINT), _in(STRING), _out(STRING), _out(UINT), _out_managed_array(6, AST))) */ int Z3_API Z3_read_interpolation_problem(__in Z3_context ctx, __out unsigned *num, - __out Z3_ast *cnsts, - __out unsigned parents[], + __out Z3_ast *cnsts[], + __out unsigned *parents[], __in Z3_string filename, __out_opt Z3_string_ptr error, __out unsigned *num_theory, - __out Z3_ast theory[]); + __out Z3_ast *theory[]); From 3e7c95db6b57aab3e657c928f6a07e24c1f16a62 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 10 Oct 2014 12:34:17 +0100 Subject: [PATCH 055/117] Interpolation API bugfixes Added Interpolation to the Java API Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 9 +- src/api/dotnet/InterpolationContext.cs | 4 +- src/api/java/InterpolationContext.java | 169 +++++++++++++++++++++++++ 3 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 src/api/java/InterpolationContext.java diff --git a/scripts/update_api.py b/scripts/update_api.py index 2ffd95e3d..837c2e1f4 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -281,8 +281,13 @@ def param2java(p): print("ERROR: unreachable code") assert(False) exit(1) - if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: + elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: return "%s[]" % type2java(param_type(p)) + elif k == OUT_MANAGED_ARRAY: + if param_type(p) == UINT: + return "UIntArrayPtr" + else: + return "ObjArrayPtr" else: return type2java(param_type(p)) @@ -529,6 +534,8 @@ def mk_java(): java_native.write(' public static class IntPtr { public int value; }\n') java_native.write(' public static class LongPtr { public long value; }\n') java_native.write(' public static class StringPtr { public String value; }\n') + java_native.write(' public static class ObjArrayPtr { public long[] value; }\n') + java_native.write(' public static class UIntArrayPtr { public int[] value; }\n') java_native.write(' public static native void setInternalErrorHandler(long ctx);\n\n') if IS_WINDOWS or os.uname()[0]=="CYGWIN": java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name) diff --git a/src/api/dotnet/InterpolationContext.cs b/src/api/dotnet/InterpolationContext.cs index 8ba5fe773..b5ada1bbd 100644 --- a/src/api/dotnet/InterpolationContext.cs +++ b/src/api/dotnet/InterpolationContext.cs @@ -153,10 +153,10 @@ namespace Microsoft.Z3 /// For more information on interpolation please refer /// too the function Z3_write_interpolation_problem in the C/C++ API, which is /// well documented. - public void WriteInterpolationProblem(string filename, Expr[] cnsts, uint[] parents, string error, Expr[] theory) + public void WriteInterpolationProblem(string filename, Expr[] cnsts, uint[] parents, Expr[] theory) { Contract.Requires(cnsts.Length == parents.Length); - Native.Z3_write_interpolation_problem(nCtx, (uint)cnsts.Length, Expr.ArrayToNative(cnsts), parents, error, (uint)theory.Length, Expr.ArrayToNative(theory)); + Native.Z3_write_interpolation_problem(nCtx, (uint)cnsts.Length, Expr.ArrayToNative(cnsts), parents, filename, (uint)theory.Length, Expr.ArrayToNative(theory)); } } } diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java new file mode 100644 index 000000000..067871324 --- /dev/null +++ b/src/api/java/InterpolationContext.java @@ -0,0 +1,169 @@ +/** + * + */ +package com.microsoft.z3; + +import java.util.Map; +import java.lang.String; + +import com.microsoft.z3.Native.IntPtr; +import com.microsoft.z3.Native.UIntArrayPtr; +import com.microsoft.z3.enumerations.Z3_lbool; + +/** + * The InterpolationContext is suitable for generation of interpolants. + * + * For more information on interpolation please refer + * too the C/C++ API, which is well documented. + **/ +public class InterpolationContext extends Context +{ + /** + * Constructor. + **/ + public InterpolationContext() throws Z3Exception + { + m_ctx = Native.mkInterpolationContext(0); + initContext(); + } + + /** + * Constructor. + * + * + **/ + public InterpolationContext(Map settings) throws Z3Exception + { + long cfg = Native.mkConfig(); + for (Map.Entry kv : settings.entrySet()) + Native.setParamValue(cfg, kv.getKey(), kv.getValue()); + m_ctx = Native.mkInterpolationContext(cfg); + Native.delConfig(cfg); + initContext(); + } + + /** + * Create an expression that marks a formula position for interpolation. + * @throws Z3Exception + **/ + public BoolExpr MkInterpolant(BoolExpr a) throws Z3Exception + { + checkContextMatch(a); + return new BoolExpr(this, Native.mkInterpolant(nCtx(), a.getNativeObject())); + } + + /** + * Computes an interpolant. + * For more information on interpolation please refer + * too the function Z3_get_interpolant in the C/C++ API, which is + * well documented. + * @throws Z3Exception + **/ + Expr[] GetInterpolant(Expr pf, Expr pat, Params p) throws Z3Exception + { + checkContextMatch(pf); + checkContextMatch(pat); + checkContextMatch(p); + + ASTVector seq = new ASTVector(this, Native.getInterpolant(nCtx(), pf.getNativeObject(), pat.getNativeObject(), p.getNativeObject())); + int n = seq.size(); + Expr[] res = new Expr[n]; + for (int i = 0; i < n; i++) + res[i] = Expr.create(this, seq.get(i).getNativeObject()); + return res; + } + + /** + * Computes an interpolant. + * For more information on interpolation please refer + * too the function Z3_compute_interpolant in the C/C++ API, which is + * well documented. + * @throws Z3Exception + **/ + Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) throws Z3Exception + { + checkContextMatch(pat); + checkContextMatch(p); + + Native.LongPtr n_i = new Native.LongPtr(); + Native.LongPtr n_m = new Native.LongPtr(); + int r = Native.computeInterpolant(nCtx(), pat.getNativeObject(), p.getNativeObject(), n_i, n_m); + interp = new ASTVector(this, n_i.value); + model = new Model(this, n_m.value); + return Z3_lbool.fromInt(r); + } + + /// + /// Return a string summarizing cumulative time used for interpolation. + /// + /// For more information on interpolation please refer + /// too the function Z3_interpolation_profile in the C/C++ API, which is + /// well documented. + public String InterpolationProfile() throws Z3Exception + { + return Native.interpolationProfile(nCtx()); + } + + /// + /// Checks the correctness of an interpolant. + /// + /// For more information on interpolation please refer + /// too the function Z3_check_interpolant in the C/C++ API, which is + /// well documented. + public int CheckInterpolant(Expr[] cnsts, int[] parents, Expr[] interps, String error, Expr[] theory) throws Z3Exception + { + Native.StringPtr n_err_str = new Native.StringPtr(); + int r = Native.checkInterpolant(nCtx(), + cnsts.length, + Expr.arrayToNative(cnsts), + parents, + Expr.arrayToNative(interps), + n_err_str, + theory.length, + Expr.arrayToNative(theory)); + error = n_err_str.value; + return r; + } + + /// + /// Reads an interpolation problem from a file. + /// + /// For more information on interpolation please refer + /// too the function Z3_read_interpolation_problem in the C/C++ API, which is + /// well documented. + public int ReadInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception + { + Native.IntPtr n_num = new Native.IntPtr(); + Native.IntPtr n_num_theory = new Native.IntPtr(); + Native.ObjArrayPtr n_cnsts = new Native.ObjArrayPtr(); + Native.UIntArrayPtr n_parents = new Native.UIntArrayPtr(); + Native.ObjArrayPtr n_theory = new Native.ObjArrayPtr(); + Native.StringPtr n_err_str = new Native.StringPtr(); + int r = Native.readInterpolationProblem(nCtx(), n_num, n_cnsts, n_parents, filename, n_err_str, n_num_theory, n_theory); + int num = n_num.value; + int num_theory = n_num_theory.value; + error = n_err_str.value; + cnsts = new Expr[num]; + parents = new int[num]; + theory = new Expr[num_theory]; + for (int i = 0; i < num; i++) + { + cnsts[i] = Expr.create(this, n_cnsts.value[i]); + parents[i] = n_parents.value[i]; + } + for (int i = 0; i < num_theory; i++) + theory[i] = Expr.create(this, n_theory.value[i]); + return r; + } + + /// + /// Writes an interpolation problem to a file. + /// + /// For more information on interpolation please refer + /// too the function Z3_write_interpolation_problem in the C/C++ API, which is + /// well documented. + public void WriteInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception + { + Native.writeInterpolationProblem(nCtx(), cnsts.length, Expr.arrayToNative(cnsts), parents, filename, theory.length, Expr.arrayToNative(theory)); + } +} From 342a23cfcbff0dceedaecd6a1ca00e2ca88c8482 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 10 Oct 2014 13:00:41 +0100 Subject: [PATCH 056/117] C++ API bugfix Signed-off-by: Christoph M. Wintersteiger --- src/api/c++/z3++.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 20100d124..c35208d86 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -1432,12 +1432,12 @@ namespace z3 { t1.check_error(); return tactic(t1.ctx(), r); } - friend tactic repeat(tactic const & t, unsigned max=UINT_MAX); + friend tactic repeat(tactic const & t, unsigned max); friend tactic with(tactic const & t, params const & p); friend tactic try_for(tactic const & t, unsigned ms); }; - inline tactic repeat(tactic const & t, unsigned max) { + inline tactic repeat(tactic const & t, unsigned max=UINT_MAX) { Z3_tactic r = Z3_tactic_repeat(t.ctx(), t, max); t.check_error(); return tactic(t.ctx(), r); From 0451a605f43065edccdfd1f091c6414cd1b297f8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 10 Oct 2014 13:05:11 +0100 Subject: [PATCH 057/117] Interpolation example bugfixes Signed-off-by: Christoph M. Wintersteiger --- examples/interp/iz3.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/interp/iz3.cpp b/examples/interp/iz3.cpp index fa7d8b896..26f62976f 100755 --- a/examples/interp/iz3.cpp +++ b/examples/interp/iz3.cpp @@ -90,12 +90,12 @@ int main(int argc, const char **argv) { /* Read an interpolation problem */ - int num; + unsigned num; Z3_ast *constraints; - int *parents = 0; + unsigned *parents = 0; const char *error; bool ok; - int num_theory; + unsigned num_theory; Z3_ast *theory; ok = Z3_read_interpolation_problem(ctx, &num, &constraints, tree_mode ? &parents : 0, filename, &error, &num_theory, &theory); @@ -144,7 +144,7 @@ int main(int argc, const char **argv) { if(!incremental_mode){ /* In non-incremental mode, we just pass the constraints. */ - result = Z3_interpolate(ctx, num, constraints, (unsigned int *)parents, options, interpolants, &model, 0, false, num_theory, theory); + result = Z3_interpolate(ctx, num, constraints, parents, options, interpolants, &model, 0, false, num_theory, theory); } else { @@ -165,7 +165,7 @@ int main(int argc, const char **argv) { for(int i = 0; i < num; i++){ asserted[i] = constraints[i]; Z3_assert_cnstr(ctx,constraints[i]); // assert one constraint - result = Z3_interpolate(ctx, num, &asserted[0], (unsigned int *)parents, options, interpolants, &model, 0, true, 0, 0); + result = Z3_interpolate(ctx, num, &asserted[0], parents, options, interpolants, &model, 0, true, 0, 0); if(result == Z3_L_FALSE){ for(unsigned j = 0; j < num-1; j++) /* Since we want the interpolant formulas to survive a "pop", we From e8b04790cf20688b5ef829912fcf8afa6da3f8dc Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sat, 11 Oct 2014 09:43:55 -0700 Subject: [PATCH 058/117] fix build by disabling removed API call from interpolation sample Signed-off-by: Nikolaj Bjorner --- examples/interp/iz3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/interp/iz3.cpp b/examples/interp/iz3.cpp index 26f62976f..6d631ebc9 100755 --- a/examples/interp/iz3.cpp +++ b/examples/interp/iz3.cpp @@ -144,7 +144,7 @@ int main(int argc, const char **argv) { if(!incremental_mode){ /* In non-incremental mode, we just pass the constraints. */ - result = Z3_interpolate(ctx, num, constraints, parents, options, interpolants, &model, 0, false, num_theory, theory); + result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, constraints, parents, options, interpolants, &model, 0, false, num_theory, theory); } else { @@ -165,7 +165,7 @@ int main(int argc, const char **argv) { for(int i = 0; i < num; i++){ asserted[i] = constraints[i]; Z3_assert_cnstr(ctx,constraints[i]); // assert one constraint - result = Z3_interpolate(ctx, num, &asserted[0], parents, options, interpolants, &model, 0, true, 0, 0); + result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, &asserted[0], parents, options, interpolants, &model, 0, true, 0, 0); if(result == Z3_L_FALSE){ for(unsigned j = 0; j < num-1; j++) /* Since we want the interpolant formulas to survive a "pop", we From 0e4e72b1bc70adcd1f05268bfcbce87a33e010af Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 14 Oct 2014 13:22:12 +0100 Subject: [PATCH 059/117] Added new params.Add functions to the .NET and Java APIs. Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Params.cs | 20 ++++++++++++++++++++ src/api/java/Params.java | 22 ++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/api/dotnet/Params.cs b/src/api/dotnet/Params.cs index 56a7a891f..c33728491 100644 --- a/src/api/dotnet/Params.cs +++ b/src/api/dotnet/Params.cs @@ -58,6 +58,16 @@ namespace Microsoft.Z3 Native.Z3_params_set_double(Context.nCtx, NativeObject, name.NativeObject, value); } + /// + /// Adds a parameter setting. + /// + public void Add(Symbol name, string value) + { + Contract.Requires(value != null); + + Native.Z3_params_set_symbol(Context.nCtx, NativeObject, name.NativeObject, Context.MkSymbol(value).NativeObject); + } + /// /// Adds a parameter setting. /// @@ -103,6 +113,16 @@ namespace Microsoft.Z3 Native.Z3_params_set_symbol(Context.nCtx, NativeObject, Context.MkSymbol(name).NativeObject, value.NativeObject); } + /// + /// Adds a parameter setting. + /// + public void Add(string name, string value) + { + Contract.Requires(value != null); + + Native.Z3_params_set_symbol(Context.nCtx, NativeObject, Context.MkSymbol(name).NativeObject, Context.MkSymbol(value).NativeObject); + } + /// /// A string representation of the parameter set. /// diff --git a/src/api/java/Params.java b/src/api/java/Params.java index 68af4386b..cf3d8c759 100644 --- a/src/api/java/Params.java +++ b/src/api/java/Params.java @@ -28,6 +28,17 @@ public class Params extends Z3Object Native.paramsSetDouble(getContext().nCtx(), getNativeObject(), name.getNativeObject(), value); } + + /** + * Adds a parameter setting. + **/ + public void add(Symbol name, String value) throws Z3Exception + { + + Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(), + name.getNativeObject(), + getContext().mkSymbol(value).getNativeObject()); + } /** * Adds a parameter setting. @@ -75,6 +86,17 @@ public class Params extends Z3Object .mkSymbol(name).getNativeObject(), value.getNativeObject()); } + /** + * Adds a parameter setting. + **/ + public void add(String name, String value) throws Z3Exception + { + + Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(), + getContext().mkSymbol(name).getNativeObject(), + getContext().mkSymbol(value).getNativeObject()); + } + /** * A string representation of the parameter set. **/ From 10c5ed634470c635326f9c8a13fdbf690134ac04 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 14 Oct 2014 11:29:05 -0700 Subject: [PATCH 060/117] add parameter validation in two remaining local cases Signed-off-by: Nikolaj Bjorner --- src/api/api_solver.cpp | 3 +++ src/api/api_tactic.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index c8b1723f1..6fc0c1c72 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -130,6 +130,9 @@ extern "C" { Z3_TRY; LOG_Z3_solver_set_params(c, s, p); RESET_ERROR_CODE(); + param_descrs r; + to_solver_ref(s)->collect_param_descrs(r); + to_param_ref(p).validate(r); 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); diff --git a/src/api/api_tactic.cpp b/src/api/api_tactic.cpp index 7dce33971..adfd0fb71 100644 --- a/src/api/api_tactic.cpp +++ b/src/api/api_tactic.cpp @@ -450,6 +450,9 @@ extern "C" { Z3_TRY; LOG_Z3_tactic_apply_ex(c, t, g, p); RESET_ERROR_CODE(); + param_descrs pd; + to_tactic_ref(t)->collect_param_descrs(pd); + to_param_ref(p).validate(pd); Z3_apply_result r = _tactic_apply(c, t, g, to_param_ref(p)); RETURN_Z3(r); Z3_CATCH_RETURN(0); From 92166eb5cb6efe0f08ac6824e7c75c6074a24988 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 14 Oct 2014 13:12:40 -0700 Subject: [PATCH 061/117] deal with warning for unused parameter Signed-off-by: Nikolaj Bjorner --- src/muz/pdr/pdr_context.cpp | 2 +- src/muz/pdr/pdr_context.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/muz/pdr/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp index f07964395..a1f3af401 100644 --- a/src/muz/pdr/pdr_context.cpp +++ b/src/muz/pdr/pdr_context.cpp @@ -1274,7 +1274,7 @@ namespace pdr { m_pm(m_fparams, params.max_num_contexts(), m), m_query_pred(m), m_query(0), - m_search(m_params.bfs_model_search(), m), + m_search(m_params.bfs_model_search()), m_last_result(l_undef), m_inductive_lvl(0), m_expanded_lvl(0), diff --git a/src/muz/pdr/pdr_context.h b/src/muz/pdr/pdr_context.h index a85011600..e21f46412 100644 --- a/src/muz/pdr/pdr_context.h +++ b/src/muz/pdr/pdr_context.h @@ -245,7 +245,6 @@ namespace pdr { class model_search { typedef ptr_vector model_nodes; - ast_manager& m; bool m_bfs; model_node* m_root; std::deque m_leaves; @@ -258,7 +257,7 @@ namespace pdr { void enqueue_leaf(model_node& n); // add leaf to priority queue. void update_models(); public: - model_search(bool bfs, ast_manager& m): m(m), m_bfs(bfs), m_root(0) {} + model_search(bool bfs): m_bfs(bfs), m_root(0) {} ~model_search(); void reset(); From 136b172b5a3ef2dd943b1af1534416d9abbe956f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 15 Oct 2014 09:58:54 -0700 Subject: [PATCH 062/117] move parameter validation for when solver object is actually crated Signed-off-by: Nikolaj Bjorner --- src/api/api_solver.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 6fc0c1c72..65b2a9047 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -40,6 +40,10 @@ extern "C" { params_ref p = s->m_params; mk_c(c)->params().get_solver_params(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled); s->m_solver = (*(s->m_solver_factory))(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled, s->m_logic); + + param_descrs r; + s->m_solver->collect_param_descrs(r); + p.validate(r); s->m_solver->updt_params(p); } @@ -130,14 +134,15 @@ extern "C" { Z3_TRY; LOG_Z3_solver_set_params(c, s, p); RESET_ERROR_CODE(); - param_descrs r; - to_solver_ref(s)->collect_param_descrs(r); - to_param_ref(p).validate(r); + 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) to_solver_ref(s)->set_produce_models(new_model); + param_descrs r; + to_solver_ref(s)->collect_param_descrs(r); + to_param_ref(p).validate(r); to_solver_ref(s)->updt_params(to_param_ref(p)); } to_solver(s)->m_params = to_param_ref(p); From c739d803ab0ea7543234d6300841b3809823ce2d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 15 Oct 2014 13:42:56 -0700 Subject: [PATCH 063/117] include model/proof/unsat_core as part of model parameters Signed-off-by: Nikolaj Bjorner --- src/api/api_solver.cpp | 4 ++++ src/cmd_context/context_params.cpp | 10 +++++++--- src/cmd_context/context_params.h | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 65b2a9047..b9b3d8166 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -43,6 +43,7 @@ extern "C" { param_descrs r; s->m_solver->collect_param_descrs(r); + context_params::collect_solver_param_descrs(r); p.validate(r); s->m_solver->updt_params(p); } @@ -106,6 +107,7 @@ extern "C" { if (!initialized) init_solver(c, s); to_solver_ref(s)->collect_param_descrs(descrs); + context_params::collect_solver_param_descrs(descrs); if (!initialized) to_solver(s)->m_solver = 0; descrs.display(buffer); @@ -123,6 +125,7 @@ extern "C" { if (!initialized) init_solver(c, s); to_solver_ref(s)->collect_param_descrs(d->m_descrs); + context_params::collect_solver_param_descrs(d->m_descrs); if (!initialized) to_solver(s)->m_solver = 0; Z3_param_descrs r = of_param_descrs(d); @@ -142,6 +145,7 @@ extern "C" { to_solver_ref(s)->set_produce_models(new_model); param_descrs r; to_solver_ref(s)->collect_param_descrs(r); + context_params::collect_solver_param_descrs(r); to_param_ref(p).validate(r); to_solver_ref(s)->updt_params(to_param_ref(p)); } diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 0ec44e0cf..d796dc9b1 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -114,15 +114,19 @@ void context_params::collect_param_descrs(param_descrs & d) { d.insert("well_sorted_check", CPK_BOOL, "type checker", "true"); d.insert("type_check", CPK_BOOL, "type checker (alias for well_sorted_check)", "true"); d.insert("auto_config", CPK_BOOL, "use heuristics to automatically select solver and configure it", "true"); - d.insert("proof", CPK_BOOL, "proof generation, it must be enabled when the Z3 context is created", "false"); d.insert("check_interpolants", CPK_BOOL, "check correctness of interpolants", "false"); - d.insert("model", CPK_BOOL, "model generation for solvers, this parameter can be overwritten when creating a solver", "true"); d.insert("model_validate", CPK_BOOL, "validate models produced by solvers", "false"); d.insert("trace", CPK_BOOL, "trace generation for VCC", "false"); d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log"); - d.insert("unsat_core", CPK_BOOL, "unsat-core generation for solvers, this parameter can be overwritten when creating a solver, not every solver in Z3 supports unsat core generation", "false"); d.insert("debug_ref_count", CPK_BOOL, "debug support for AST reference counting", "false"); d.insert("smtlib2_compliant", CPK_BOOL, "enable/disable SMT-LIB 2.0 compliance", "false"); + collect_solver_param_descrs(d); +} + +void context_params::collect_solver_param_descrs(param_descrs & d) { + d.insert("proof", CPK_BOOL, "proof generation, it must be enabled when the Z3 context is created", "false"); + d.insert("model", CPK_BOOL, "model generation for solvers, this parameter can be overwritten when creating a solver", "true"); + d.insert("unsat_core", CPK_BOOL, "unsat-core generation for solvers, this parameter can be overwritten when creating a solver, not every solver in Z3 supports unsat core generation", "false"); } params_ref context_params::merge_default_params(params_ref const & p) { diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index 7271bb84f..e26fd3fe5 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -55,6 +55,8 @@ public: */ void get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled); + static void collect_solver_param_descrs(param_descrs & d); + /** \brief Include in p parameters derived from this context_params. These are parameters that are meaningful for tactics and solvers. From 7767a2362685e407a38b8efd5b534992a319a7c2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 15 Oct 2014 21:37:37 -0700 Subject: [PATCH 064/117] improve error messages on incorrect parameter passing Signed-off-by: Nikolaj Bjorner --- src/cmd_context/context_params.cpp | 8 +++++++- src/smt/arith_eq_solver.cpp | 4 +++- src/util/gparams.cpp | 21 +++++++++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index d796dc9b1..d1184fbc8 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -86,7 +86,13 @@ void context_params::set(char const * param, char const * value) { set_bool(m_smtlib2_compliant, param, value); } else { - throw default_exception("unknown parameter '%s'", p.c_str()); + param_descrs d; + collect_param_descrs(d); + std::stringstream strm; + strm << "unknown parameter '" << p << "'\n"; + strm << "Legal parameters are:\n"; + d.display(strm, 2, false, false); + throw default_exception(strm.str()); } } diff --git a/src/smt/arith_eq_solver.cpp b/src/smt/arith_eq_solver.cpp index 41a61bf73..9a6868ff1 100644 --- a/src/smt/arith_eq_solver.cpp +++ b/src/smt/arith_eq_solver.cpp @@ -604,7 +604,9 @@ bool arith_eq_solver::solve_integer_equations_gcd( } SASSERT(g == r0[i]); } - SASSERT(abs(r0[i]).is_one()); + if (!abs(r0[i]).is_one()) { + return false; + } live.erase(live.begin()+live_pos); for (j = 0; j < live.size(); ++j) { row& r = rows[live[j]]; diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 1d9426390..04acf1ad9 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -201,7 +201,7 @@ public: } } - void throw_unknown_parameter(symbol const & param_name, symbol const & mod_name) { + void throw_unknown_parameter(symbol const & param_name, param_descrs const& d, symbol const & mod_name) { if (mod_name == symbol::null) { char const * new_name = get_new_param_name(param_name); if (new_name) { @@ -213,11 +213,20 @@ public: param_name.bare_str()); } else { - throw exception("unknown parameter '%s'", param_name.bare_str()); + std::stringstream strm; + strm << "unknown parameter '" << param_name << "'\n"; + strm << "Legal parameters are:\n"; + d.display(strm, 2, false, false); + throw default_exception(strm.str()); } } else { - throw exception("unknown parameter '%s' at module '%s'", param_name.bare_str(), mod_name.bare_str()); + std::stringstream strm; + strm << "unknown parameter '" << param_name << "' "; + strm << "at module '" << mod_name << "'\n"; + strm << "Legal parameters are:\n"; + d.display(strm, 2, false, false); + throw default_exception(strm.str()); } } @@ -225,7 +234,7 @@ public: param_kind k = d.get_kind(param_name); params_ref & ps = get_params(mod_name); if (k == CPK_INVALID) { - throw_unknown_parameter(param_name, mod_name); + throw_unknown_parameter(param_name, d, mod_name); } else if (k == CPK_UINT) { long val = strtol(value, 0, 10); @@ -312,7 +321,7 @@ public: std::string get_default(param_descrs const & d, symbol const & p, symbol const & m) { if (!d.contains(p)) { - throw_unknown_parameter(p, m); + throw_unknown_parameter(p, d, m); } char const * r = d.get_default(p); if (r == 0) @@ -478,7 +487,7 @@ public: throw exception("unknown module '%s'", m.bare_str()); } if (!d->contains(p)) - throw_unknown_parameter(p, m); + throw_unknown_parameter(p, *d, m); out << " name: " << p << "\n"; if (m != symbol::null) { out << " module: " << m << "\n"; From fe4a8b44a51e3364f6006b3171973d43a2ba418d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 16 Oct 2014 22:40:52 -0700 Subject: [PATCH 065/117] revert some changes to how 'out' parameters are annotated on API calls. Retain the 'out' annotation for so-called managed out parameters. The data-type examples in managed API fail with the out parameter annotation as no memory is allocated on instances of out parameters, other than the interpolation APIs that are new Signed-off-by: Nikolaj Bjorner --- scripts/update_api.py | 8 +++++--- src/api/dotnet/Constructor.cs | 6 +++--- src/api/dotnet/Context.cs | 2 +- src/api/dotnet/EnumSort.cs | 2 +- src/api/dotnet/TupleSort.cs | 4 ++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index 837c2e1f4..e08adf111 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -263,8 +263,10 @@ def param2dotnet(p): return "[In] %s[]" % type2dotnet(param_type(p)) elif k == INOUT_ARRAY: return "[In, Out] %s[]" % type2dotnet(param_type(p)) - elif k == OUT_ARRAY or k == OUT_MANAGED_ARRAY: - return "[Out] out %s[]" % type2dotnet(param_type(p)) + elif k == OUT_ARRAY: + return "[Out] %s[]" % type2dotnet(param_type(p)) + elif k == OUT_MANAGED_ARRAY: + return "[Out] out %s[]" % type2dotnet(param_type(p)) else: return type2dotnet(param_type(p)) @@ -476,7 +478,7 @@ def mk_dotnet_wrappers(): dotnet.write('out '); else: dotnet.write('ref ') - elif param_kind(param) == OUT_ARRAY or param_kind(param) == OUT_MANAGED_ARRAY: + elif param_kind(param) == OUT_MANAGED_ARRAY: dotnet.write('out '); dotnet.write('a%d' % i) i = i + 1 diff --git a/src/api/dotnet/Constructor.cs b/src/api/dotnet/Constructor.cs index 8d478dd85..527b8bc13 100644 --- a/src/api/dotnet/Constructor.cs +++ b/src/api/dotnet/Constructor.cs @@ -50,7 +50,7 @@ namespace Microsoft.Z3 IntPtr constructor = IntPtr.Zero; IntPtr tester = IntPtr.Zero; IntPtr[] accessors = new IntPtr[n]; - Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors); + Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors); return new FuncDecl(Context, constructor); } } @@ -66,7 +66,7 @@ namespace Microsoft.Z3 IntPtr constructor = IntPtr.Zero; IntPtr tester = IntPtr.Zero; IntPtr[] accessors = new IntPtr[n]; - Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors); + Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors); return new FuncDecl(Context, tester); } } @@ -82,7 +82,7 @@ namespace Microsoft.Z3 IntPtr constructor = IntPtr.Zero; IntPtr tester = IntPtr.Zero; IntPtr[] accessors = new IntPtr[n]; - Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors); + Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors); FuncDecl[] t = new FuncDecl[n]; for (uint i = 0; i < n; i++) t[i] = new FuncDecl(Context, accessors[i]); diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index a9e25de4f..2b88cbab7 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -424,7 +424,7 @@ namespace Microsoft.Z3 n_constr[i] = cla[i].NativeObject; } IntPtr[] n_res = new IntPtr[n]; - Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), out n_res, n_constr); + Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); DatatypeSort[] res = new DatatypeSort[n]; for (uint i = 0; i < n; i++) res[i] = new DatatypeSort(this, n_res[i]); diff --git a/src/api/dotnet/EnumSort.cs b/src/api/dotnet/EnumSort.cs index db3d5123f..e62043078 100644 --- a/src/api/dotnet/EnumSort.cs +++ b/src/api/dotnet/EnumSort.cs @@ -88,7 +88,7 @@ namespace Microsoft.Z3 IntPtr[] n_constdecls = new IntPtr[n]; IntPtr[] n_testers = new IntPtr[n]; NativeObject = Native.Z3_mk_enumeration_sort(ctx.nCtx, name.NativeObject, (uint)n, - Symbol.ArrayToNative(enumNames), out n_constdecls, out n_testers); + Symbol.ArrayToNative(enumNames), n_constdecls, n_testers); } #endregion }; diff --git a/src/api/dotnet/TupleSort.cs b/src/api/dotnet/TupleSort.cs index 7d0b6a853..81a0eaf60 100644 --- a/src/api/dotnet/TupleSort.cs +++ b/src/api/dotnet/TupleSort.cs @@ -74,10 +74,10 @@ namespace Microsoft.Z3 Contract.Requires(name != null); IntPtr t = IntPtr.Zero; - IntPtr[] f; + IntPtr[] f = new IntPtr[numFields]; NativeObject = Native.Z3_mk_tuple_sort(ctx.nCtx, name.NativeObject, numFields, Symbol.ArrayToNative(fieldNames), AST.ArrayToNative(fieldSorts), - ref t, out f); + ref t, f); } #endregion }; From f4a015602ca0b204ba72373301240eaa89e6fc08 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 18 Oct 2014 13:43:13 +0100 Subject: [PATCH 066/117] Disable FPA-min/max because of name clashes with user-defined functions. Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index df26422c8..c6706b7b1 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -581,8 +581,9 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL)); op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS)); - op_names.push_back(builtin_name("min", OP_FLOAT_MIN)); - op_names.push_back(builtin_name("max", OP_FLOAT_MAX)); + // Disabled min/max, clashes with user-defined min/max functions + // op_names.push_back(builtin_name("min", OP_FLOAT_MIN)); + // op_names.push_back(builtin_name("max", OP_FLOAT_MAX)); op_names.push_back(builtin_name("asFloat", OP_TO_FLOAT)); From de9f6d3e11d536e6dabf4247747214da96af3546 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 21 Oct 2014 16:52:16 +0100 Subject: [PATCH 067/117] FPA name clash fix Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index c6706b7b1..5466df069 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -314,8 +314,8 @@ func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_paramete symbol name; switch (k) { case OP_FLOAT_REM: name = "remainder"; break; - case OP_FLOAT_MIN: name = "min"; break; - case OP_FLOAT_MAX: name = "max"; break; + case OP_FLOAT_MIN: name = "fp.min"; break; + case OP_FLOAT_MAX: name = "fp.max"; break; default: UNREACHABLE(); break; From 7f045290804ff9564f6db59cb1c6145bf0d6062c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 21 Oct 2014 09:11:38 -0700 Subject: [PATCH 068/117] validate types of parameter values that get set globally Signed-off-by: Nikolaj Bjorner --- src/util/gparams.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 04acf1ad9..6397ad377 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -230,6 +230,43 @@ public: } } + void validate_type(symbol const& name, char const* value, param_descrs const& d) { + param_kind k = d.get_kind(name); + std::stringstream strm; + + switch (k) { + case CPK_UINT: + for (; *value; ++value) { + if (!('0' <= *value && *value <= '9')) { + strm << "Expected values for parameter " << name + << " is an unsigned integer. It was given argument '" << value << "'"; + throw default_exception(strm.str()); + } + } + break; + case CPK_DOUBLE: + for (; *value; ++value) { + if (!('0' <= *value && *value <= '9') && *value != '.' && *value != '-') { + strm << "Expected values for parameter " << name + << " is a double. It was given argument '" << value << "'"; + throw default_exception(strm.str()); + } + } + break; + + case CPK_BOOL: + if (strcmp(value, "true") != 0 && strcmp(value, "false") != 0) { + strm << "Expected values for parameter " << name + << " are 'true' or 'false'. It was given argument '" << value << "'"; + throw default_exception(strm.str()); + } + break; + case CPK_SYMBOL: + case CPK_STRING: + break; + } + } + void set(param_descrs const & d, symbol const & param_name, char const * value, symbol const & mod_name) { param_kind k = d.get_kind(param_name); params_ref & ps = get_params(mod_name); @@ -291,11 +328,13 @@ public: symbol m, p; normalize(name, m, p); if (m == symbol::null) { + validate_type(p, value, get_param_descrs()); set(get_param_descrs(), p, value, m); } else { param_descrs * d; if (get_module_param_descrs().find(m, d)) { + validate_type(p, value, *d); set(*d, p, value, m); } else { From 340f7659839ce492b7eb8483fd2bd91eb1ca9645 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 21 Oct 2014 09:35:32 -0700 Subject: [PATCH 069/117] make sure that parameters are appended such that multiple paramters are not ignored on the solver Signed-off-by: Nikolaj Bjorner --- src/api/api_solver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index b9b3d8166..e57050e82 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -149,7 +149,7 @@ extern "C" { to_param_ref(p).validate(r); to_solver_ref(s)->updt_params(to_param_ref(p)); } - to_solver(s)->m_params = to_param_ref(p); + to_solver(s)->m_params.append(to_param_ref(p)); Z3_CATCH; } From 3ecffaa1e5c7706c196c2cd11db4f8c865c6846d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 21 Oct 2014 11:12:50 -0700 Subject: [PATCH 070/117] remove unused and always failing get_param_value function Signed-off-by: Nikolaj Bjorner --- src/api/api_config_params.cpp | 6 ------ src/api/dotnet/Context.cs | 17 ----------------- src/api/z3_api.h | 9 --------- src/cmd_context/context_params.cpp | 14 +++++++------- 4 files changed, 7 insertions(+), 39 deletions(-) diff --git a/src/api/api_config_params.cpp b/src/api/api_config_params.cpp index 48c2df4a9..c46e7363d 100644 --- a/src/api/api_config_params.cpp +++ b/src/api/api_config_params.cpp @@ -106,10 +106,4 @@ extern "C" { Z3_CATCH; } - Z3_bool Z3_API Z3_get_param_value(Z3_context c, Z3_string param_id, Z3_string* param_value) { - LOG_Z3_get_param_value(c, param_id, param_value); - // TODO - return Z3_FALSE; - } - }; diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index 2b88cbab7..1c03d76b6 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -3527,28 +3527,11 @@ namespace Microsoft.Z3 /// Only a few configuration parameters are mutable once the context is created. /// An exception is thrown when trying to modify an immutable parameter. /// - /// public void UpdateParamValue(string id, string value) { Native.Z3_update_param_value(nCtx, id, value); } - /// - /// Get a configuration parameter. - /// - /// - /// Returns null if the parameter value does not exist. - /// - /// - public string GetParamValue(string id) - { - IntPtr res = IntPtr.Zero; - if (Native.Z3_get_param_value(nCtx, id, out res) == 0) - return null; - else - return Marshal.PtrToStringAnsi(res); - } - #endregion #region Internal diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 04e2d38af..2e3ddf4b4 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1462,15 +1462,6 @@ extern "C" { */ void Z3_API Z3_update_param_value(__in Z3_context c, __in Z3_string param_id, __in Z3_string param_value); - /** - \brief Return the value of a context parameter. - - \sa Z3_global_param_get - - def_API('Z3_get_param_value', BOOL, (_in(CONTEXT), _in(STRING), _out(STRING))) - */ - Z3_bool_opt Z3_API Z3_get_param_value(__in Z3_context c, __in Z3_string param_id, __out_opt Z3_string_ptr param_value); - #ifdef CorML4 /** \brief Interrupt the execution of a Z3 procedure. diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index d1184fbc8..254a1d931 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -86,13 +86,13 @@ void context_params::set(char const * param, char const * value) { set_bool(m_smtlib2_compliant, param, value); } else { - param_descrs d; - collect_param_descrs(d); - std::stringstream strm; - strm << "unknown parameter '" << p << "'\n"; - strm << "Legal parameters are:\n"; - d.display(strm, 2, false, false); - throw default_exception(strm.str()); + param_descrs d; + collect_param_descrs(d); + std::stringstream strm; + strm << "unknown parameter '" << p << "'\n"; + strm << "Legal parameters are:\n"; + d.display(strm, 2, false, false); + throw default_exception(strm.str()); } } From f3a04734d9cd685f5921c368f648899246b094fc Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 21 Oct 2014 12:48:49 -0700 Subject: [PATCH 071/117] add pretty printing to SMT2 from solver, add get_id to Ast objects Signed-off-by: Nikolaj Bjorner --- src/api/python/z3.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 82ba85472..470280630 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -297,6 +297,11 @@ class AstRef(Z3PPObject): """Return a pointer to the corresponding C Z3_ast object.""" return self.ast + def get_id(self): + """Return unique identifier for object. It can be used for hash-tables and maps.""" + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + + def ctx_ref(self): """Return a reference to the C context where this AST node is stored.""" return self.ctx.ref() @@ -447,6 +452,10 @@ class SortRef(AstRef): def as_ast(self): return Z3_sort_to_ast(self.ctx_ref(), self.ast) + def get_id(self): + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + + def kind(self): """Return the Z3 internal kind of a sort. This method can be used to test if `self` is one of the Z3 builtin sorts. @@ -585,6 +594,9 @@ class FuncDeclRef(AstRef): def as_ast(self): return Z3_func_decl_to_ast(self.ctx_ref(), self.ast) + def get_id(self): + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + def as_func_decl(self): return self.ast @@ -730,6 +742,9 @@ class ExprRef(AstRef): def as_ast(self): return self.ast + def get_id(self): + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + def sort(self): """Return the sort of expression `self`. @@ -1524,6 +1539,9 @@ class PatternRef(ExprRef): def as_ast(self): return Z3_pattern_to_ast(self.ctx_ref(), self.ast) + def get_id(self): + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + def is_pattern(a): """Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation. @@ -1586,6 +1604,9 @@ class QuantifierRef(BoolRef): def as_ast(self): return self.ast + def get_id(self): + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + def sort(self): """Return the Boolean sort.""" return BoolSort(self.ctx) @@ -6011,6 +6032,24 @@ class Solver(Z3PPObject): """ return Z3_solver_to_string(self.ctx.ref(), self.solver) + def to_smt2(self): + """return SMTLIB2 formatted benchmark for solver's assertions""" + es = self.assertions() + sz = len(es) + sz1 = sz + if sz1 > 0: + sz1 -= 1 + v = (Ast * sz1)() + for i in range(sz1): + v[i] = es[i].as_ast() + if sz > 0: + e = es[sz1].as_ast() + else: + e = BoolVal(True, self.ctx).as_ast() + return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) + + + def SolverFor(logic, ctx=None): """Create a solver customized for the given logic. From d77d6c6648a1aaf8cafefd1458500c71e2c271ec Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 21 Oct 2014 13:24:31 -0700 Subject: [PATCH 072/117] update parameter checking for doubles, and fix error reporting Signed-off-by: Nikolaj Bjorner --- src/util/gparams.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 6397ad377..83157a0b0 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -233,22 +233,22 @@ public: void validate_type(symbol const& name, char const* value, param_descrs const& d) { param_kind k = d.get_kind(name); std::stringstream strm; - + char const* _value = value; switch (k) { case CPK_UINT: for (; *value; ++value) { if (!('0' <= *value && *value <= '9')) { strm << "Expected values for parameter " << name - << " is an unsigned integer. It was given argument '" << value << "'"; + << " is an unsigned integer. It was given argument '" << _value << "'"; throw default_exception(strm.str()); } } break; case CPK_DOUBLE: for (; *value; ++value) { - if (!('0' <= *value && *value <= '9') && *value != '.' && *value != '-') { + if (!('0' <= *value && *value <= '9') && *value != '.' && *value != '-' && *value != '/') { strm << "Expected values for parameter " << name - << " is a double. It was given argument '" << value << "'"; + << " is a double. It was given argument '" << _value << "'"; throw default_exception(strm.str()); } } From 1059d226e44d9ad65285e5e1a9aba58856a2ed57 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 21 Oct 2014 13:25:19 -0700 Subject: [PATCH 073/117] add default statement instead of incomplete cases Signed-off-by: Nikolaj Bjorner --- src/util/gparams.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 83157a0b0..adffe6bde 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -261,8 +261,7 @@ public: throw default_exception(strm.str()); } break; - case CPK_SYMBOL: - case CPK_STRING: + default: break; } } From ae6121525a9c6dd8ba079001bd2fcfad4015d81b Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 22 Oct 2014 13:57:07 +0100 Subject: [PATCH 074/117] Z3Py: improve readability of Z3 exceptions Signed-off-by: Nuno Lopes --- src/api/python/z3types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3types.py b/src/api/python/z3types.py index 593312d68..5d59368ff 100644 --- a/src/api/python/z3types.py +++ b/src/api/python/z3types.py @@ -4,7 +4,7 @@ class Z3Exception(Exception): def __init__(self, value): self.value = value def __str__(self): - return repr(self.value) + return str(self.value) class ContextObj(ctypes.c_void_p): def __init__(self, context): self._as_parameter_ = context From 65ce445b7e209728c725997e140191ab16454bf2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 22 Oct 2014 08:24:49 -0700 Subject: [PATCH 075/117] update Java API Signed-off-by: Nikolaj Bjorner --- src/api/java/Context.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 6b6c63ac3..cc5c07c5e 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -2911,20 +2911,6 @@ public class Context extends IDisposable Native.updateParamValue(nCtx(), id, value); } - /** - * Get a configuration parameter. Returns null if the parameter - * value does not exist. - **/ - public String getParamValue(String id) throws Z3Exception - { - Native.StringPtr res = new Native.StringPtr(); - boolean r = Native.getParamValue(nCtx(), id, res); - if (!r) - return null; - else - return res.value; - } - long m_ctx = 0; long nCtx() From d91a114b8086d3f3d68d354b80bc62a9e7d5b3d6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 22 Oct 2014 16:29:13 +0100 Subject: [PATCH 076/117] Java API: removed Z3_get_param_value as in other APIs. Signed-off-by: Christoph M. Wintersteiger --- src/api/java/Context.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 6b6c63ac3..41a98e3d9 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -2904,27 +2904,13 @@ public class Context extends IDisposable * configuration parameters can be obtained using the Z3 executable: * z3.exe -ini? Only a few configuration parameters are mutable * once the context is created. An exception is thrown when trying to modify - * an immutable parameter. + * an immutable parameter. **/ public void updateParamValue(String id, String value) throws Z3Exception { Native.updateParamValue(nCtx(), id, value); } - /** - * Get a configuration parameter. Returns null if the parameter - * value does not exist. - **/ - public String getParamValue(String id) throws Z3Exception - { - Native.StringPtr res = new Native.StringPtr(); - boolean r = Native.getParamValue(nCtx(), id, res); - if (!r) - return null; - else - return res.value; - } - long m_ctx = 0; long nCtx() From 4304012971ef5293a09d73b010bd3263d5b9d9a5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 22 Oct 2014 16:55:08 +0100 Subject: [PATCH 077/117] Java API: copyright notices Signed-off-by: Christoph M. Wintersteiger --- src/api/java/AST.java | 19 +++++++++++++++---- src/api/java/ASTDecRefQueue.java | 18 +++++++++++++++--- src/api/java/ASTMap.java | 19 +++++++++++++++---- src/api/java/ASTVector.java | 19 +++++++++++++++---- src/api/java/AlgebraicNum.java | 19 +++++++++++++++---- src/api/java/ApplyResult.java | 19 +++++++++++++++---- src/api/java/ApplyResultDecRefQueue.java | 18 +++++++++++++++--- src/api/java/ArithExpr.java | 19 +++++++++++++++---- src/api/java/ArithSort.java | 19 +++++++++++++++---- src/api/java/ArrayExpr.java | 19 +++++++++++++++---- src/api/java/ArraySort.java | 19 +++++++++++++++---- src/api/java/AstMapDecRefQueue.java | 18 +++++++++++++++--- src/api/java/AstVectorDecRefQueue.java | 18 +++++++++++++++--- src/api/java/BitVecExpr.java | 19 +++++++++++++++---- src/api/java/BitVecNum.java | 19 +++++++++++++++---- src/api/java/BitVecSort.java | 20 ++++++++++++++++---- src/api/java/BoolExpr.java | 19 +++++++++++++++---- src/api/java/BoolSort.java | 19 +++++++++++++++---- src/api/java/Constructor.java | 19 +++++++++++++++---- src/api/java/ConstructorList.java | 19 +++++++++++++++---- src/api/java/Context.java | 19 +++++++++++++++---- src/api/java/DatatypeExpr.java | 19 +++++++++++++++---- src/api/java/DatatypeSort.java | 19 +++++++++++++++---- src/api/java/EnumSort.java | 19 +++++++++++++++---- src/api/java/Expr.java | 19 +++++++++++++++---- src/api/java/FiniteDomainSort.java | 19 +++++++++++++++---- src/api/java/Fixedpoint.java | 19 +++++++++++++++---- src/api/java/FixedpointDecRefQueue.java | 18 +++++++++++++++--- src/api/java/FuncDecl.java | 19 +++++++++++++++---- src/api/java/FuncInterp.java | 19 +++++++++++++++---- src/api/java/FuncInterpDecRefQueue.java | 18 +++++++++++++++--- src/api/java/FuncInterpEntryDecRefQueue.java | 18 +++++++++++++++--- src/api/java/Global.java | 18 +++++++++++++++--- src/api/java/Goal.java | 19 +++++++++++++++---- src/api/java/GoalDecRefQueue.java | 18 +++++++++++++++--- src/api/java/IDecRefQueue.java | 19 +++++++++++++++---- src/api/java/IntExpr.java | 19 +++++++++++++++---- src/api/java/IntNum.java | 19 +++++++++++++++---- src/api/java/IntSort.java | 19 +++++++++++++++---- src/api/java/IntSymbol.java | 19 +++++++++++++++---- src/api/java/InterpolationContext.java | 18 ++++++++++++++++-- src/api/java/ListSort.java | 19 +++++++++++++++---- src/api/java/Log.java | 19 +++++++++++++++---- src/api/java/Model.java | 19 +++++++++++++++---- src/api/java/ModelDecRefQueue.java | 18 +++++++++++++++--- src/api/java/ParamDescrs.java | 19 +++++++++++++++---- src/api/java/ParamDescrsDecRefQueue.java | 18 +++++++++++++++--- src/api/java/Params.java | 20 ++++++++++++++++---- src/api/java/ParamsDecRefQueue.java | 18 +++++++++++++++--- src/api/java/Pattern.java | 19 +++++++++++++++---- src/api/java/Probe.java | 19 +++++++++++++++---- src/api/java/ProbeDecRefQueue.java | 18 +++++++++++++++--- src/api/java/Quantifier.java | 19 +++++++++++++++---- src/api/java/RatNum.java | 19 +++++++++++++++---- src/api/java/RealExpr.java | 19 +++++++++++++++---- src/api/java/RealSort.java | 19 +++++++++++++++---- src/api/java/RelationSort.java | 19 +++++++++++++++---- src/api/java/SetSort.java | 19 +++++++++++++++---- src/api/java/Solver.java | 19 +++++++++++++++---- src/api/java/SolverDecRefQueue.java | 18 +++++++++++++++--- src/api/java/Sort.java | 19 +++++++++++++++---- src/api/java/Statistics.java | 19 +++++++++++++++---- src/api/java/StatisticsDecRefQueue.java | 18 +++++++++++++++--- src/api/java/Status.java | 19 +++++++++++++++---- src/api/java/StringSymbol.java | 19 +++++++++++++++---- src/api/java/Symbol.java | 19 +++++++++++++++---- src/api/java/Tactic.java | 19 +++++++++++++++---- src/api/java/TacticDecRefQueue.java | 18 +++++++++++++++--- src/api/java/TupleSort.java | 19 +++++++++++++++---- src/api/java/UninterpretedSort.java | 19 +++++++++++++++---- src/api/java/Version.java | 19 +++++++++++++++---- src/api/java/Z3Exception.java | 19 +++++++++++++++---- src/api/java/Z3Object.java | 19 +++++++++++++++---- 73 files changed, 1098 insertions(+), 274 deletions(-) diff --git a/src/api/java/AST.java b/src/api/java/AST.java index fa5cd8284..1f5463ec7 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from AST.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + AST.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ASTDecRefQueue.java b/src/api/java/ASTDecRefQueue.java index e0711363d..6ae84eb41 100644 --- a/src/api/java/ASTDecRefQueue.java +++ b/src/api/java/ASTDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ASTDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ASTMap.java b/src/api/java/ASTMap.java index dbe7fbd02..6a4e6d56f 100644 --- a/src/api/java/ASTMap.java +++ b/src/api/java/ASTMap.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ASTMap.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ASTMap.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ASTVector.java b/src/api/java/ASTVector.java index 39e32f5d5..07b7dbf56 100644 --- a/src/api/java/ASTVector.java +++ b/src/api/java/ASTVector.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ASTVector.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ASTVector.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/AlgebraicNum.java b/src/api/java/AlgebraicNum.java index eaeae933d..340f37f80 100644 --- a/src/api/java/AlgebraicNum.java +++ b/src/api/java/AlgebraicNum.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from AlgebraicNum.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + AlgebraicNum.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ApplyResult.java b/src/api/java/ApplyResult.java index e6c6b89fd..c550c05ae 100644 --- a/src/api/java/ApplyResult.java +++ b/src/api/java/ApplyResult.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ApplyResult.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ApplyResult.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ApplyResultDecRefQueue.java b/src/api/java/ApplyResultDecRefQueue.java index 275f4b8f0..78f74d6cc 100644 --- a/src/api/java/ApplyResultDecRefQueue.java +++ b/src/api/java/ApplyResultDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ApplyResultDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ArithExpr.java b/src/api/java/ArithExpr.java index c429f2322..83ec35d01 100644 --- a/src/api/java/ArithExpr.java +++ b/src/api/java/ArithExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ArithExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - * **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ArithExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ArithSort.java b/src/api/java/ArithSort.java index 5e1780539..2346d9b74 100644 --- a/src/api/java/ArithSort.java +++ b/src/api/java/ArithSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ArithSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ArithSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ArrayExpr.java b/src/api/java/ArrayExpr.java index b3bbb8d75..2d5a5a273 100644 --- a/src/api/java/ArrayExpr.java +++ b/src/api/java/ArrayExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ArrayExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ArrayExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ArraySort.java b/src/api/java/ArraySort.java index 2ab8a9750..a371fa3cb 100644 --- a/src/api/java/ArraySort.java +++ b/src/api/java/ArraySort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ArraySort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ArraySort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/AstMapDecRefQueue.java b/src/api/java/AstMapDecRefQueue.java index f4c6b2ab5..a4e02d29f 100644 --- a/src/api/java/AstMapDecRefQueue.java +++ b/src/api/java/AstMapDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + AstMapDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/AstVectorDecRefQueue.java b/src/api/java/AstVectorDecRefQueue.java index bdabcdcb1..e0c7988a9 100644 --- a/src/api/java/AstVectorDecRefQueue.java +++ b/src/api/java/AstVectorDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + AstVectorDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/BitVecExpr.java b/src/api/java/BitVecExpr.java index 9602ea3a0..24b1cfdf3 100644 --- a/src/api/java/BitVecExpr.java +++ b/src/api/java/BitVecExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from BitVecExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + BitVecExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/BitVecNum.java b/src/api/java/BitVecNum.java index 2dd0dd75a..69ac5dadc 100644 --- a/src/api/java/BitVecNum.java +++ b/src/api/java/BitVecNum.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from BitVecNum.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + BitVecNum.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/BitVecSort.java b/src/api/java/BitVecSort.java index c2ec4c26e..be406c806 100644 --- a/src/api/java/BitVecSort.java +++ b/src/api/java/BitVecSort.java @@ -1,8 +1,20 @@ /** - * This file was automatically generated from BitVecSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + BitVecSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ + package com.microsoft.z3; /** diff --git a/src/api/java/BoolExpr.java b/src/api/java/BoolExpr.java index 40786f76d..99453496a 100644 --- a/src/api/java/BoolExpr.java +++ b/src/api/java/BoolExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from BoolExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + BoolExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/BoolSort.java b/src/api/java/BoolSort.java index 03711289a..85ca0a7f7 100644 --- a/src/api/java/BoolSort.java +++ b/src/api/java/BoolSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from BoolSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + BoolSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Constructor.java b/src/api/java/Constructor.java index 0c53da73c..4813c2b0a 100644 --- a/src/api/java/Constructor.java +++ b/src/api/java/Constructor.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Constructor.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Constructor.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ConstructorList.java b/src/api/java/ConstructorList.java index a33276ebb..315a2e535 100644 --- a/src/api/java/ConstructorList.java +++ b/src/api/java/ConstructorList.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ConstructorList.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ConstructorList.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Context.java b/src/api/java/Context.java index 41a98e3d9..4fbd79be2 100644 --- a/src/api/java/Context.java +++ b/src/api/java/Context.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Context.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Context.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/DatatypeExpr.java b/src/api/java/DatatypeExpr.java index 63cb02f80..806ceacab 100644 --- a/src/api/java/DatatypeExpr.java +++ b/src/api/java/DatatypeExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from DatatypeExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + DatatypeExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/DatatypeSort.java b/src/api/java/DatatypeSort.java index f7b2f7d32..9c339d932 100644 --- a/src/api/java/DatatypeSort.java +++ b/src/api/java/DatatypeSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from DatatypeSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + DatatypeSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/EnumSort.java b/src/api/java/EnumSort.java index c0fb6d1d6..9715b9a97 100644 --- a/src/api/java/EnumSort.java +++ b/src/api/java/EnumSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from EnumSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + EnumSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index f7edc6a2b..3773e749d 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Expr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Expr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/FiniteDomainSort.java b/src/api/java/FiniteDomainSort.java index a8ba0d8c3..4cb2ab917 100644 --- a/src/api/java/FiniteDomainSort.java +++ b/src/api/java/FiniteDomainSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from FiniteDomainSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + FiniteDomainSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Fixedpoint.java b/src/api/java/Fixedpoint.java index 4710368aa..57e1e105a 100644 --- a/src/api/java/Fixedpoint.java +++ b/src/api/java/Fixedpoint.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Fixedpoint.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Fixedpoint.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/FixedpointDecRefQueue.java b/src/api/java/FixedpointDecRefQueue.java index e52389b85..2ea40dd2c 100644 --- a/src/api/java/FixedpointDecRefQueue.java +++ b/src/api/java/FixedpointDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + FixedpointDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/FuncDecl.java b/src/api/java/FuncDecl.java index ada44bbd7..573ebd102 100644 --- a/src/api/java/FuncDecl.java +++ b/src/api/java/FuncDecl.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from FuncDecl.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + FuncDecl.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/FuncInterp.java b/src/api/java/FuncInterp.java index b7fa118e9..243ade71f 100644 --- a/src/api/java/FuncInterp.java +++ b/src/api/java/FuncInterp.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from FuncInterp.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + FuncInterp.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/FuncInterpDecRefQueue.java b/src/api/java/FuncInterpDecRefQueue.java index e2814a9b8..8bdad4ad5 100644 --- a/src/api/java/FuncInterpDecRefQueue.java +++ b/src/api/java/FuncInterpDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + FuncInterpDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/FuncInterpEntryDecRefQueue.java b/src/api/java/FuncInterpEntryDecRefQueue.java index 61488ec74..494c2695c 100644 --- a/src/api/java/FuncInterpEntryDecRefQueue.java +++ b/src/api/java/FuncInterpEntryDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + FuncInterpEntryDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Global.java b/src/api/java/Global.java index 33a828fb8..b97e48721 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -1,7 +1,19 @@ /** - * Global.java - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Global.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Goal.java b/src/api/java/Goal.java index c486a57b3..aba8b0149 100644 --- a/src/api/java/Goal.java +++ b/src/api/java/Goal.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Goal.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Goal.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/GoalDecRefQueue.java b/src/api/java/GoalDecRefQueue.java index 0c7b8f5d9..45992170f 100644 --- a/src/api/java/GoalDecRefQueue.java +++ b/src/api/java/GoalDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + GoalDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/IDecRefQueue.java b/src/api/java/IDecRefQueue.java index ddb679910..2190f8e4d 100644 --- a/src/api/java/IDecRefQueue.java +++ b/src/api/java/IDecRefQueue.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from IDecRefQueue.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + IDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/IntExpr.java b/src/api/java/IntExpr.java index 78cc15f90..2e90c3cbf 100644 --- a/src/api/java/IntExpr.java +++ b/src/api/java/IntExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from IntExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + IntExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/IntNum.java b/src/api/java/IntNum.java index ebf237a2e..0fdcf1aa6 100644 --- a/src/api/java/IntNum.java +++ b/src/api/java/IntNum.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from IntNum.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + IntNum.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/IntSort.java b/src/api/java/IntSort.java index 44e48ccd1..bcfc730c4 100644 --- a/src/api/java/IntSort.java +++ b/src/api/java/IntSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from IntSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + IntSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/IntSymbol.java b/src/api/java/IntSymbol.java index 113b507c3..b0f1af685 100644 --- a/src/api/java/IntSymbol.java +++ b/src/api/java/IntSymbol.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from IntSymbol.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + IntSymbol.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/InterpolationContext.java b/src/api/java/InterpolationContext.java index 067871324..3e9996b3e 100644 --- a/src/api/java/InterpolationContext.java +++ b/src/api/java/InterpolationContext.java @@ -1,6 +1,20 @@ /** - * - */ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + InterpolationContext.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ + package com.microsoft.z3; import java.util.Map; diff --git a/src/api/java/ListSort.java b/src/api/java/ListSort.java index af1645187..52cb1a179 100644 --- a/src/api/java/ListSort.java +++ b/src/api/java/ListSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ListSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ListSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Log.java b/src/api/java/Log.java index 99581cedb..254da1bc6 100644 --- a/src/api/java/Log.java +++ b/src/api/java/Log.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Log.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Log.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Model.java b/src/api/java/Model.java index 32247eb4a..11eed201e 100644 --- a/src/api/java/Model.java +++ b/src/api/java/Model.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Model.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Model.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ModelDecRefQueue.java b/src/api/java/ModelDecRefQueue.java index a0542714e..1200b29be 100644 --- a/src/api/java/ModelDecRefQueue.java +++ b/src/api/java/ModelDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ModelDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ParamDescrs.java b/src/api/java/ParamDescrs.java index 3b3e76e51..4afae9f76 100644 --- a/src/api/java/ParamDescrs.java +++ b/src/api/java/ParamDescrs.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from ParamDescrs.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ParamDescrs.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ParamDescrsDecRefQueue.java b/src/api/java/ParamDescrsDecRefQueue.java index 70806041d..a29565e8e 100644 --- a/src/api/java/ParamDescrsDecRefQueue.java +++ b/src/api/java/ParamDescrsDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ParamDescrsDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Params.java b/src/api/java/Params.java index cf3d8c759..bbe6d66cf 100644 --- a/src/api/java/Params.java +++ b/src/api/java/Params.java @@ -1,8 +1,20 @@ /** - * This file was automatically generated from Params.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Params.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ + package com.microsoft.z3; diff --git a/src/api/java/ParamsDecRefQueue.java b/src/api/java/ParamsDecRefQueue.java index 361fdf133..7d71feb8f 100644 --- a/src/api/java/ParamsDecRefQueue.java +++ b/src/api/java/ParamsDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ParamDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Pattern.java b/src/api/java/Pattern.java index cd9340c9d..797b387d0 100644 --- a/src/api/java/Pattern.java +++ b/src/api/java/Pattern.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Pattern.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Pattern.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Probe.java b/src/api/java/Probe.java index b68b0266f..17ad81b5c 100644 --- a/src/api/java/Probe.java +++ b/src/api/java/Probe.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Probe.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Probe.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/ProbeDecRefQueue.java b/src/api/java/ProbeDecRefQueue.java index 0ae0b0e8e..fda5d37b4 100644 --- a/src/api/java/ProbeDecRefQueue.java +++ b/src/api/java/ProbeDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + ProbeDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Quantifier.java b/src/api/java/Quantifier.java index 78a0fc03f..e9aeefcca 100644 --- a/src/api/java/Quantifier.java +++ b/src/api/java/Quantifier.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Quantifier.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Quantifier.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/RatNum.java b/src/api/java/RatNum.java index e1cb5b346..f937ea593 100644 --- a/src/api/java/RatNum.java +++ b/src/api/java/RatNum.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from RatNum.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + RatNum.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/RealExpr.java b/src/api/java/RealExpr.java index 20d603d9a..6188e2999 100644 --- a/src/api/java/RealExpr.java +++ b/src/api/java/RealExpr.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from RealExpr.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + RealExpr.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/RealSort.java b/src/api/java/RealSort.java index ce7295ead..d76823a0d 100644 --- a/src/api/java/RealSort.java +++ b/src/api/java/RealSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from RealSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + RealSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/RelationSort.java b/src/api/java/RelationSort.java index bdc4d7804..77f6c595b 100644 --- a/src/api/java/RelationSort.java +++ b/src/api/java/RelationSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from RelationSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + RelationSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/SetSort.java b/src/api/java/SetSort.java index a94a34b26..69126933a 100644 --- a/src/api/java/SetSort.java +++ b/src/api/java/SetSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from SetSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + SetSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Solver.java b/src/api/java/Solver.java index 3827de07a..e129189f9 100644 --- a/src/api/java/Solver.java +++ b/src/api/java/Solver.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Solver.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Solver.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/SolverDecRefQueue.java b/src/api/java/SolverDecRefQueue.java index 1c715716a..993c99621 100644 --- a/src/api/java/SolverDecRefQueue.java +++ b/src/api/java/SolverDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + SolverDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 381b9b0ae..7bcc7ce7e 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Sort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Sort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Statistics.java b/src/api/java/Statistics.java index c36020bd6..315feeaa2 100644 --- a/src/api/java/Statistics.java +++ b/src/api/java/Statistics.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Statistics.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Statistics.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/StatisticsDecRefQueue.java b/src/api/java/StatisticsDecRefQueue.java index d16bf3710..db3e32c86 100644 --- a/src/api/java/StatisticsDecRefQueue.java +++ b/src/api/java/StatisticsDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + StatisticsDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Status.java b/src/api/java/Status.java index e37631070..a08f47909 100644 --- a/src/api/java/Status.java +++ b/src/api/java/Status.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Status.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Status.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/StringSymbol.java b/src/api/java/StringSymbol.java index 951051aa0..09273c946 100644 --- a/src/api/java/StringSymbol.java +++ b/src/api/java/StringSymbol.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from StringSymbol.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + StringSymbol.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Symbol.java b/src/api/java/Symbol.java index 177409ec8..856c9b57e 100644 --- a/src/api/java/Symbol.java +++ b/src/api/java/Symbol.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Symbol.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Symbol.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Tactic.java b/src/api/java/Tactic.java index e62096715..6573a1407 100644 --- a/src/api/java/Tactic.java +++ b/src/api/java/Tactic.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Tactic.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Tactic.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/TacticDecRefQueue.java b/src/api/java/TacticDecRefQueue.java index 50fba156e..5557d03b8 100644 --- a/src/api/java/TacticDecRefQueue.java +++ b/src/api/java/TacticDecRefQueue.java @@ -1,7 +1,19 @@ /** - * Copyright (c) 2012 Microsoft Corporation - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + TacticDecRefQueue.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/TupleSort.java b/src/api/java/TupleSort.java index 554581d0f..523f8d676 100644 --- a/src/api/java/TupleSort.java +++ b/src/api/java/TupleSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from TupleSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + TupleSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/UninterpretedSort.java b/src/api/java/UninterpretedSort.java index 51df17543..07e4707f5 100644 --- a/src/api/java/UninterpretedSort.java +++ b/src/api/java/UninterpretedSort.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from UninterpretedSort.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + UninterpretedSort.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Version.java b/src/api/java/Version.java index b96fb50f9..3f019390b 100644 --- a/src/api/java/Version.java +++ b/src/api/java/Version.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Version.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Version.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Z3Exception.java b/src/api/java/Z3Exception.java index 24dc586d4..2522db627 100644 --- a/src/api/java/Z3Exception.java +++ b/src/api/java/Z3Exception.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Z3Exception.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Z3Exception.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; diff --git a/src/api/java/Z3Object.java b/src/api/java/Z3Object.java index 6c2c11e25..03cfcd625 100644 --- a/src/api/java/Z3Object.java +++ b/src/api/java/Z3Object.java @@ -1,8 +1,19 @@ /** - * This file was automatically generated from Z3Object.cs - * w/ further modifications by: - * @author Christoph M. Wintersteiger (cwinter) - **/ +Copyright (c) 2012-2014 Microsoft Corporation + +Module Name: + + Z3Object.java + +Abstract: + +Author: + + @author Christoph Wintersteiger (cwinter) 2012-03-15 + +Notes: + +**/ package com.microsoft.z3; From 6e18f44d991344fc444b21c13e4c2233334ab6d8 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Wed, 22 Oct 2014 10:42:23 -0700 Subject: [PATCH 078/117] fixed error check in read_interpolation_problem --- src/api/api_interp.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index dbf68da38..63ecc6c24 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -617,7 +617,7 @@ extern "C" { } for (unsigned j = 0; j < num - 1; j++) - if (read_parents[j] == SHRT_MIN){ + if (read_parents[j] == SHRT_MAX){ read_error << "formula " << j + 1 << ": unreferenced"; goto fail; } @@ -717,4 +717,4 @@ Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx, __in unsigned incremental, __in unsigned num_theory, __in_ecount(num_theory) Z3_ast *theory); -#endif \ No newline at end of file +#endif From 5454e389355f3a98e82ccd03815cf058458190fd Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Wed, 22 Oct 2014 10:43:04 -0700 Subject: [PATCH 079/117] replaced check_interpolants option with interp.check --- src/cmd_context/basic_cmds.cpp | 6 ------ src/cmd_context/cmd_context.cpp | 8 -------- src/cmd_context/cmd_context.h | 2 -- src/cmd_context/context_params.cpp | 5 ----- src/cmd_context/context_params.h | 1 - src/cmd_context/interpolant_cmds.cpp | 2 +- src/interp/iz3params.pyg | 1 + 7 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 836ade9ce..a80c5bc6c 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -241,7 +241,6 @@ protected: symbol m_produce_models; symbol m_produce_assignments; symbol m_produce_interpolants; - symbol m_check_interpolants; symbol m_regular_output_channel; symbol m_diagnostic_output_channel; symbol m_random_seed; @@ -256,7 +255,6 @@ protected: s == m_print_success || s == m_print_warning || s == m_expand_definitions || s == m_interactive_mode || s == m_produce_proofs || s == m_produce_unsat_cores || s == m_produce_models || s == m_produce_assignments || s == m_produce_interpolants || - s == m_check_interpolants || s == m_regular_output_channel || s == m_diagnostic_output_channel || s == m_random_seed || s == m_verbosity || s == m_global_decls; } @@ -275,7 +273,6 @@ public: m_produce_models(":produce-models"), m_produce_assignments(":produce-assignments"), m_produce_interpolants(":produce-interpolants"), - m_check_interpolants(":check-interpolants"), m_regular_output_channel(":regular-output-channel"), m_diagnostic_output_channel(":diagnostic-output-channel"), m_random_seed(":random-seed"), @@ -347,9 +344,6 @@ class set_option_cmd : public set_get_option_cmd { check_not_initialized(ctx, m_produce_interpolants); ctx.set_produce_interpolants(to_bool(value)); } - else if (m_option == m_check_interpolants) { - ctx.set_check_interpolants(to_bool(value)); - } else if (m_option == m_produce_unsat_cores) { check_not_initialized(ctx, m_produce_unsat_cores); ctx.set_produce_unsat_cores(to_bool(value)); diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index ce2838aba..731608524 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -397,10 +397,6 @@ void cmd_context::set_produce_interpolants(bool f) { // set_solver_factory(mk_smt_solver_factory()); } -void cmd_context::set_check_interpolants(bool f) { - m_params.m_check_interpolants = f; -} - bool cmd_context::produce_models() const { return m_params.m_model; } @@ -414,10 +410,6 @@ bool cmd_context::produce_interpolants() const { return m_params.m_proof; } -bool cmd_context::check_interpolants() const { - return m_params.m_check_interpolants; -} - bool cmd_context::produce_unsat_cores() const { return m_params.m_unsat_core; } diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index e34975183..8ad07e8cc 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -279,7 +279,6 @@ public: bool produce_models() const; bool produce_proofs() const; bool produce_interpolants() const; - bool check_interpolants() const; bool produce_unsat_cores() const; bool well_sorted_check_enabled() const; bool validate_model_enabled() const; @@ -287,7 +286,6 @@ public: void set_produce_unsat_cores(bool flag); void set_produce_proofs(bool flag); void set_produce_interpolants(bool flag); - void set_check_interpolants(bool flag); bool produce_assignments() const { return m_produce_assignments; } void set_produce_assignments(bool flag) { m_produce_assignments = flag; } void set_status(status st) { m_status = st; } diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 254a1d931..f87c8d264 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -61,9 +61,6 @@ void context_params::set(char const * param, char const * value) { else if (p == "proof") { set_bool(m_proof, param, value); } - else if (p == "check_interpolants") { - set_bool(m_check_interpolants, param, value); - } else if (p == "model") { set_bool(m_model, param, value); } @@ -105,7 +102,6 @@ void context_params::updt_params(params_ref const & p) { m_well_sorted_check = p.get_bool("type_check", p.get_bool("well_sorted_check", true)); m_auto_config = p.get_bool("auto_config", true); m_proof = p.get_bool("proof", false); - m_check_interpolants = p.get_bool("check_interpolants", false); m_model = p.get_bool("model", true); m_model_validate = p.get_bool("model_validate", false); m_trace = p.get_bool("trace", false); @@ -120,7 +116,6 @@ void context_params::collect_param_descrs(param_descrs & d) { d.insert("well_sorted_check", CPK_BOOL, "type checker", "true"); d.insert("type_check", CPK_BOOL, "type checker (alias for well_sorted_check)", "true"); d.insert("auto_config", CPK_BOOL, "use heuristics to automatically select solver and configure it", "true"); - d.insert("check_interpolants", CPK_BOOL, "check correctness of interpolants", "false"); d.insert("model_validate", CPK_BOOL, "validate models produced by solvers", "false"); d.insert("trace", CPK_BOOL, "trace generation for VCC", "false"); d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log"); diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index e26fd3fe5..506e559db 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -30,7 +30,6 @@ public: bool m_auto_config; bool m_proof; bool m_interpolants; - bool m_check_interpolants; bool m_debug_ref_count; bool m_trace; std::string m_trace_file_name; diff --git a/src/cmd_context/interpolant_cmds.cpp b/src/cmd_context/interpolant_cmds.cpp index cb83b52f6..42646a99d 100644 --- a/src/cmd_context/interpolant_cmds.cpp +++ b/src/cmd_context/interpolant_cmds.cpp @@ -65,7 +65,7 @@ static void show_interpolant_and_maybe_check(cmd_context & ctx, s.cleanup(); // verify, for the paranoid... - if(check || ctx.check_interpolants()){ + if(check || interp_params(m_params).check()){ std::ostringstream err; ast_manager &_m = ctx.m(); diff --git a/src/interp/iz3params.pyg b/src/interp/iz3params.pyg index 5b574c859..3116a18db 100644 --- a/src/interp/iz3params.pyg +++ b/src/interp/iz3params.pyg @@ -2,4 +2,5 @@ def_module_params('interp', description='interpolation parameters', export=True, params=(('profile', BOOL, False, '(INTERP) profile interpolation'), + ('check', BOOL, False, '(INTERP) check interpolants'), )) From 31a017e99e1569b3913bd260816a3b9a45d44b3f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 22 Oct 2014 19:47:50 +0100 Subject: [PATCH 080/117] FPA: standard function names consistency, improved error messages, bugfixes. Signed-off-by: Christoph M. Wintersteiger --- src/ast/float_decl_plugin.cpp | 308 +++++++++++++++------------- src/ast/float_decl_plugin.h | 45 ++-- src/ast/fpa/fpa2bv_converter.cpp | 88 ++++++-- src/ast/fpa/fpa2bv_converter.h | 9 +- src/ast/fpa/fpa2bv_rewriter.h | 18 +- src/ast/rewriter/float_rewriter.cpp | 41 ++-- src/ast/rewriter/float_rewriter.h | 9 +- 7 files changed, 303 insertions(+), 215 deletions(-) diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index 5466df069..f51101d79 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -40,11 +40,10 @@ void float_decl_plugin::set_manager(ast_manager * m, family_id id) { SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. m_manager->inc_ref(m_int_sort); - if (m_manager->has_plugin(symbol("bv"))) { - // bv plugin is optional, so m_bv_plugin may be 0 + // BV is not optional anymore. + SASSERT(m_manager->has_plugin(symbol("bv"))); m_bv_fid = m_manager->mk_family_id("bv"); m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); - } } float_decl_plugin::~float_decl_plugin() { @@ -103,6 +102,18 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) { m_fm.mk_nan(ebits, sbits, val); return true; } + else if (is_app_of(n, m_family_id, OP_FLOAT_PLUS_ZERO)) { + unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); + unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); + m_fm.mk_pzero(ebits, sbits, val); + return true; + } + else if (is_app_of(n, m_family_id, OP_FLOAT_MINUS_ZERO)) { + unsigned ebits = to_app(n)->get_decl()->get_range()->get_parameter(0).get_int(); + unsigned sbits = to_app(n)->get_decl()->get_range()->get_parameter(1).get_int(); + m_fm.mk_nzero(ebits, sbits, val); + return true; + } return false; } @@ -156,7 +167,7 @@ sort * float_decl_plugin::mk_float_sort(unsigned ebits, unsigned sbits) { parameter ps[2] = { p1, p2 }; sort_size sz; sz = sort_size::mk_very_big(); // TODO: refine - return m_manager->mk_sort(symbol("FP"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps)); + return m_manager->mk_sort(symbol("FloatingPoint"), sort_info(m_family_id, FLOAT_SORT, sz, 2, ps)); } sort * float_decl_plugin::mk_rm_sort() { @@ -176,6 +187,14 @@ sort * float_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, paramete return mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); case ROUNDING_MODE_SORT: return mk_rm_sort(); + case FLOAT16_SORT: + return mk_float_sort(5, 11); + case FLOAT32_SORT: + return mk_float_sort(8, 24); + case FLOAT64_SORT: + return mk_float_sort(11, 53); + case FLOAT128_SORT: + return mk_float_sort(15, 133); default: m_manager->raise_exception("unknown floating point theory sort"); return 0; @@ -229,17 +248,18 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par unsigned ebits = s->get_parameter(0).get_int(); unsigned sbits = s->get_parameter(1).get_int(); scoped_mpf val(m_fm); - if (k == OP_FLOAT_NAN) { - m_fm.mk_nan(ebits, sbits, val); + + switch (k) + { + case OP_FLOAT_NAN: m_fm.mk_nan(ebits, sbits, val); SASSERT(m_fm.is_nan(val)); + break; + case OP_FLOAT_MINUS_INF: m_fm.mk_ninf(ebits, sbits, val); break; + case OP_FLOAT_PLUS_INF: m_fm.mk_pinf(ebits, sbits, val); break; + case OP_FLOAT_MINUS_ZERO: m_fm.mk_nzero(ebits, sbits, val); break; + case OP_FLOAT_PLUS_ZERO: m_fm.mk_pzero(ebits, sbits, val); break; } - else if (k == OP_FLOAT_MINUS_INF) { - m_fm.mk_ninf(ebits, sbits, val); - } - else { - SASSERT(k == OP_FLOAT_PLUS_INF); - m_fm.mk_pinf(ebits, sbits, val); - } + return mk_value_decl(val); } @@ -248,14 +268,14 @@ func_decl * float_decl_plugin::mk_bin_rel_decl(decl_kind k, unsigned num_paramet if (arity != 2) m_manager->raise_exception("invalid number of arguments to floating point relation"); if (domain[0] != domain[1] || !is_float_sort(domain[0])) - m_manager->raise_exception("sort mismatch"); + m_manager->raise_exception("sort mismatch, expected equal FloatingPoint sorts as arguments"); symbol name; switch (k) { - case OP_FLOAT_EQ: name = "=="; break; - case OP_FLOAT_LT: name = "<"; break; - case OP_FLOAT_GT: name = ">"; break; - case OP_FLOAT_LE: name = "<="; break; - case OP_FLOAT_GE: name = ">="; break; + case OP_FLOAT_EQ: name = "fp.eq"; break; + case OP_FLOAT_LT: name = "fp.lt"; break; + case OP_FLOAT_GT: name = "fp.gt"; break; + case OP_FLOAT_LE: name = "fp.lte"; break; + case OP_FLOAT_GE: name = "fp.gte"; break; default: UNREACHABLE(); break; @@ -270,17 +290,18 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param if (arity != 1) m_manager->raise_exception("invalid number of arguments to floating point relation"); if (!is_float_sort(domain[0])) - m_manager->raise_exception("sort mismatch"); + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); symbol name; switch (k) { - case OP_FLOAT_IS_ZERO: name = "isZero"; break; - case OP_FLOAT_IS_NZERO: name = "isNZero"; break; - case OP_FLOAT_IS_PZERO: name = "isPZero"; break; - case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus"; break; - case OP_FLOAT_IS_NAN: name = "isNaN"; break; - case OP_FLOAT_IS_INF: name = "isInfinite"; break; - case OP_FLOAT_IS_NORMAL: name = "isNormal"; break; - case OP_FLOAT_IS_SUBNORMAL: name = "isSubnormal"; break; + case OP_FLOAT_IS_ZERO: name = "fp.isZero"; break; + case OP_FLOAT_IS_NZERO: name = "fp.isNZero"; break; + case OP_FLOAT_IS_PZERO: name = "fp.isPZero"; break; + case OP_FLOAT_IS_NEGATIVE: name = "fp.isNegative"; break; + case OP_FLOAT_IS_POSITIVE: name = "fp.isPositive"; break; + case OP_FLOAT_IS_NAN: name = "fp.isNaN"; break; + case OP_FLOAT_IS_INF: name = "fp.isInfinite"; break; + case OP_FLOAT_IS_NORMAL: name = "fp.isNormal"; break; + case OP_FLOAT_IS_SUBNORMAL: name = "fp.isSubnormal"; break; default: UNREACHABLE(); break; @@ -293,11 +314,11 @@ func_decl * float_decl_plugin::mk_unary_decl(decl_kind k, unsigned num_parameter if (arity != 1) m_manager->raise_exception("invalid number of arguments to floating point operator"); if (!is_float_sort(domain[0])) - m_manager->raise_exception("sort mismatch"); + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); symbol name; switch (k) { - case OP_FLOAT_ABS: name = "abs"; break; - case OP_FLOAT_UMINUS: name = "-"; break; + case OP_FLOAT_ABS: name = "fp.abs"; break; + case OP_FLOAT_NEG: name = "fp.neg"; break; default: UNREACHABLE(); break; @@ -310,12 +331,12 @@ func_decl * float_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_paramete if (arity != 2) m_manager->raise_exception("invalid number of arguments to floating point operator"); if (domain[0] != domain[1] || !is_float_sort(domain[0])) - m_manager->raise_exception("sort mismatch"); + m_manager->raise_exception("sort mismatch, expected arguments of equal FloatingPoint sorts"); symbol name; switch (k) { - case OP_FLOAT_REM: name = "remainder"; break; - case OP_FLOAT_MIN: name = "fp.min"; break; - case OP_FLOAT_MAX: name = "fp.max"; break; + case OP_FLOAT_REM: name = "fp.rem"; break; + case OP_FLOAT_MIN: name = "fp.min"; break; + case OP_FLOAT_MAX: name = "fp.max"; break; default: UNREACHABLE(); break; @@ -327,14 +348,16 @@ func_decl * float_decl_plugin::mk_rm_binary_decl(decl_kind k, unsigned num_param unsigned arity, sort * const * domain, sort * range) { if (arity != 3) m_manager->raise_exception("invalid number of arguments to floating point operator"); - if (!is_rm_sort(domain[0]) || domain[1] != domain[2] || !is_float_sort(domain[1])) - m_manager->raise_exception("sort mismatch"); + if (!is_rm_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); + if (domain[1] != domain[2] || !is_float_sort(domain[1])) + m_manager->raise_exception("sort mismatch, expected arguments 1 and 2 of equal FloatingPoint sorts"); symbol name; switch (k) { - case OP_FLOAT_ADD: name = "+"; break; - case OP_FLOAT_SUB: name = "-"; break; - case OP_FLOAT_MUL: name = "*"; break; - case OP_FLOAT_DIV: name = "/"; break; + case OP_FLOAT_ADD: name = "fp.add"; break; + case OP_FLOAT_SUB: name = "fp.sub"; break; + case OP_FLOAT_MUL: name = "fp.mul"; break; + case OP_FLOAT_DIV: name = "fp.div"; break; default: UNREACHABLE(); break; @@ -346,12 +369,14 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame unsigned arity, sort * const * domain, sort * range) { if (arity != 2) m_manager->raise_exception("invalid number of arguments to floating point operator"); - if (!is_rm_sort(domain[0]) || !is_float_sort(domain[1])) - m_manager->raise_exception("sort mismatch"); + if (!is_rm_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument"); + if (!is_float_sort(domain[1])) + m_manager->raise_exception("sort mismatch, expected FloatingPoint as second argument"); symbol name; switch (k) { - case OP_FLOAT_SQRT: name = "squareRoot"; break; - case OP_FLOAT_ROUND_TO_INTEGRAL: name = "roundToIntegral"; break; + case OP_FLOAT_SQRT: name = "fp.sqrt"; break; + case OP_FLOAT_ROUND_TO_INTEGRAL: name = "fp.roundToIntegral"; break; default: UNREACHABLE(); break; @@ -359,13 +384,15 @@ func_decl * float_decl_plugin::mk_rm_unary_decl(decl_kind k, unsigned num_parame return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_fused_ma(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * float_decl_plugin::mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (arity != 4) m_manager->raise_exception("invalid number of arguments to fused_ma operator"); - if (!is_rm_sort(domain[0]) || domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1])) - m_manager->raise_exception("sort mismatch"); - symbol name("fusedMA"); + if (!is_rm_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected RoundingMode as first argument"); + if (domain[1] != domain[2] || domain[1] != domain[3] || !is_float_sort(domain[1])) + m_manager->raise_exception("sort mismatch, expected arguments 1,2,3 of equal FloatingPoint sort"); + symbol name("fp.fma"); return m_manager->mk_func_decl(name, arity, domain, domain[1], func_decl_info(m_family_id, k)); } @@ -375,12 +402,13 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, is_sort_of(domain[0], m_bv_fid, BV_SORT) && is_sort_of(domain[1], m_bv_fid, BV_SORT) && is_sort_of(domain[2], m_bv_fid, BV_SORT)) { - // When the bv_decl_plugin is installed, then we know how to convert 3 bit-vectors into a float! + // 3 BVs -> 1 FP sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1); - symbol name("asFloat"); + symbol name("fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } else if (m_bv_plugin && arity == 1 && is_sort_of(domain[0], m_bv_fid, BV_SORT)) { + // 1 BV -> 1 FP if (num_parameters != 2) m_manager->raise_exception("invalid number of parameters to to_fp"); if (!parameters[0].is_int() || !parameters[1].is_int()) @@ -389,37 +417,67 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters, int sbits = parameters[1].get_int(); sort * fp = mk_float_sort(ebits, sbits); - symbol name("asFloat"); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + } + else if (m_bv_plugin && arity == 2 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_bv_fid, BV_SORT)) { + // Rounding + 1 BV -> 1 FP + if (num_parameters != 2) + m_manager->raise_exception("invalid number of parameters to to_fp"); + if (!parameters[0].is_int() || !parameters[1].is_int()) + m_manager->raise_exception("invalid parameter type to to_fp"); + int ebits = parameters[0].get_int(); + int sbits = parameters[1].get_int(); + + sort * fp = mk_float_sort(ebits, sbits); + symbol name("to_fp"); + return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); + } + else if (arity == 2 && + is_sort_of(domain[0], m_family_id, ROUNDING_MODE_SORT) && + is_sort_of(domain[1], m_family_id, FLOAT_SORT)) { + // Rounding + 1 FP -> 1 FP + if (num_parameters != 2) + m_manager->raise_exception("invalid number of parameters to to_fp"); + if (!parameters[0].is_int() || !parameters[1].is_int()) + m_manager->raise_exception("invalid parameter type to to_fp"); + int ebits = parameters[0].get_int(); + int sbits = parameters[1].get_int(); + if (!is_rm_sort(domain[0])) + m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); + if (!is_sort_of(domain[1], m_family_id, FLOAT_SORT)) + m_manager->raise_exception("sort mismatch, expected second argument of FloatingPoint sort"); + + sort * fp = mk_float_sort(ebits, sbits); + symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } else { - // .. Otherwise we only know how to convert rationals/reals. + // 1 Real -> 1 FP if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) - m_manager->raise_exception("expecting two integer parameters to asFloat"); + m_manager->raise_exception("expecting two integer parameters to to_fp"); if (arity != 2 && arity != 3) - m_manager->raise_exception("invalid number of arguments to asFloat operator"); + m_manager->raise_exception("invalid number of arguments to to_fp operator"); if (arity == 3 && domain[2] != m_int_sort) - m_manager->raise_exception("sort mismatch"); - if (!is_rm_sort(domain[0]) || - !(domain[1] == m_real_sort || is_sort_of(domain[1], m_family_id, FLOAT_SORT))) - m_manager->raise_exception("sort mismatch"); + m_manager->raise_exception("sort mismatch, expected second argument of Int sort"); + if (domain[1] != m_real_sort) + m_manager->raise_exception("sort mismatch, expected second argument of Real sort"); sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); - symbol name("asFloat"); + symbol name("to_fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters)); } } -func_decl * float_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * float_decl_plugin::mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { - if (!m_bv_plugin) - m_manager->raise_exception("asIEEEBV unsupported; use a logic with BV support"); if (arity != 1) m_manager->raise_exception("invalid number of arguments to asIEEEBV"); if (!is_float_sort(domain[0])) - m_manager->raise_exception("sort mismatch"); - - // When the bv_decl_plugin is installed, then we know how to convert a float to an IEEE bit-vector. + m_manager->raise_exception("sort mismatch, expected argument of FloatingPoint sort"); + unsigned float_sz = domain[0]->get_parameter(0).get_int() + domain[0]->get_parameter(1).get_int(); parameter ps[] = { parameter(float_sz) }; sort * bv_srt = m_bv_plugin->mk_sort(m_bv_fid, 1, ps); @@ -429,41 +487,34 @@ func_decl * float_decl_plugin::mk_to_ieee_bv(decl_kind k, unsigned num_parameter func_decl * float_decl_plugin::mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { - if (!m_bv_plugin) - m_manager->raise_exception("fp unsupported; use a logic with BV support"); if (arity != 3) m_manager->raise_exception("invalid number of arguments to fp"); if (!is_sort_of(domain[0], m_bv_fid, BV_SORT) || !is_sort_of(domain[1], m_bv_fid, BV_SORT) || !is_sort_of(domain[2], m_bv_fid, BV_SORT)) - m_manager->raise_exception("sort mismtach"); + m_manager->raise_exception("sort mismatch"); sort * fp = mk_float_sort(domain[1]->get_parameter(0).get_int(), domain[2]->get_parameter(0).get_int() + 1); symbol name("fp"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, +func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { if (!m_bv_plugin) m_manager->raise_exception("to_fp_unsigned unsupported; use a logic with BV support"); if (arity != 2) m_manager->raise_exception("invalid number of arguments to to_fp_unsigned"); if (is_rm_sort(domain[0])) - m_manager->raise_exception("sort mismtach"); + m_manager->raise_exception("sort mismatch, expected first argument of RoundingMode sort"); if (!is_sort_of(domain[1], m_bv_fid, BV_SORT)) - m_manager->raise_exception("sort mismtach"); + m_manager->raise_exception("sort mismatch, expected second argument of BV sort"); sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int()); - symbol name("to_fp_unsigned"); + symbol name("fp.t_ubv"); return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k)); } -func_decl * float_decl_plugin::mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range) { - NOT_IMPLEMENTED_YET(); -} - func_decl * float_decl_plugin::mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { NOT_IMPLEMENTED_YET(); @@ -498,14 +549,15 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_FLOAT_IS_ZERO: case OP_FLOAT_IS_NZERO: case OP_FLOAT_IS_PZERO: - case OP_FLOAT_IS_SIGN_MINUS: + case OP_FLOAT_IS_NEGATIVE: + case OP_FLOAT_IS_POSITIVE: case OP_FLOAT_IS_NAN: case OP_FLOAT_IS_INF: case OP_FLOAT_IS_NORMAL: case OP_FLOAT_IS_SUBNORMAL: return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_ABS: - case OP_FLOAT_UMINUS: + case OP_FLOAT_NEG: return mk_unary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_REM: case OP_FLOAT_MIN: @@ -517,20 +569,18 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_SUB: if (arity == 1) - return mk_unary_decl(OP_FLOAT_UMINUS, num_parameters, parameters, arity, domain, range); + return mk_unary_decl(OP_FLOAT_NEG, num_parameters, parameters, arity, domain, range); else return mk_rm_binary_decl(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_SQRT: case OP_FLOAT_ROUND_TO_INTEGRAL: return mk_rm_unary_decl(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_FUSED_MA: - return mk_fused_ma(k, num_parameters, parameters, arity, domain, range); - case OP_TO_IEEE_BV: - return mk_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_FMA: + return mk_fma(k, num_parameters, parameters, arity, domain, range); + case OP_FLOAT_TO_IEEE_BV: + return mk_float_to_ieee_bv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_FP: return mk_from3bv(k, num_parameters, parameters, arity, domain, range); - case OP_FLOAT_TO_FP_UNSIGNED: - return mk_to_fp_unsigned(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_UBV: return mk_to_ubv(k, num_parameters, parameters, arity, domain, range); case OP_FLOAT_TO_SBV: @@ -544,8 +594,11 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters } void float_decl_plugin::get_op_names(svector & op_names, symbol const & logic) { - op_names.push_back(builtin_name("plusInfinity", OP_FLOAT_PLUS_INF)); - op_names.push_back(builtin_name("minusInfinity", OP_FLOAT_MINUS_INF)); + // These are the operators from the final draft of the SMT FloatingPoint standard + op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF)); + op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF)); + op_names.push_back(builtin_name("+zero", OP_FLOAT_PLUS_ZERO)); + op_names.push_back(builtin_name("-zero", OP_FLOAT_MINUS_ZERO)); op_names.push_back(builtin_name("NaN", OP_FLOAT_NAN)); op_names.push_back(builtin_name("roundNearestTiesToEven", OP_RM_NEAREST_TIES_TO_EVEN)); @@ -554,46 +607,6 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("roundTowardNegative", OP_RM_TOWARD_NEGATIVE)); op_names.push_back(builtin_name("roundTowardZero", OP_RM_TOWARD_ZERO)); - op_names.push_back(builtin_name("+", OP_FLOAT_ADD)); - op_names.push_back(builtin_name("-", OP_FLOAT_SUB)); - op_names.push_back(builtin_name("/", OP_FLOAT_DIV)); - op_names.push_back(builtin_name("*", OP_FLOAT_MUL)); - - op_names.push_back(builtin_name("abs", OP_FLOAT_ABS)); - op_names.push_back(builtin_name("remainder", OP_FLOAT_REM)); - op_names.push_back(builtin_name("fusedMA", OP_FLOAT_FUSED_MA)); - op_names.push_back(builtin_name("squareRoot", OP_FLOAT_SQRT)); - op_names.push_back(builtin_name("roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); - - op_names.push_back(builtin_name("==", OP_FLOAT_EQ)); - - op_names.push_back(builtin_name("<", OP_FLOAT_LT)); - op_names.push_back(builtin_name(">", OP_FLOAT_GT)); - op_names.push_back(builtin_name("<=", OP_FLOAT_LE)); - op_names.push_back(builtin_name(">=", OP_FLOAT_GE)); - - op_names.push_back(builtin_name("isNaN", OP_FLOAT_IS_NAN)); - op_names.push_back(builtin_name("isInfinite", OP_FLOAT_IS_INF)); - op_names.push_back(builtin_name("isZero", OP_FLOAT_IS_ZERO)); - op_names.push_back(builtin_name("isNZero", OP_FLOAT_IS_NZERO)); - op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO)); - op_names.push_back(builtin_name("isNormal", OP_FLOAT_IS_NORMAL)); - op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL)); - op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS)); - - // Disabled min/max, clashes with user-defined min/max functions - // op_names.push_back(builtin_name("min", OP_FLOAT_MIN)); - // op_names.push_back(builtin_name("max", OP_FLOAT_MAX)); - - op_names.push_back(builtin_name("asFloat", OP_TO_FLOAT)); - - if (m_bv_plugin) - op_names.push_back(builtin_name("asIEEEBV", OP_TO_IEEE_BV)); - - // These are the operators from the final draft of the SMT FloatingPoints standard - op_names.push_back(builtin_name("+oo", OP_FLOAT_PLUS_INF)); - op_names.push_back(builtin_name("-oo", OP_FLOAT_MINUS_INF)); - op_names.push_back(builtin_name("RNE", OP_RM_NEAREST_TIES_TO_EVEN)); op_names.push_back(builtin_name("RNA", OP_RM_NEAREST_TIES_TO_AWAY)); op_names.push_back(builtin_name("RTP", OP_RM_TOWARD_POSITIVE)); @@ -601,44 +614,47 @@ void float_decl_plugin::get_op_names(svector & op_names, symbol co op_names.push_back(builtin_name("RTZ", OP_RM_TOWARD_ZERO)); op_names.push_back(builtin_name("fp.abs", OP_FLOAT_ABS)); - op_names.push_back(builtin_name("fp.neg", OP_FLOAT_UMINUS)); + op_names.push_back(builtin_name("fp.neg", OP_FLOAT_NEG)); op_names.push_back(builtin_name("fp.add", OP_FLOAT_ADD)); op_names.push_back(builtin_name("fp.sub", OP_FLOAT_SUB)); op_names.push_back(builtin_name("fp.mul", OP_FLOAT_MUL)); op_names.push_back(builtin_name("fp.div", OP_FLOAT_DIV)); - op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FUSED_MA)); + op_names.push_back(builtin_name("fp.fma", OP_FLOAT_FMA)); op_names.push_back(builtin_name("fp.sqrt", OP_FLOAT_SQRT)); op_names.push_back(builtin_name("fp.rem", OP_FLOAT_REM)); - op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ)); + op_names.push_back(builtin_name("fp.roundToIntegral", OP_FLOAT_ROUND_TO_INTEGRAL)); + op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN)); + op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX)); op_names.push_back(builtin_name("fp.leq", OP_FLOAT_LE)); op_names.push_back(builtin_name("fp.lt", OP_FLOAT_LT)); op_names.push_back(builtin_name("fp.geq", OP_FLOAT_GE)); op_names.push_back(builtin_name("fp.gt", OP_FLOAT_GT)); + op_names.push_back(builtin_name("fp.eq", OP_FLOAT_EQ)); + op_names.push_back(builtin_name("fp.isNormal", OP_FLOAT_IS_NORMAL)); op_names.push_back(builtin_name("fp.isSubnormal", OP_FLOAT_IS_SUBNORMAL)); op_names.push_back(builtin_name("fp.isZero", OP_FLOAT_IS_ZERO)); op_names.push_back(builtin_name("fp.isInfinite", OP_FLOAT_IS_INF)); op_names.push_back(builtin_name("fp.isNaN", OP_FLOAT_IS_NAN)); - op_names.push_back(builtin_name("fp.min", OP_FLOAT_MIN)); - op_names.push_back(builtin_name("fp.max", OP_FLOAT_MAX)); - op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT)); + op_names.push_back(builtin_name("fp.isNegative", OP_FLOAT_IS_NEGATIVE)); + op_names.push_back(builtin_name("fp.isPositive", OP_FLOAT_IS_POSITIVE)); - if (m_bv_plugin) { - op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); - op_names.push_back(builtin_name("to_fp_unsigned", OP_FLOAT_TO_FP_UNSIGNED)); - op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); - op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - } + op_names.push_back(builtin_name("fp", OP_FLOAT_FP)); + op_names.push_back(builtin_name("fp.to_ubv", OP_FLOAT_TO_UBV)); + op_names.push_back(builtin_name("fp.to_sbv", OP_FLOAT_TO_SBV)); - // op_names.push_back(builtin_name("fp.toReal", ?)); + op_names.push_back(builtin_name("to_fp", OP_TO_FLOAT)); } void float_decl_plugin::get_sort_names(svector & sort_names, symbol const & logic) { - sort_names.push_back(builtin_name("FP", FLOAT_SORT)); + sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT)); sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT)); - // In the SMT FPA final draft, FP is called FloatingPoint - sort_names.push_back(builtin_name("FloatingPoint", FLOAT_SORT)); + // The final theory supports three common FloatingPoint sorts + sort_names.push_back(builtin_name("Float16", FLOAT16_SORT)); + sort_names.push_back(builtin_name("Float32", FLOAT32_SORT)); + sort_names.push_back(builtin_name("Float64", FLOAT64_SORT)); + sort_names.push_back(builtin_name("Float128", FLOAT128_SORT)); } expr * float_decl_plugin::get_some_value(sort * s) { @@ -662,6 +678,8 @@ bool float_decl_plugin::is_value(app * e) const { case OP_FLOAT_VALUE: case OP_FLOAT_PLUS_INF: case OP_FLOAT_MINUS_INF: + case OP_FLOAT_PLUS_ZERO: + case OP_FLOAT_MINUS_ZERO: case OP_FLOAT_NAN: return true; case OP_TO_FLOAT: diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index 58c37080d..c7ec04932 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -27,7 +27,11 @@ Revision History: enum float_sort_kind { FLOAT_SORT, - ROUNDING_MODE_SORT + ROUNDING_MODE_SORT, + FLOAT16_SORT, + FLOAT32_SORT, + FLOAT64_SORT, + FLOAT128_SORT }; enum float_op_kind { @@ -37,22 +41,23 @@ enum float_op_kind { OP_RM_TOWARD_NEGATIVE, OP_RM_TOWARD_ZERO, - OP_FLOAT_VALUE, OP_FLOAT_PLUS_INF, OP_FLOAT_MINUS_INF, OP_FLOAT_NAN, + OP_FLOAT_PLUS_ZERO, + OP_FLOAT_MINUS_ZERO, OP_FLOAT_ADD, OP_FLOAT_SUB, - OP_FLOAT_UMINUS, + OP_FLOAT_NEG, OP_FLOAT_MUL, OP_FLOAT_DIV, OP_FLOAT_REM, OP_FLOAT_ABS, OP_FLOAT_MIN, OP_FLOAT_MAX, - OP_FLOAT_FUSED_MA, // x*y + z + OP_FLOAT_FMA, // x*y + z OP_FLOAT_SQRT, OP_FLOAT_ROUND_TO_INTEGRAL, @@ -68,13 +73,14 @@ enum float_op_kind { OP_FLOAT_IS_SUBNORMAL, OP_FLOAT_IS_PZERO, OP_FLOAT_IS_NZERO, - OP_FLOAT_IS_SIGN_MINUS, + OP_FLOAT_IS_NEGATIVE, + OP_FLOAT_IS_POSITIVE, OP_TO_FLOAT, - OP_TO_IEEE_BV, + OP_FLOAT_TO_IEEE_BV, OP_FLOAT_FP, - OP_FLOAT_TO_FP_UNSIGNED, + OP_FLOAT_TO_FP, OP_FLOAT_TO_UBV, OP_FLOAT_TO_SBV, OP_FLOAT_TO_REAL, @@ -125,16 +131,14 @@ class float_decl_plugin : public decl_plugin { unsigned arity, sort * const * domain, sort * range); func_decl * mk_rm_unary_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - func_decl * mk_fused_ma(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + func_decl * mk_fma(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_float(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - func_decl * mk_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); + func_decl * mk_float_to_ieee_bv(decl_kind k, unsigned num_parameters, parameter const * parameters, + unsigned arity, sort * const * domain, sort * range); func_decl * mk_from3bv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); - func_decl * mk_to_fp_unsigned(decl_kind k, unsigned num_parameters, parameter const * parameters, - unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_ubv(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range); func_decl * mk_to_sbv(decl_kind k, unsigned num_parameters, parameter const * parameters, @@ -195,6 +199,7 @@ public: family_id get_fid() const { return m_fid; } family_id get_family_id() const { return m_fid; } arith_util & au() { return m_a_util; } + float_decl_plugin & plugin() { return *m_plugin; } sort * mk_float_sort(unsigned ebits, unsigned sbits); sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); } @@ -242,16 +247,16 @@ public: app * mk_mul(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_MUL, arg1, arg2, arg3); } app * mk_sub(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_SUB, arg1, arg2, arg3); } app * mk_div(expr * arg1, expr * arg2, expr * arg3) { return m().mk_app(m_fid, OP_FLOAT_DIV, arg1, arg2, arg3); } - app * mk_uminus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_UMINUS, arg1); } + app * mk_neg(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_NEG, arg1); } app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); } app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); } app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); } app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); } app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); } app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); } - app * mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) { + app * mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) { expr * args[4] = { arg1, arg2, arg3, arg4 }; - return m().mk_app(m_fid, OP_FLOAT_FUSED_MA, 4, args); + return m().mk_app(m_fid, OP_FLOAT_FMA, 4, args); } app * mk_float_eq(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_EQ, arg1, arg2); } @@ -267,11 +272,13 @@ public: app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); } app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); } app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); } - app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SIGN_MINUS, arg1); } + app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } + app * mk_is_positive(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_POSITIVE, arg1); } + app * mk_is_negative(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NEGATIVE, arg1); } - bool is_uminus(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_UMINUS); } + bool is_neg(expr * a) { return is_app_of(a, m_fid, OP_FLOAT_NEG); } - app * mk_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_TO_IEEE_BV, arg1); } + app * mk_float_to_ieee_bv(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_TO_IEEE_BV, arg1); } }; #endif diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index d6f362902..5f92b4d94 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -136,12 +136,13 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { unsigned sbits = m_util.get_sbits(srt); expr_ref sgn(m), s(m), e(m); - sort_ref s_sgn(m), s_sig(m), s_exp(m); - s_sgn = m_bv_util.mk_sort(1); - s_sig = m_bv_util.mk_sort(sbits-1); - s_exp = m_bv_util.mk_sort(ebits); #ifdef Z3DEBUG + sort_ref s_sgn(m), s_sig(m), s_exp(m); + s_sgn = m_bv_util.mk_sort(1); + s_sig = m_bv_util.mk_sort(sbits - 1); + s_exp = m_bv_util.mk_sort(ebits); + std::string p("fpa2bv"); std::string name = f->get_name().str(); @@ -149,9 +150,17 @@ void fpa2bv_converter::mk_const(func_decl * f, expr_ref & result) { s = m.mk_fresh_const((p + "_sig_" + name).c_str(), s_sig); e = m.mk_fresh_const((p + "_exp_" + name).c_str(), s_exp); #else - sgn = m.mk_fresh_const(0, s_sgn); - s = m.mk_fresh_const(0, s_sig); - e = m.mk_fresh_const(0, s_exp); + expr_ref bv(m); + unsigned bv_sz = 1 + ebits + (sbits - 1); + bv = m.mk_fresh_const(0, m_bv_util.mk_sort(bv_sz)); + + sgn = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, bv); + e = m_bv_util.mk_extract(bv_sz - 2, sbits - 1, bv); + s = m_bv_util.mk_extract(sbits - 2, 0, bv); + + SASSERT(m_bv_util.get_bv_size(sgn) == 1); + SASSERT(m_bv_util.get_bv_size(s) == sbits-1); + SASSERT(m_bv_util.get_bv_size(e) == ebits); #endif mk_triple(sgn, s, e, result); @@ -595,12 +604,12 @@ void fpa2bv_converter::mk_add(func_decl * f, unsigned num, expr * const * args, void fpa2bv_converter::mk_sub(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 3); expr_ref t(m); - mk_uminus(f, 1, &args[2], t); + mk_neg(f, 1, &args[2], t); expr * nargs[3] = { args[0], args[1], t }; mk_add(f, 3, nargs, result); } -void fpa2bv_converter::mk_uminus(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { +void fpa2bv_converter::mk_neg(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; split(args[0], sgn, s, e); @@ -906,7 +915,7 @@ void fpa2bv_converter::mk_div(func_decl * f, unsigned num, expr * const * args, TRACE("fpa2bv_div", tout << "DIV = " << mk_ismt2_pp(result, m) << std::endl; ); } -void fpa2bv_converter::mk_remainder(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { +void fpa2bv_converter::mk_rem(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 2); // Remainder is always exact, so there is no rounding mode. @@ -1114,7 +1123,7 @@ void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, mk_triple(r_sgn, r_sig, r_exp, result); } -void fpa2bv_converter::mk_fusedma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { +void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 4); // fusedma means (x * y) + z @@ -1835,9 +1844,18 @@ void fpa2bv_converter::mk_is_subnormal(func_decl * f, unsigned num, expr * const mk_is_denormal(args[0], result); } -void fpa2bv_converter::mk_is_sign_minus(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { +void fpa2bv_converter::mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); mk_is_neg(args[0], result); + TRACE("fpa2bv_is_negative", tout << "result = " << mk_ismt2_pp(result, m) << std::endl;); +} + +void fpa2bv_converter::mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + SASSERT(num == 1); + expr_ref t1(m), t2(m); + mk_is_nan(args[0], t1); + mk_is_pos(args[0], t2); + result = m.mk_and(m.mk_not(t1), t2); } void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { @@ -2123,7 +2141,7 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); expr * sgn, * s, * e; - split(args[0], sgn, s, e); + split(args[0], sgn, s, e); result = m_bv_util.mk_concat(m_bv_util.mk_concat(sgn, e), s); } @@ -2132,19 +2150,55 @@ void fpa2bv_converter::mk_fp(func_decl * f, unsigned num, expr * const * args, e mk_triple(args[0], args[2], args[1], result); } -void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { - NOT_IMPLEMENTED_YET(); -} - void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + SASSERT(num == 2); + SASSERT(f->get_num_parameters() == 1); + SASSERT(f->get_parameter(0).is_int()); + + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + int width = f->get_parameter(0).get_int(); + + expr * rm = args[0]; + expr * x = args[1]; + + expr * sgn, *s, *e; + split(x, sgn, s, e); + NOT_IMPLEMENTED_YET(); } void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + SASSERT(num == 2); + SASSERT(f->get_num_parameters() == 1); + SASSERT(f->get_parameter(0).is_int()); + + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + int width = f->get_parameter(0).get_int(); + + expr * rm = args[0]; + expr * x = args[1]; + + expr * sgn, *s, *e; + split(x, sgn, s, e); + NOT_IMPLEMENTED_YET(); } void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { + SASSERT(num == 1); + + unsigned ebits = m_util.get_ebits(f->get_range()); + unsigned sbits = m_util.get_sbits(f->get_range()); + int width = f->get_parameter(0).get_int(); + + expr * rm = args[0]; + expr * x = args[1]; + + expr * sgn, *s, *e; + split(x, sgn, s, e); + NOT_IMPLEMENTED_YET(); } diff --git a/src/ast/fpa/fpa2bv_converter.h b/src/ast/fpa/fpa2bv_converter.h index dcb508ffd..eb539d8ae 100644 --- a/src/ast/fpa/fpa2bv_converter.h +++ b/src/ast/fpa/fpa2bv_converter.h @@ -94,14 +94,14 @@ public: void mk_add(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_sub(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_uminus(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_neg(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_mul(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_div(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_remainder(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_rem(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_abs(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_fusedma(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_sqrt(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_round_to_integral(func_decl * f, unsigned num, expr * const * args, expr_ref & result); @@ -114,7 +114,8 @@ public: void mk_is_zero(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_nzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_pzero(func_decl * f, unsigned num, expr * const * args, expr_ref & result); - void mk_is_sign_minus(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_is_negative(func_decl * f, unsigned num, expr * const * args, expr_ref & result); + void mk_is_positive(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_nan(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_inf(func_decl * f, unsigned num, expr * const * args, expr_ref & result); void mk_is_normal(func_decl * f, unsigned num, expr * const * args, expr_ref & result); diff --git a/src/ast/fpa/fpa2bv_rewriter.h b/src/ast/fpa/fpa2bv_rewriter.h index 225aad668..7a245b71a 100644 --- a/src/ast/fpa/fpa2bv_rewriter.h +++ b/src/ast/fpa/fpa2bv_rewriter.h @@ -65,8 +65,6 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { bool max_steps_exceeded(unsigned num_steps) const { cooperate("fpa2bv"); - if (memory::get_allocation_size() > m_max_memory) - throw tactic_exception(TACTIC_MAX_MEMORY_MSG); return num_steps > m_max_steps; } @@ -117,17 +115,19 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_VALUE: m_conv.mk_value(f, num, args, result); return BR_DONE; case OP_FLOAT_PLUS_INF: m_conv.mk_plus_inf(f, result); return BR_DONE; case OP_FLOAT_MINUS_INF: m_conv.mk_minus_inf(f, result); return BR_DONE; + case OP_FLOAT_PLUS_ZERO: m_conv.mk_pzero(f, result); return BR_DONE; + case OP_FLOAT_MINUS_ZERO: m_conv.mk_nzero(f, result); return BR_DONE; case OP_FLOAT_NAN: m_conv.mk_nan(f, result); return BR_DONE; case OP_FLOAT_ADD: m_conv.mk_add(f, num, args, result); return BR_DONE; case OP_FLOAT_SUB: m_conv.mk_sub(f, num, args, result); return BR_DONE; - case OP_FLOAT_UMINUS: m_conv.mk_uminus(f, num, args, result); return BR_DONE; + case OP_FLOAT_NEG: m_conv.mk_neg(f, num, args, result); return BR_DONE; case OP_FLOAT_MUL: m_conv.mk_mul(f, num, args, result); return BR_DONE; case OP_FLOAT_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE; - case OP_FLOAT_REM: m_conv.mk_remainder(f, num, args, result); return BR_DONE; + case OP_FLOAT_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE; case OP_FLOAT_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE; case OP_FLOAT_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE; case OP_FLOAT_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE; - case OP_FLOAT_FUSED_MA: m_conv.mk_fusedma(f, num, args, result); return BR_DONE; + case OP_FLOAT_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE; case OP_FLOAT_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE; case OP_FLOAT_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE; case OP_FLOAT_EQ: m_conv.mk_float_eq(f, num, args, result); return BR_DONE; @@ -142,18 +142,18 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg { case OP_FLOAT_IS_INF: m_conv.mk_is_inf(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_NORMAL: m_conv.mk_is_normal(f, num, args, result); return BR_DONE; case OP_FLOAT_IS_SUBNORMAL: m_conv.mk_is_subnormal(f, num, args, result); return BR_DONE; - case OP_FLOAT_IS_SIGN_MINUS: m_conv.mk_is_sign_minus(f, num, args, result); return BR_DONE; + case OP_FLOAT_IS_POSITIVE: m_conv.mk_is_positive(f, num, args, result); return BR_DONE; + case OP_FLOAT_IS_NEGATIVE: m_conv.mk_is_negative(f, num, args, result); return BR_DONE; case OP_TO_FLOAT: m_conv.mk_to_float(f, num, args, result); return BR_DONE; - case OP_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; + case OP_FLOAT_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE; case OP_FLOAT_FP: m_conv.mk_fp(f, num, args, result); return BR_DONE; - case OP_FLOAT_TO_FP_UNSIGNED: m_conv.mk_to_fp_unsigned(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_UBV: m_conv.mk_to_ubv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_SBV: m_conv.mk_to_sbv(f, num, args, result); return BR_DONE; case OP_FLOAT_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE; default: TRACE("fpa2bv", tout << "unsupported operator: " << f->get_name() << "\n"; for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); - throw tactic_exception("NYI"); + NOT_IMPLEMENTED_YET(); } } diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index a4212d579..7dc34dd11 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -36,17 +36,17 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c br_status st = BR_FAILED; SASSERT(f->get_family_id() == get_fid()); switch (f->get_decl_kind()) { - case OP_TO_FLOAT: st = mk_to_float(f, num_args, args, result); break; + case OP_TO_FLOAT: st = mk_to_fp(f, num_args, args, result); break; case OP_FLOAT_ADD: SASSERT(num_args == 3); st = mk_add(args[0], args[1], args[2], result); break; case OP_FLOAT_SUB: SASSERT(num_args == 3); st = mk_sub(args[0], args[1], args[2], result); break; - case OP_FLOAT_UMINUS: SASSERT(num_args == 1); st = mk_uminus(args[0], result); break; + case OP_FLOAT_NEG: SASSERT(num_args == 1); st = mk_neg(args[0], result); break; case OP_FLOAT_MUL: SASSERT(num_args == 3); st = mk_mul(args[0], args[1], args[2], result); break; case OP_FLOAT_DIV: SASSERT(num_args == 3); st = mk_div(args[0], args[1], args[2], result); break; case OP_FLOAT_REM: SASSERT(num_args == 2); st = mk_rem(args[0], args[1], result); break; case OP_FLOAT_ABS: SASSERT(num_args == 1); st = mk_abs(args[0], result); break; case OP_FLOAT_MIN: SASSERT(num_args == 2); st = mk_min(args[0], args[1], result); break; case OP_FLOAT_MAX: SASSERT(num_args == 2); st = mk_max(args[0], args[1], result); break; - case OP_FLOAT_FUSED_MA: SASSERT(num_args == 4); st = mk_fused_ma(args[0], args[1], args[2], args[3], result); break; + case OP_FLOAT_FMA: SASSERT(num_args == 4); st = mk_fma(args[0], args[1], args[2], args[3], result); break; case OP_FLOAT_SQRT: SASSERT(num_args == 2); st = mk_sqrt(args[0], args[1], result); break; case OP_FLOAT_ROUND_TO_INTEGRAL: SASSERT(num_args == 2); st = mk_round(args[0], args[1], result); break; @@ -62,10 +62,10 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c case OP_FLOAT_IS_INF: SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break; case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break; case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break; - case OP_FLOAT_IS_SIGN_MINUS: SASSERT(num_args == 1); st = mk_is_sign_minus(args[0], result); break; - case OP_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; + case OP_FLOAT_IS_NEGATIVE: SASSERT(num_args == 1); st = mk_is_negative(args[0], result); break; + case OP_FLOAT_IS_POSITIVE: SASSERT(num_args == 1); st = mk_is_positive(args[0], result); break; + case OP_FLOAT_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break; case OP_FLOAT_FP: SASSERT(num_args == 3); st = mk_fp(args[0], args[1], args[2], result); break; - case OP_FLOAT_TO_FP_UNSIGNED: SASSERT(num_args == 2); st = mk_to_fp_unsigned(args[0], args[1], result); break; case OP_FLOAT_TO_UBV: SASSERT(num_args == 2); st = mk_to_ubv(args[0], args[1], result); break; case OP_FLOAT_TO_SBV: SASSERT(num_args == 2); st = mk_to_sbv(args[0], args[1], result); break; case OP_FLOAT_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break; @@ -73,7 +73,7 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c return st; } -br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { +br_status float_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { SASSERT(f->get_num_parameters() == 2); SASSERT(f->get_parameter(0).is_int()); SASSERT(f->get_parameter(1).is_int()); @@ -154,7 +154,7 @@ br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref br_status float_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) { // a - b = a + (-b) - result = m_util.mk_add(arg1, arg2, m_util.mk_uminus(arg3)); + result = m_util.mk_add(arg1, arg2, m_util.mk_neg(arg3)); return BR_REWRITE2; } @@ -188,7 +188,7 @@ br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_uminus(expr * arg1, expr_ref & result) { +br_status float_rewriter::mk_neg(expr * arg1, expr_ref & result) { if (m_util.is_nan(arg1)) { // -nan --> nan result = arg1; @@ -204,7 +204,7 @@ br_status float_rewriter::mk_uminus(expr * arg1, expr_ref & result) { result = m_util.mk_plus_inf(m().get_sort(arg1)); return BR_DONE; } - if (m_util.is_uminus(arg1)) { + if (m_util.is_neg(arg1)) { // - - a --> a result = to_app(arg1)->get_arg(0); return BR_DONE; @@ -239,7 +239,7 @@ br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) { return BR_DONE; } result = m().mk_ite(m_util.mk_is_sign_minus(arg1), - m_util.mk_uminus(arg1), + m_util.mk_neg(arg1), arg1); return BR_REWRITE2; } @@ -284,7 +284,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) { return BR_REWRITE_FULL; } -br_status float_rewriter::mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { +br_status float_rewriter::mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) { mpf_rounding_mode rm; if (m_util.is_rm_value(arg1, rm)) { scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm()); @@ -480,7 +480,7 @@ br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) { return BR_FAILED; } -br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) { +br_status float_rewriter::mk_is_negative(expr * arg1, expr_ref & result) { scoped_mpf v(m_util.fm()); if (m_util.is_value(arg1, v)) { result = (m_util.fm().is_neg(v)) ? m().mk_true() : m().mk_false(); @@ -490,6 +490,17 @@ br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) { return BR_FAILED; } +br_status float_rewriter::mk_is_positive(expr * arg1, expr_ref & result) { + scoped_mpf v(m_util.fm()); + if (m_util.is_value(arg1, v)) { + result = (m_util.fm().is_neg(v) || m_util.fm().is_nan(v)) ? m().mk_false() : m().mk_true(); + return BR_DONE; + } + + return BR_FAILED; +} + + // This the SMT = br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result) { scoped_mpf v1(m_util.fm()), v2(m_util.fm()); @@ -532,10 +543,6 @@ br_status float_rewriter::mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref return BR_FAILED; } -br_status float_rewriter::mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result) { - return BR_FAILED; -} - br_status float_rewriter::mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result) { return BR_FAILED; } diff --git a/src/ast/rewriter/float_rewriter.h b/src/ast/rewriter/float_rewriter.h index 0f44d227c..4d8cec856 100644 --- a/src/ast/rewriter/float_rewriter.h +++ b/src/ast/rewriter/float_rewriter.h @@ -45,17 +45,16 @@ public: br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_eq_core(expr * arg1, expr * arg2, expr_ref & result); - br_status mk_to_float(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); - br_status mk_uminus(expr * arg1, expr_ref & result); + br_status mk_neg(expr * arg1, expr_ref & result); br_status mk_rem(expr * arg1, expr * arg2, expr_ref & result); br_status mk_abs(expr * arg1, expr_ref & result); br_status mk_min(expr * arg1, expr * arg2, expr_ref & result); br_status mk_max(expr * arg1, expr * arg2, expr_ref & result); - br_status mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result); + br_status mk_fma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result); br_status mk_sqrt(expr * arg1, expr * arg2, expr_ref & result); br_status mk_round(expr * arg1, expr * arg2, expr_ref & result); br_status mk_float_eq(expr * arg1, expr * arg2, expr_ref & result); @@ -70,10 +69,12 @@ public: br_status mk_is_inf(expr * arg1, expr_ref & result); br_status mk_is_normal(expr * arg1, expr_ref & result); br_status mk_is_subnormal(expr * arg1, expr_ref & result); - br_status mk_is_sign_minus(expr * arg1, expr_ref & result); + br_status mk_is_negative(expr * arg1, expr_ref & result); + br_status mk_is_positive(expr * arg1, expr_ref & result); br_status mk_to_ieee_bv(expr * arg1, expr_ref & result); + br_status mk_to_fp(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result); br_status mk_fp(expr * arg1, expr * arg2, expr * arg3, expr_ref & result); br_status mk_to_fp_unsigned(expr * arg1, expr * arg2, expr_ref & result); br_status mk_to_ubv(expr * arg1, expr * arg2, expr_ref & result); From 5adfbe885733f67b0d1f5f2a7d051d1a0c60b921 Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Wed, 22 Oct 2014 21:57:57 +0100 Subject: [PATCH 081/117] Z3Py: Fix test output Signed-off-by: Nuno Lopes --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 470280630..f2318021f 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -38,7 +38,7 @@ Z3 exceptions: ... n = x + y ... except Z3Exception as ex: ... print("failed: %s" % ex) -failed: 'sort mismatch' +failed: sort mismatch """ from z3core import * from z3types import * From a6bee82ef8dd8ad49e90bdc80c796436e1ccaca0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 23 Oct 2014 17:10:31 +0100 Subject: [PATCH 082/117] Interpolation API: fixed some memory leaks Signed-off-by: Christoph M. Wintersteiger --- src/interp/iz3proof_itp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index e89aa1d6d..52ddcd64f 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -3078,6 +3078,11 @@ public: m().dec_ref(add_pos); m().dec_ref(rewrite_A); m().dec_ref(rewrite_B); + m().dec_ref(normal_step); + m().dec_ref(normal_chain); + m().dec_ref(normal); + m().dec_ref(sforall); + m().dec_ref(sexists); } }; From 6a27d93776fce414f4c4a04fb8358361a2a07d70 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 23 Oct 2014 17:20:55 +0100 Subject: [PATCH 083/117] Fixed memory leaks in interpolation API Signed-off-by: Christoph M. Wintersteiger --- src/api/api_interp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index 63ecc6c24..dd689dcb0 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -273,6 +273,9 @@ extern "C" { 0 // ignore params for now ); + for (unsigned i = 0; i < cnsts.size(); i++) + _m.dec_ref(cnsts[i]); + Z3_lbool status = of_lbool(_status); Z3_ast_vector_ref *v = 0; From fd0920eb36c308f935b43a0bb4ee5cd910ffbd3f Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 23 Oct 2014 19:15:26 +0100 Subject: [PATCH 084/117] Updated release notes Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 643c9b26f..4be65b260 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,6 +3,15 @@ RELEASE NOTES Version 4.3.2 ============= +- Added preliminary support for the theory of floating point numbers (tactics qffpa, qffpabv, and logics QF_FPA, QF_FPABV). + +- Added the interpolation features of iZ3, which are now integrated into the Z3. + +- Fixed a multitude of bugs and inconsistencies that were reported to us either in person, by email, or on Codeplex. Of those that we do have records of, we would like to express our gratitude to: + Vladimir Klebanov, Konrad Jamrozik, Nuno Lopes, Carsten Ruetz, Esteban Pavese, Tomer Weiss, Ilya Mironov, Gabriele Paganelli, Levent Erkok, Fabian Emmes, David Cok, Etienne Kneuss, Arlen Cox, Matt Lewis, Carsten Otto, Paul Jackson, David Monniaux, Markus Rabe, Martin Pluecker, Jasmin Blanchette, Jules Villard, Andrew Gacek, George Karpenkov, Joerg Pfaehler, and Pablo Aledo + as well as the following Codeplex users that either reported bugs or took part in discussions: +xor88, parno, gario, Bauna, GManNickG, hanwentao, dinu09, fhowar, Cici, chinissai, barak_cohen, tvalentyn, krikunts, sukyoung, daramos, snedunuri, rajtendulkar, sonertari, nick8325, dvitek, amdragon, Beatgodes, dmonniaux, nickolai, DameNingen, mangpo, ttsiodras, blurium, sbrickey, pcodemod, indranilsaha, apanda, hougaardj, yoff, EfForEffort, Ansotegui, scottgw, viorelpreoteasa, idudka, c2855337, gario, jnfoster, omarmrivas, switicus, vosandi, foens, yzwwf, Heizmann, znajem, ilyagri, hougaardj, cliguda, rgrig, 92c849c1ccc707173, edmcman, cipher1024, MichaelvW, hellok, n00b42, ic3guy, Adorf, tvcsantos, zilongwang, Elarnon, immspw, jbridge99, danliew, zverlov, petross, jmh93, dradorf, fniksic, Heyji, cxcfan, henningg, wxlfrank, rvprasad, MovGP0, jackie1015, cowang, ffaghih, sanpra1989, gzchenyin, baitman, xjtulixiangyang, andreis, trucnguyenlam, erizzi, hanhchi, qsp, windypan, vadave, gradanne, SamWot, gsingh93, manjeetdahiya, zverlov, and RaLa + - New parameter setting infrastructure. Now, it is possible to set parameter for Z3 internal modules. Several parameter names changed. Execute `z3 -p` for the new parameter list. - Added get_version() and get_version_string() to Z3Py From 7d196201dc00db41693d53abb63104462001792b Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 12:33:20 +0100 Subject: [PATCH 085/117] fixed warnings Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 1 + src/util/mpz.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 647529b4f..7757275f3 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ src/util/version.h src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java +*.bak diff --git a/src/util/mpz.cpp b/src/util/mpz.cpp index bd7f30a76..94df9f78d 100644 --- a/src/util/mpz.cpp +++ b/src/util/mpz.cpp @@ -1535,7 +1535,7 @@ bool mpz_manager::is_power_of_two(mpz const & a, unsigned & shift) { return false; if (is_small(a)) { if (::is_power_of_two(a.m_val)) { - shift = ::log2(a.m_val); + shift = ::log2((unsigned)a.m_val); return true; } else { @@ -1838,7 +1838,7 @@ unsigned mpz_manager::log2(mpz const & a) { if (is_nonpos(a)) return 0; if (is_small(a)) - return ::log2(a.m_val); + return ::log2((unsigned)a.m_val); #ifndef _MP_GMP COMPILE_TIME_ASSERT(sizeof(digit_t) == 8 || sizeof(digit_t) == 4); mpz_cell * c = a.m_ptr; @@ -1860,7 +1860,7 @@ unsigned mpz_manager::mlog2(mpz const & a) { if (is_nonneg(a)) return 0; if (is_small(a)) - return ::log2(-a.m_val); + return ::log2((unsigned)-a.m_val); #ifndef _MP_GMP COMPILE_TIME_ASSERT(sizeof(digit_t) == 8 || sizeof(digit_t) == 4); mpz_cell * c = a.m_ptr; From e0c42f589225883c03438f6c5f9ad1fe9368708a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 14:43:01 +0100 Subject: [PATCH 086/117] Java API bugfix Signed-off-by: Christoph M. Wintersteiger --- scripts/update_api.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index e08adf111..2fbf42cca 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -297,11 +297,13 @@ def param2javaw(p): k = param_kind(p) if k == OUT: return "jobject" - if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: + elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: if param_type(p) == INT or param_type(p) == UINT: return "jintArray" else: return "jlongArray" + elif k == OUT_MANAGED_ARRAY: + return "jlong"; else: return type2javaw(param_type(p)) From 4d62ff6b9fe241e76ae64e8fe4322df1980a8aaf Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 15:53:52 +0100 Subject: [PATCH 087/117] Spelling. Thanks to codeplex user regehr for reporting this. Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index f2318021f..e58e47640 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -1398,7 +1398,7 @@ def BoolVector(prefix, sz, ctx=None): return [ Bool('%s__%s' % (prefix, i)) for i in range(sz) ] def FreshBool(prefix='b', ctx=None): - """Return a fresh Bolean constant in the given context using the given prefix. + """Return a fresh Boolean constant in the given context using the given prefix. If `ctx=None`, then the global context is used. From 6e159bd442a8c338ebd9d94d489cef51eb18f25a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 15:54:49 +0100 Subject: [PATCH 088/117] updated release notes Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 4be65b260..fa4857e32 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -10,7 +10,7 @@ Version 4.3.2 - Fixed a multitude of bugs and inconsistencies that were reported to us either in person, by email, or on Codeplex. Of those that we do have records of, we would like to express our gratitude to: Vladimir Klebanov, Konrad Jamrozik, Nuno Lopes, Carsten Ruetz, Esteban Pavese, Tomer Weiss, Ilya Mironov, Gabriele Paganelli, Levent Erkok, Fabian Emmes, David Cok, Etienne Kneuss, Arlen Cox, Matt Lewis, Carsten Otto, Paul Jackson, David Monniaux, Markus Rabe, Martin Pluecker, Jasmin Blanchette, Jules Villard, Andrew Gacek, George Karpenkov, Joerg Pfaehler, and Pablo Aledo as well as the following Codeplex users that either reported bugs or took part in discussions: -xor88, parno, gario, Bauna, GManNickG, hanwentao, dinu09, fhowar, Cici, chinissai, barak_cohen, tvalentyn, krikunts, sukyoung, daramos, snedunuri, rajtendulkar, sonertari, nick8325, dvitek, amdragon, Beatgodes, dmonniaux, nickolai, DameNingen, mangpo, ttsiodras, blurium, sbrickey, pcodemod, indranilsaha, apanda, hougaardj, yoff, EfForEffort, Ansotegui, scottgw, viorelpreoteasa, idudka, c2855337, gario, jnfoster, omarmrivas, switicus, vosandi, foens, yzwwf, Heizmann, znajem, ilyagri, hougaardj, cliguda, rgrig, 92c849c1ccc707173, edmcman, cipher1024, MichaelvW, hellok, n00b42, ic3guy, Adorf, tvcsantos, zilongwang, Elarnon, immspw, jbridge99, danliew, zverlov, petross, jmh93, dradorf, fniksic, Heyji, cxcfan, henningg, wxlfrank, rvprasad, MovGP0, jackie1015, cowang, ffaghih, sanpra1989, gzchenyin, baitman, xjtulixiangyang, andreis, trucnguyenlam, erizzi, hanhchi, qsp, windypan, vadave, gradanne, SamWot, gsingh93, manjeetdahiya, zverlov, and RaLa +xor88, parno, gario, Bauna, GManNickG, hanwentao, dinu09, fhowar, Cici, chinissai, barak_cohen, tvalentyn, krikunts, sukyoung, daramos, snedunuri, rajtendulkar, sonertari, nick8325, dvitek, amdragon, Beatgodes, dmonniaux, nickolai, DameNingen, mangpo, ttsiodras, blurium, sbrickey, pcodemod, indranilsaha, apanda, hougaardj, yoff, EfForEffort, Ansotegui, scottgw, viorelpreoteasa, idudka, c2855337, gario, jnfoster, omarmrivas, switicus, vosandi, foens, yzwwf, Heizmann, znajem, ilyagri, hougaardj, cliguda, rgrig, 92c849c1ccc707173, edmcman, cipher1024, MichaelvW, hellok, n00b42, ic3guy, Adorf, tvcsantos, zilongwang, Elarnon, immspw, jbridge99, danliew, zverlov, petross, jmh93, dradorf, fniksic, Heyji, cxcfan, henningg, wxlfrank, rvprasad, MovGP0, jackie1015, cowang, ffaghih, sanpra1989, gzchenyin, baitman, xjtulixiangyang, andreis, trucnguyenlam, erizzi, hanhchi, qsp, windypan, vadave, gradanne, SamWot, gsingh93, manjeetdahiya, zverlov, RaLa, and regehr. - New parameter setting infrastructure. Now, it is possible to set parameter for Z3 internal modules. Several parameter names changed. Execute `z3 -p` for the new parameter list. From cc99e967866de3b975ce9facf08e02cec0df1db7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 18:00:36 +0100 Subject: [PATCH 089/117] Java API Cleanup Signed-off-by: Christoph M. Wintersteiger --- examples/java/README | 10 ++++------ src/api/java/README | 3 +++ src/api/java/manifest | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/java/README b/examples/java/README index fa1f20a63..6da4958e4 100644 --- a/examples/java/README +++ b/examples/java/README @@ -1,7 +1,5 @@ -### This is work-in-progress and does not work yet. - -Small example using the Z3 Java bindings. -To build the example execute +A small example using the Z3 Java bindings. +To build the example, configure Z3 with the --java option to scripts/mk_make.py, build via make examples in the build directory. @@ -11,5 +9,5 @@ which can be run on Windows via On Linux and FreeBSD, we must use LD_LIBRARY_PATH=. java -cp com.microsoft.z3.jar:. JavaExample - - \ No newline at end of file +On OSX, the corresponding option is DYLD_LIBRARY_PATH: + DYLD_LIBRARY_PATH=. java -cp com.microsoft.z3.jar:. JavaExample diff --git a/src/api/java/README b/src/api/java/README index 7afe098fb..c9dbcf8f7 100644 --- a/src/api/java/README +++ b/src/api/java/README @@ -1,3 +1,6 @@ Java bindings ------------- +The Java bindings will be included in the Z3 build if it is configured with +the option --java to python scripts/mk_make.py. This will produce the +com.microsoft.z3.jar package in the build directory. diff --git a/src/api/java/manifest b/src/api/java/manifest index b54445cf2..88eac9a3a 100644 --- a/src/api/java/manifest +++ b/src/api/java/manifest @@ -1,2 +1,2 @@ Manifest-Version: 1.0 -Created-By: 4.3.0 (Microsoft Research LTD.) +Created-By: 4.3.2 (Microsoft Research LTD.) From 60cf1d5a4f24802a283f3b427d70b578b1b2989c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 18:02:58 +0100 Subject: [PATCH 090/117] Update copyright notices Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Properties/AssemblyInfo | 2 +- src/api/ml/z3_theory_stubs.c | 2 +- src/shell/main.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/dotnet/Properties/AssemblyInfo b/src/api/dotnet/Properties/AssemblyInfo index ee0e3f354..001264e79 100644 --- a/src/api/dotnet/Properties/AssemblyInfo +++ b/src/api/dotnet/Properties/AssemblyInfo @@ -12,7 +12,7 @@ using System.Security.Permissions; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Microsoft Corporation")] [assembly: AssemblyProduct("Z3")] -[assembly: AssemblyCopyright("Copyright © Microsoft Corporation 2006")] +[assembly: AssemblyCopyright("Copyright (C) 2006-2014 Microsoft Corporation")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/src/api/ml/z3_theory_stubs.c b/src/api/ml/z3_theory_stubs.c index d17a1790d..a48b94553 100644 --- a/src/api/ml/z3_theory_stubs.c +++ b/src/api/ml/z3_theory_stubs.c @@ -1,5 +1,5 @@ /*++ -Copyright (c) 2010 Microsoft Corporation +Copyright (c) Microsoft Corporation Module Name: diff --git a/src/shell/main.cpp b/src/shell/main.cpp index f23bc470c..0eb612f35 100644 --- a/src/shell/main.cpp +++ b/src/shell/main.cpp @@ -65,7 +65,7 @@ void display_usage() { #ifdef Z3GITHASH std::cout << " - build hashcode " << STRINGIZE_VALUE_OF(Z3GITHASH); #endif - std::cout << "]. (C) Copyright 2006-2013 Microsoft Corp.\n"; + std::cout << "]. (C) Copyright 2006-2014 Microsoft Corp.\n"; std::cout << "Usage: z3 [options] [-file:]file\n"; std::cout << "\nInput format:\n"; std::cout << " -smt use parser for SMT input format.\n"; From 2f9b3c42eb0e629fdb9c88a2a41863e73e8ffb09 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 19:43:36 +0100 Subject: [PATCH 091/117] Java API cleanup Signed-off-by: Christoph M. Wintersteiger --- examples/java/README | 1 + src/api/java/mk_java.py | 463 ---------------------------------------- 2 files changed, 1 insertion(+), 463 deletions(-) delete mode 100644 src/api/java/mk_java.py diff --git a/examples/java/README b/examples/java/README index 6da4958e4..1939afc49 100644 --- a/examples/java/README +++ b/examples/java/README @@ -1,4 +1,5 @@ A small example using the Z3 Java bindings. + To build the example, configure Z3 with the --java option to scripts/mk_make.py, build via make examples in the build directory. diff --git a/src/api/java/mk_java.py b/src/api/java/mk_java.py deleted file mode 100644 index 87f3e274a..000000000 --- a/src/api/java/mk_java.py +++ /dev/null @@ -1,463 +0,0 @@ -###################################################### -# Copyright (c) 2012 Microsoft Corporation -# -# Auxiliary scripts for generating Java bindings -# from the managed API. -# -# Author: Christoph M. Wintersteiger (cwinter) -###################################################### - - -### -# DO NOT USE THIS SCRIPT! -# This script creates a rough draft of a Java API from -# the managed API, but does not automated the process. -### - -CS="../dotnet/" -EXT=".cs" -EXCLUDE=["Enumerations.cs", "Native.cs", "AssemblyInfo.cs"] -OUTDIR="com/Microsoft/Z3/" -ENUMS_FILE = "Enumerations.cs" - -import os -import fileinput -import string -import re - -EXCLUDE_METHODS = [ [ "Context.cs", "public Expr MkNumeral(ulong" ], - [ "Context.cs", "public Expr MkNumeral(uint" ], - [ "Context.cs", "public RatNum MkReal(ulong" ], - [ "Context.cs", "public RatNum MkReal(uint" ], - [ "Context.cs", "public IntNum MkInt(ulong" ], - [ "Context.cs", "public IntNum MkInt(uint" ], - [ "Context.cs", "public BitVecNum MkBV(ulong" ], - [ "Context.cs", "public BitVecNum MkBV(uint" ], - ] - -ENUMS = [] - -def mk_java_bindings(): - print "Generating Java bindings (from C# bindings in " + CS + ")..." - print "Finding enumerations in " + ENUMS_FILE + "..." - find_enums(ENUMS_FILE) - for root, dirs, files in os.walk(CS): - for fn in files: - if not fn in EXCLUDE and fn.endswith(EXT): - translate(fn) - -def subst_getters(s, getters): - for g in getters: - s = s.replace(g, g + "()") - -def type_replace(s): - s = s.replace(" bool", " boolean") - s = s.replace("(bool", "(boolean") - s = s.replace("uint", "int") - s = s.replace("ulong", "long") - s = s.replace("string", "String") - s = s.replace("IntPtr", "long") - s = s.replace("Dictionary<", "Map<") - s = s.replace("UInt64", "long") - s = s.replace("Int64", "long") - s = s.replace("List", "LinkedList") - s = s.replace("System.Exception", "Exception") - return s - -def rename_native(s): - while s.find("Native.Z3") != -1: - i0 = s.find("Native.Z3") - i1 = s.find("(", i0) - c0 = s[:i0] - c1 = s[i0:i1] - c1 = c1.replace("Native.Z3_", "Native.") - c2 = s[i1:] - lc_callback = lambda pat: pat.group("id").upper() - c1 = re.sub("_(?P\w)", lc_callback, c1) - s = c0 + c1 + c2 - return s - -def find_enums(fn): - for line in fileinput.input(os.path.join(CS, fn)): - s = string.rstrip(string.lstrip(line)) - if s.startswith("public enum"): - ENUMS.append(s.split(" ")[2]) - - -def enum_replace(line): - for e in ENUMS: - if line.find("case") != -1: - line = line.replace(e + ".", "") - elif line.find("== (int)") != -1 or line.find("!= (int)") != -1: - line = re.sub("\(int\)" + e + "\.(?P[A-Z0-9_]*)", e + ".\g.toInt()", line) - elif line.find("==") != -1 or line.find("!=") != -1: - line = re.sub(e + "\.(?P[A-Z0-9_]*)", e + ".\g", line) - else: - # line = re.sub("\(\(" + e + "\)(?P.*\(.*)\)", "(" + e + ".values()[\g])", line) - line = re.sub("\(" + e + "\)(?P.*\(.*\))", e + ".fromInt(\g)", line) - return line - -def replace_generals(a): - a = re.sub(" NativeObject", " NativeObject()", a) - a = re.sub("\.NativeObject", ".NativeObject()", a) - a = re.sub("(?P[\.\(])Id", "\gId()", a) - a = a.replace("(Context ==", "(Context() ==") - a = a.replace("(Context,", "(Context(),") - a = a.replace("Context.", "Context().") - a = a.replace(".nCtx", ".nCtx()") - a = a.replace("(nCtx", "(nCtx()") - a = re.sub("Context\(\).(?P[^_]*)_DRQ", "Context().\g_DRQ()", a) - a = re.sub("ASTKind", "ASTKind()", a) - a = re.sub("IsExpr(?P[ ;])", "IsExpr()\g", a) - a = re.sub("IsNumeral(?P[ ;])", "IsNumeral()\g", a) - a = re.sub("IsInt(?P[ ;])", "IsInt()\g", a) - a = re.sub("IsReal(?P[ ;])", "IsReal()\g", a) - a = re.sub("IsVar(?P[ ;\)])", "IsVar()\g", a) - a = re.sub("FuncDecl.DeclKind", "FuncDecl().DeclKind()", a) - a = re.sub("FuncDecl.DomainSize", "FuncDecl().DomainSize()", a) - a = re.sub("(?P[=&]) Num(?P[a-zA-Z]*)", "\g Num\g()", a) - a = re.sub("= Denominator", "= Denominator()", a) - a = re.sub(", BoolSort(?P[\)\.])", ", BoolSort()\g", a) - a = re.sub(", RealSort(?P[\)\.])", ", RealSort()\g", a) - a = re.sub(", IntSort(?P[\)\.])", ", IntSort()\g", a) - a = a.replace("? 1 : 0", "? true : false") - if a.find("Native.") != -1 and a.find("!= 0") != -1: - a = a.replace("!= 0", "") - if a.find("Native.") != -1 and a.find("== 0") != -1: - a = a.replace("== 0", "^ true") - return a - -def translate(filename): - tgtfn = OUTDIR + filename.replace(EXT, ".java") - print "Translating " + filename + " to " + tgtfn - tgt = open(tgtfn, "w") - in_header = 0 - in_class = 0 - in_static_class = 0 - in_javadoc = 0 - lastindent = 0 - skip_brace = 0 - in_getter = "" - in_getter_type = "" - in_unsupported = 0 - getters = [] - in_bracket_op = 0 - in_getter_get = 0 - in_getter_set = 0 - had_ulong_res = 0 - in_enum = 0 - missing_foreach_brace = 0 - foreach_opened_brace = 0 - for line in fileinput.input(os.path.join(CS, filename)): - s = string.rstrip(string.lstrip(line)) - if in_javadoc: - if s.startswith("///"): - lastindent = line.find(s); - if s.startswith("/// "): - pass - else: - a = line - a = a.replace("", "") - a = a.replace("", "") - a = a.replace("///"," *") - a = a.replace("","@return ") - a = a.replace("","") - tgt.write(a) - else: - t = "" - for i in range(0, lastindent): - t += " " - tgt.write(t + " **/\n") - in_javadoc = 0 - - # for i in range(0, len(EXCLUDE_METHODS)): - # if filename == EXCLUDE_METHODS[i][0] and s.startswith(EXCLUDE_METHODS[i][1]): - # tgt.write(t + "/* Not translated because it would translate to a function with clashing types. */\n") - # in_unsupported = 1 - # break - - - if in_unsupported: - if s == "}": - in_unsupported = 0 - elif not in_javadoc: - if not in_header and s.find("/*++") != -1: - in_header = 1 - tgt.write("/**\n") - elif in_header and s.startswith("--*/"): - in_header = 0 - tgt.write(" * This file was automatically generated from " + filename + " \n") - tgt.write(" **/\n") - tgt.write("\npackage com.Microsoft.Z3;\n\n") - tgt.write("import java.math.BigInteger;\n") - tgt.write("import java.util.*;\n") - tgt.write("import java.lang.Exception;\n") - tgt.write("import com.Microsoft.Z3.Enumerations.*;\n") - elif in_header == 1: - # tgt.write(" * " + line.replace(filename, tgtfn)) - pass - elif s.startswith("using"): - if s.find("System.Diagnostics.Contracts") == -1: - tgt.write("/* " + s + " */\n") - elif s.startswith("namespace"): - pass - elif s.startswith("public") and s.find("operator") != -1 and (s.find("==") != -1 or s.find("!=") != -1): - t = "" - for i in range(0, line.find(s)+1): - t += " " - tgt.write(t + "/* Overloaded operators are not translated. */\n") - in_unsupported = 1 - elif s.startswith("public enum"): - tgt.write(line.replace("enum", "class")) - in_enum = 1 - elif in_enum == 1: - if s == "}": - tgt.write(line) - in_enum = 0 - else: - line = re.sub("(?P.*)\W*=\W*(?P[^\n,])", "public static final int \g = \g;", line) - tgt.write(line.replace(",","")) - elif s.startswith("public class") or s.startswith("internal class") or s.startswith("internal abstract class"): - a = line.replace(":", "extends").replace("internal ", "") - a = a.replace(", IComparable", "") - a = type_replace(a) - tgt.write(a) - in_class = 1 - in_static_class = 0 - elif s.startswith("public static class") or s.startswith("abstract class"): - tgt.write(line.replace(":", "extends").replace("static", "final")) - in_class = 1 - in_static_class = 1 - elif s.startswith("/// "): - tgt.write(line.replace("/// ", "/**")) - in_javadoc = 1 - elif skip_brace and s == "{": - skip_brace = 0 - elif ((s.find("public") != -1 or s.find("protected") != -1) and s.find("class") == -1 and s.find("event") == -1 and s.find("(") == -1) or s.startswith("internal virtual IntPtr NativeObject") or s.startswith("internal Context Context"): - if (s.startswith("new")): - s = s[3:] - s = s.replace("internal virtual", "") - s = s.replace("internal", "") - tokens = s.split(" ") - # print "TOKENS: " + str(len(tokens)) - if len(tokens) == 3: - in_getter = tokens[2] - in_getter_type = type_replace((tokens[0] + " " + tokens[1])) - if in_static_class: - in_getter_type = in_getter_type.replace("static", "") - lastindent = line.find(s) - skip_brace = 1 - getters.append(in_getter) - elif len(tokens) == 4: - if tokens[2].startswith("this["): - in_bracket_op = 1 - in_getter = type_replace(tokens[2]).replace("this[", "get(") - in_getter += " " + tokens[3].replace("]", ")") - in_getter_type = type_replace(tokens[0] + " " + tokens[1]) - else: - in_getter = tokens[3] - in_getter_type = type_replace(tokens[0] + " " + tokens[1] + " " + tokens[2]) - if in_static_class: - in_getter_type = in_getter_type.replace("static", "") - lastindent = line.find(s) - skip_brace = 1 - getters.append(in_getter) - else: - in_getter = tokens[2] - in_getter_type = type_replace(tokens[0] + " " + tokens[1]) - if tokens[2].startswith("this["): - lastindent = line.find(s) - t = "" - for i in range(0, lastindent): t += " " - tgt.write(t + "/* operator this[] not translated */\n ") - in_unsupported = 1 - else: - if in_static_class: - in_getter_type = in_getter_type.replace("static", "") - rest = s[s.find("get ") + 4:-1] - subst_getters(rest, getters) - rest = type_replace(rest) - rest = rename_native(rest) - rest = replace_generals(rest) - rest = enum_replace(rest) - t = "" - for i in range(0, lastindent): - t += " " - tgt.write(t + in_getter_type + " " + in_getter + "() " + rest + "\n") - if rest.find("}") == -1: - in_getter_get = 1 - else: - getters.append(in_getter) - in_getter = "" - in_getter_type = "" - print "ACC: " + s + " --> " + in_getter - elif s.find("{ get {") != -1: - line = type_replace(line) - line = line.replace("internal ", "") - d = line[0:line.find("{ get")] - rest = line[line.find("{ get")+5:] - rest = rest.replace("} }", "}") - rest = re.sub("Contract.\w+\([\s\S]*\);", "", rest) - subst_getters(rest, getters) - rest = rename_native(rest) - rest = replace_generals(rest) - rest = enum_replace(rest) - if in_bracket_op: - tgt.write(d + rest) - else: - tgt.write(d + "()" + rest) - print "ACC: " + s + " --> " + in_getter - elif in_getter != "" and s.startswith("get"): - t = "" - for i in range(0, lastindent): - t += " " - if len(s) > 3: rest = s[3:] - else: rest = "" - subst_getters(rest, getters) - rest = type_replace(rest) - rest = rename_native(rest) - rest = replace_generals(rest) - rest = enum_replace(rest) - if in_bracket_op: - tgt.write(t + in_getter_type + " " + in_getter + " " + rest + "\n") - else: - tgt.write(t + in_getter_type + " " + in_getter + "() " + rest + "\n") - if rest.find("}") == -1: - in_getter_get = 1 - elif in_getter != "" and s.startswith("set"): - t = "" - for i in range(0, lastindent): - t += " " - if len(s) > 3: rest = type_replace(s[3:]) - else: rest = "" - subst_getters(rest, getters) - rest = rest.replace("(Integer)value", "Integer(value)") - rest = type_replace(rest) - rest = rename_native(rest) - rest = replace_generals(rest) - rest = enum_replace(rest) - ac_acc = in_getter_type[:in_getter_type.find(' ')] - ac_type = in_getter_type[in_getter_type.find(' ')+1:] - if in_bracket_op: - in_getter = in_getter.replace("get", "set").replace(")", "") - tgt.write(t + ac_acc + " void " + in_getter + ", " + ac_type + " value) " + rest + "\n") - else: - tgt.write(t + ac_acc + " void set" + in_getter + "(" + ac_type + " value) " + rest + "\n") - if rest.find("}") == -1: - in_getter_set = 1 - elif in_getter != "" and in_getter_get == 1 and s == "}": - tgt.write(line) - in_getter_get = 0 - elif in_getter != "" and in_getter_set == 1 and s == "}": - tgt.write(line) - in_getter_set = 0 - elif in_getter != "" and in_getter_get == 0 and in_getter_set == 0 and s == "}": - in_getter = "" - in_getter_type == "" - in_bracket_op = 0 - skip_brace = 0 - elif s.startswith("uint ") and s.find("=") == -1: - line = line.replace("uint", "Integer", line) - line = re.sub("(?P\w+)(?P[,;])", "\g\g", line) - tgt.write(line); - elif (not in_class and (s.startswith("{") or s.startswith("}"))) or s.startswith("[") or s.startswith("#"): - # tgt.write("// Skipping: " + s) - pass - elif line == "}\n": - pass - else: - # indent = line.find(s) - # tgt.write("// LINE: " + line) - if line.find(": base") != -1: - line = re.sub(": base\((?P

[^\{]*)\)", "{ super(\g

);", line) - line = line[4:] - obraces = line.count("{") - cbraces = line.count("}") - mbraces = obraces - cbraces - # tgt.write("// obraces = " + str(obraces) + "\n") - if obraces == 1: - skip_brace = 1 - else: - for i in range(0, mbraces): - line = line.replace("\n", "}\n") - if (s.find("public") != -1 or s.find("protected") != -1 or s.find("internal") != -1) and s.find("(") != -1: - line = re.sub(" = [\w.]+(?P[,;\)])", "\g", line) - a = type_replace(line) - a = enum_replace(a) - a = re.sub("(?P[\(, ])params ", "\g", a) - a = a.replace("base.", "super.") - a = re.sub("Contract.\w+\([\s\S]*\);", "", a) - a = rename_native(a) - a = re.sub("~\w+\(\)", "protected void finalize()", a) - - if missing_foreach_brace == 1: - # a = a.replace("\n", " // checked " + str(foreach_opened_brace) + "\n") - if foreach_opened_brace == 0 and a.find("{") != -1: - foreach_opened_brace = 1 - elif foreach_opened_brace == 0 and a.find("}") == -1: - a = a.replace("\n", "}}\n") - foreach_opened_brace = 0 - missing_foreach_brace = 0 - elif foreach_opened_brace == 1 and a.find("}") != -1: - a = a.replace("\n", "}}\n") - foreach_opened_brace = 0 - missing_foreach_brace = 0 - -# if a.find("foreach") != -1: -# missing_foreach_brace = 1 -# a = re.sub("foreach\s*\((?P[\w <>,]+)\s+(?P\w+)\s+in\s+(?P\w+)\)", - # "{ Iterator fe_i = \g.iterator(); while (fe_i.hasNext()) { \g \g = (long)fe_i.next(); ", -# a) - a = re.sub("foreach\s*\((?P[\w <>,]+)\s+(?P\w+)\s+in\s+(?P\w+)\)", - "for (\g \g: \g)", - a) - if a.find("long o: m_queue") != -1: - a = a.replace("long", "Long") - a = a.replace("readonly ", "") - a = a.replace("const ", "final ") - a = a.replace("String ToString", "String toString") - a = a.replace(".ToString", ".toString") - a = a.replace("internal ", "") - a = a.replace("new static", "static") - a = a.replace("new public", "public") - a = a.replace("override ", "") - a = a.replace("virtual ", "") - a = a.replace("o as AST", "(AST) o") - a = a.replace("o as Sort", "(Sort) o") - a = a.replace("other as AST", "(AST) other") - a = a.replace("o as FuncDecl", "(FuncDecl) o") - a = a.replace("IntPtr obj", "long obj") - a = a.replace("IntPtr o", "long o") - a = a.replace("new long()", "0") - a = a.replace("long.Zero", "0") - a = a.replace("object o", "Object o") - a = a.replace("object other", "Object other") - a = a.replace("IntPtr res = IntPtr.Zero;", "Native.IntPtr res = new Native.IntPtr();") - a = a.replace("out res", "res") - a = a.replace("GC.ReRegisterForFinalize(m_ctx);", "") - a = a.replace("GC.SuppressFinalize(this);", "") - a = a.replace(".Length", ".length") - a = a.replace("m_queue.Count", "m_queue.size()") - a = a.replace("m_queue.Add", "m_queue.add") - a = a.replace("m_queue.Clear", "m_queue.clear") - a = a.replace("for (long ", "for (int ") - a = a.replace("ReferenceEquals(Context, ctx)", "Context() == ctx") - a = a.replace("BigInteger.Parse", "new BigInteger") - if had_ulong_res == 0 and a.find("ulong res = 0") != -1: - a = a.replace("ulong res = 0;", "LongPtr res = new LongPtr();") - elif had_ulong_res == 1: - a = a.replace("ref res)", "res)") - if a.find("return res;") != -1: - a = a.replace("return res;", "return res.value;") - had_ulong_res = 0 - a = a.replace("lock (", "synchronized (") - if in_static_class: - a = a.replace("static", "") - a = re.sub("ref (?P\w+)", "\g", a) - subst_getters(a, getters) - a = re.sub("NativeObject = (?P.*);", "setNativeObject(\g);", a) - a = replace_generals(a) - tgt.write(a) - tgt.close() - -mk_java_bindings() From ddebb4a69d8c6105187063e3647136d720e3c41c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 19:45:21 +0100 Subject: [PATCH 092/117] Documentation fixes Signed-off-by: Christoph M. Wintersteiger --- doc/mk_api_doc.py | 8 ++++++++ doc/z3api.dox | 14 +++++++++----- src/api/java/AST.java | 20 ++------------------ src/api/java/Expr.java | 2 +- src/api/java/Global.java | 5 ++--- src/api/java/Sort.java | 19 +------------------ src/api/z3_algebraic.h | 16 +++++++++++++++- src/api/z3_api.h | 7 ++----- src/api/z3_interp.h | 18 +++++++++++++++++- src/api/z3_polynomial.h | 16 ++++++++++++++++ src/api/z3_rcf.h | 15 +++++++++++++++ 11 files changed, 88 insertions(+), 52 deletions(-) diff --git a/doc/mk_api_doc.py b/doc/mk_api_doc.py index 6e530243a..633f96c6b 100644 --- a/doc/mk_api_doc.py +++ b/doc/mk_api_doc.py @@ -27,6 +27,10 @@ try: shutil.copyfile('website.dox', 'tmp/website.dox') shutil.copyfile('../src/api/python/z3.py', 'tmp/z3py.py') cleanup_API('../src/api/z3_api.h', 'tmp/z3_api.h') + cleanup_API('../src/api/z3_algebraic.h', 'tmp/z3_algebraic.h') + cleanup_API('../src/api/z3_polynomial.h', 'tmp/z3_polynomial.h') + cleanup_API('../src/api/z3_rcf.h', 'tmp/z3_rcf.h') + cleanup_API('../src/api/z3_interp.h', 'tmp/z3_interp.h') print "Removed annotations from z3_api.h." try: @@ -38,6 +42,10 @@ try: exit(1) print "Generated C and .NET API documentation." os.remove('tmp/z3_api.h') + os.remove('tmp/z3_algebraic.h') + os.remove('tmp/z3_polynomial.h') + os.remove('tmp/z3_rcf.h') + os.remove('tmp/z3_interp.h') print "Removed temporary file z3_api.h." os.remove('tmp/website.dox') print "Removed temporary file website.dox" diff --git a/doc/z3api.dox b/doc/z3api.dox index 0233e6d83..dbaa3c8b8 100644 --- a/doc/z3api.dox +++ b/doc/z3api.dox @@ -363,7 +363,7 @@ TYPEDEF_HIDES_STRUCT = NO # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. -SYMBOL_CACHE_SIZE = 0 +# SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given @@ -708,7 +708,11 @@ INPUT_ENCODING = UTF-8 # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = website.dox \ - z3_api.h \ + z3_api.h \ + z3_algebraic.h \ + z3_polynomial.h \ + z3_rcf.h \ + z3_interp.h \ z3++.h \ z3py.py \ ApplyResult.cs \ @@ -1477,13 +1481,13 @@ XML_OUTPUT = xml # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +# XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +# XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting @@ -1699,7 +1703,7 @@ DOT_NUM_THREADS = 0 # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. -DOT_FONTNAME = FreeSans +# DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. diff --git a/src/api/java/AST.java b/src/api/java/AST.java index 1f5463ec7..a201d5697 100644 --- a/src/api/java/AST.java +++ b/src/api/java/AST.java @@ -24,28 +24,12 @@ import com.microsoft.z3.enumerations.Z3_ast_kind; **/ public class AST extends Z3Object { - /** - * Comparison operator. An AST An - * AST - * - * @return True if and are from - * the same context and represent the same sort; false otherwise. - **/ - /* Overloaded operators are not translated. */ - - /** - * Comparison operator. An AST An - * AST - * - * @return True if and are not - * from the same context or represent different sorts; false - * otherwise. - **/ /* Overloaded operators are not translated. */ /** * Object comparison. - **/ + * another AST + **/ public boolean equals(Object o) { AST casted = null; diff --git a/src/api/java/Expr.java b/src/api/java/Expr.java index 3773e749d..a4c669dad 100644 --- a/src/api/java/Expr.java +++ b/src/api/java/Expr.java @@ -40,7 +40,7 @@ public class Expr extends AST /** * Returns a simplified version of the expression * A set of - * parameters to configure the simplifier + * parameters a Params object to configure the simplifier * **/ public Expr simplify(Params p) throws Z3Exception diff --git a/src/api/java/Global.java b/src/api/java/Global.java index b97e48721..c93f46c88 100644 --- a/src/api/java/Global.java +++ b/src/api/java/Global.java @@ -50,8 +50,7 @@ public final class Global /** * Get a global (or module) parameter. * - * Returns null if the parameter does not exist. - * The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. + * Returns null if the parameter parameter id does not exist. * This function cannot be invoked simultaneously from different threads without synchronization. * The result string stored in param_value is stored in a shared location. * @@ -70,7 +69,7 @@ public final class Global * * This command will not affect already created objects (such as tactics and solvers) * - * @seealso SetParameter + * **/ public static void resetParameters() { diff --git a/src/api/java/Sort.java b/src/api/java/Sort.java index 7bcc7ce7e..7d89428c6 100644 --- a/src/api/java/Sort.java +++ b/src/api/java/Sort.java @@ -25,27 +25,10 @@ import com.microsoft.z3.enumerations.Z3_sort_kind; **/ public class Sort extends AST { - /** - * Comparison operator. A Sort A - * Sort - * - * @return True if and are from - * the same context and represent the same sort; false otherwise. - **/ /* Overloaded operators are not translated. */ /** - * Comparison operator. A Sort A - * Sort - * - * @return True if and are not - * from the same context or represent different sorts; false - * otherwise. - **/ - /* Overloaded operators are not translated. */ - - /** - * Equality operator for objects of type Sort. + * Equality operator for objects of type Sort. * * @return **/ diff --git a/src/api/z3_algebraic.h b/src/api/z3_algebraic.h index eef791170..8b6d97aa8 100644 --- a/src/api/z3_algebraic.h +++ b/src/api/z3_algebraic.h @@ -23,7 +23,19 @@ Notes: #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus + + /** + \defgroup capi C API + + */ + + /*@{*/ + + /** + @name Algebraic Numbers API + */ + /*@{*/ /** \brief Return Z3_TRUE if \c can be used as value in the Z3 real algebraic @@ -218,6 +230,8 @@ extern "C" { */ int Z3_API Z3_algebraic_eval(__in Z3_context c, __in Z3_ast p, __in unsigned n, __in Z3_ast a[]); + /*@}*/ + /*@}*/ #ifdef __cplusplus }; diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 2e3ddf4b4..248d2161e 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -771,7 +771,6 @@ typedef enum The premises of the rules is a sequence of clauses. The first clause argument is the main clause of the rule. - One literal from the second, third, .. clause is resolved with a literal from the first (main) clause. Premises of the rules are of the form @@ -1143,8 +1142,8 @@ typedef enum { - Z3_FILE_ACCESS_ERRROR: A file could not be accessed. - Z3_INVALID_USAGE: API call is invalid in the current state. - Z3_INTERNAL_FATAL: An error internal to Z3 occurred. - - Z3_DEC_REF_ERROR: Trying to decrement the reference counter of an AST that was deleted or the reference counter was not initialized\mlonly.\endmlonly\conly with #Z3_inc_ref. - - Z3_EXCEPTION: Internal Z3 exception. Additional details can be retrieved using \mlonly #Z3_get_error_msg. \endmlonly \conly #Z3_get_error_msg_ex. + - Z3_DEC_REF_ERROR: Trying to decrement the reference counter of an AST that was deleted or the reference counter was not initialized \mlonly.\endmlonly \conly with #Z3_inc_ref. + - Z3_EXCEPTION: Internal Z3 exception. Additional details can be retrieved using #Z3_get_error_msg. */ typedef enum { @@ -1287,8 +1286,6 @@ extern "C" { \sa Z3_global_param_set - The caller must invoke #Z3_global_param_del_value to delete the value returned at \c param_value. - \remark This function cannot be invoked simultaneously from different threads without synchronization. The result string stored in param_value is stored in shared location. diff --git a/src/api/z3_interp.h b/src/api/z3_interp.h index 729851988..6ae26c0ed 100644 --- a/src/api/z3_interp.h +++ b/src/api/z3_interp.h @@ -24,7 +24,14 @@ extern "C" { #endif // __cplusplus /** - @name Interpolation + \defgroup capi C API + + */ + + /*@{*/ + + /** + @name Interpolation API */ /*@{*/ @@ -184,6 +191,8 @@ extern "C" { \param cnsts Returns sequence of formulas (do not free) \param parents Returns the parents vector (or NULL for sequence) \param error Returns an error message in case of failure (do not free the string) + \param num_theory Number of theory terms + \param theory Theory terms Returns true on success. @@ -232,6 +241,8 @@ extern "C" { \param parents The parents vector (or NULL for sequence) \param interps The interpolant to check \param error Returns an error message if interpolant incorrect (do not free the string) + \param num_theory Number of theory terms + \param theory Theory terms Return value is Z3_L_TRUE if interpolant is verified, Z3_L_FALSE if incorrect, and Z3_L_UNDEF if unknown. @@ -258,6 +269,8 @@ extern "C" { \param cnsts Array of constraints \param parents The parents vector (or NULL for sequence) \param filename The file name to write + \param num_theory Number of theory terms + \param theory Theory terms def_API('Z3_write_interpolation_problem', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(STRING), _in(UINT), _in_array(5, AST))) */ @@ -270,6 +283,9 @@ extern "C" { __in unsigned num_theory, __in_ecount(num_theory) Z3_ast theory[]); + /*@}*/ + /*@}*/ + #ifdef __cplusplus }; #endif // __cplusplus diff --git a/src/api/z3_polynomial.h b/src/api/z3_polynomial.h index 614e654f9..f55a63dd4 100644 --- a/src/api/z3_polynomial.h +++ b/src/api/z3_polynomial.h @@ -24,6 +24,19 @@ Notes: extern "C" { #endif // __cplusplus + /** + \defgroup capi C API + + */ + + /*@{*/ + + + /** + @name Polynomials API + */ + /*@{*/ + /** \brief Return the nonzero subresultants of \c p and \c q with respect to the "variable" \c x. @@ -38,6 +51,9 @@ extern "C" { Z3_ast_vector Z3_API Z3_polynomial_subresultants(__in Z3_context c, __in Z3_ast p, __in Z3_ast q, __in Z3_ast x); + /*@}*/ + /*@}*/ + #ifdef __cplusplus }; #endif // __cplusplus diff --git a/src/api/z3_rcf.h b/src/api/z3_rcf.h index e2b4b7e05..04fe40253 100644 --- a/src/api/z3_rcf.h +++ b/src/api/z3_rcf.h @@ -25,6 +25,18 @@ Notes: #ifdef __cplusplus extern "C" { #endif // __cplusplus + + /** + \defgroup capi C API + + */ + + /*@{*/ + + /** + @name Real Closed Fields API + */ + /*@{*/ /** \brief Delete a RCF numeral created using the RCF API. @@ -192,6 +204,9 @@ extern "C" { */ void Z3_API Z3_rcf_get_numerator_denominator(__in Z3_context c, __in Z3_rcf_num a, __out Z3_rcf_num * n, __out Z3_rcf_num * d); + /*@}*/ + /*@}*/ + #ifdef __cplusplus }; #endif // __cplusplus From da71d5ee0157b2c5d521e13b90139d4c3e7c68d8 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Fri, 24 Oct 2014 11:53:03 -0700 Subject: [PATCH 093/117] unlimit stack on linux/mac --- src/interp/iz3interp.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/interp/iz3interp.cpp b/src/interp/iz3interp.cpp index 0d394090f..7a0090981 100755 --- a/src/interp/iz3interp.cpp +++ b/src/interp/iz3interp.cpp @@ -513,3 +513,26 @@ void interpolation_options_struct::apply(iz3base &b){ b.set_option((*it).first,(*it).second); } +// On linux and mac, unlimit stack space so we get recursion + +#if defined(_WINDOWS) || defined(_CYGWIN) + +#else + +#include +#include + +class iz3stack_unlimiter { +public: + iz3stack_unlimiter() { + struct rlimit rl = {RLIM_INFINITY, RLIM_INFINITY}; + setrlimit(RLIMIT_STACK, &rl); + // nothing to be done if above fails + } +}; + +// initializing this will unlimit stack + +iz3stack_unlimiter the_iz3stack_unlimiter; + +#endif From 0713535fa6a3a5fb510d5e05f7bf7bff44b3b6d9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 24 Oct 2014 21:00:23 +0100 Subject: [PATCH 094/117] Documentation website fixes. Signed-off-by: Christoph M. Wintersteiger --- .gitignore | 2 ++ doc/website.dox | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7757275f3..65a69bf51 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,5 @@ src/api/java/Native.cpp src/api/java/Native.java src/api/java/enumerations/*.java *.bak +doc/api +doc/code diff --git a/doc/website.dox b/doc/website.dox index 6936b4f77..d048dab0c 100644 --- a/doc/website.dox +++ b/doc/website.dox @@ -15,5 +15,5 @@ - .NET API - Java API - Python API (also available in pydoc format). - - Try Z3 online at RiSE4Fun using Python or SMT 2.0. + - Try Z3 online at RiSE4Fun. */ From cb3e9c96441406a7dd64a7cd2eec45b676d98b9e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Oct 2014 16:58:16 +0100 Subject: [PATCH 095/117] Bugfix for FPA models --- src/tactic/fpa/fpa2bv_model_converter.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/tactic/fpa/fpa2bv_model_converter.cpp b/src/tactic/fpa/fpa2bv_model_converter.cpp index 9b4b5a70f..53fa2405b 100644 --- a/src/tactic/fpa/fpa2bv_model_converter.cpp +++ b/src/tactic/fpa/fpa2bv_model_converter.cpp @@ -111,14 +111,25 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) { unsigned ebits = fu.get_ebits(var->get_range()); unsigned sbits = fu.get_sbits(var->get_range()); - expr_ref sgn(m), sig(m), exp(m); - sgn = bv_mdl->get_const_interp(to_app(a->get_arg(0))->get_decl()); - sig = bv_mdl->get_const_interp(to_app(a->get_arg(1))->get_decl()); - exp = bv_mdl->get_const_interp(to_app(a->get_arg(2))->get_decl()); + expr_ref sgn(m), sig(m), exp(m); + bv_mdl->eval(a->get_arg(0), sgn, true); + bv_mdl->eval(a->get_arg(1), sig, true); + bv_mdl->eval(a->get_arg(2), exp, true); + SASSERT(a->is_app_of(fu.get_family_id(), OP_TO_FLOAT)); + +#ifdef Z3DEBUG + SASSERT(to_app(a->get_arg(0))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); + SASSERT(to_app(a->get_arg(1))->get_decl()->get_arity() == 0); seen.insert(to_app(a->get_arg(0))->get_decl()); seen.insert(to_app(a->get_arg(1))->get_decl()); seen.insert(to_app(a->get_arg(2))->get_decl()); +#else + SASSERT(a->get_arg(0)->get_kind() == OP_EXTRACT); + SASSERT(to_app(a->get_arg(0))->get_arg(0)->get_kind() == OP_EXTRACT); + seen.insert(to_app(to_app(a->get_arg(0))->get_arg(0))->get_decl()); +#endif if (!sgn && !sig && !exp) continue; From 6b51f7a6104c23b855ccf1e89bb5d7f10991471e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Oct 2014 16:59:24 +0100 Subject: [PATCH 096/117] Added item to release notes Signed-off-by: Christoph M. Wintersteiger --- RELEASE_NOTES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index fa4857e32..ad2dcaf00 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,5 +1,10 @@ RELEASE NOTES +Version 4.3.3 +============= + +- Fixed bug in floating point models + Version 4.3.2 ============= From f50a8b0a59ff5c98f509dddb46da33033384bf5d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 25 Oct 2014 17:05:02 +0100 Subject: [PATCH 097/117] Bumped version number. Signed-off-by: Christoph M. Wintersteiger --- scripts/mk_project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 170124bd8..b30bba609 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -9,7 +9,7 @@ from mk_util import * # Z3 Project definition def init_project_def(): - set_version(4, 3, 2, 0) + set_version(4, 3, 3, 0) add_lib('util', []) add_lib('polynomial', ['util'], 'math/polynomial') add_lib('sat', ['util']) From a6f58bdd173f7d8b4ee55c710c4158f59a76b8cb Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Thu, 30 Oct 2014 17:22:34 -0700 Subject: [PATCH 098/117] fixes and performance improvements for interp and duality --- src/duality/duality.h | 4 ++ src/duality/duality_rpfp.cpp | 108 ++++++++++++++++++++------------- src/duality/duality_solver.cpp | 12 ++++ src/interp/iz3mgr.cpp | 6 +- src/interp/iz3mgr.h | 3 +- 5 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/duality/duality.h b/src/duality/duality.h index edd89d78f..04527450c 100755 --- a/src/duality/duality.h +++ b/src/duality/duality.h @@ -778,6 +778,10 @@ protected: struct Bad { }; + // thrown on more serious internal error + struct ReallyBad { + }; + /** Pop a scope (see Push). Note, you cannot pop axioms. */ void Pop(int num_scopes); diff --git a/src/duality/duality_rpfp.cpp b/src/duality/duality_rpfp.cpp index f2824c9b0..cdc8fb3b2 100755 --- a/src/duality/duality_rpfp.cpp +++ b/src/duality/duality_rpfp.cpp @@ -2643,6 +2643,10 @@ namespace Duality { GetGroundLitsUnderQuants(memo,f.body(),res,1); return; } + if(f.is_var()){ + // std::cout << "foo!\n"; + return; + } if(under && f.is_ground()) res.push_back(f); } @@ -3065,10 +3069,14 @@ namespace Duality { node->Annotation.SetEmpty(); hash_set *core = new hash_set; core->insert(node->Outgoing->dual); + expr prev_annot = ctx.bool_val(false); + expr prev_impl = ctx.bool_val(false); + int repeated_case_count = 0; while(1){ by_case_counter++; is.push(); expr annot = !GetAnnotation(node); + Transformer old_annot = node->Annotation; is.add(annot); if(is.check() == unsat){ is.pop(1); @@ -3076,56 +3084,70 @@ namespace Duality { } is.pop(1); Push(); - ConstrainEdgeLocalized(node->Outgoing,is.get_implicant()); + expr the_impl = is.get_implicant(); + if(eq(the_impl,prev_impl)){ + // std::cout << "got old implicant\n"; + repeated_case_count++; + } + prev_impl = the_impl; + ConstrainEdgeLocalized(node->Outgoing,the_impl); ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node)); //TODO: need this? - check_result foo = Check(root); - if(foo != unsat){ - slvr().print("should_be_unsat.smt2"); - throw "should be unsat"; - } - std::vector assumps, axioms_to_add; - slvr().get_proof().get_assumptions(assumps); - for(unsigned i = 0; i < assumps.size(); i++){ - (*core).insert(assumps[i]); - if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ - axioms_to_add.push_back(assumps[i]); - axioms_needed.erase(assumps[i]); - } - } - // AddToProofCore(*core); - Transformer old_annot = node->Annotation; - SolveSingleNode(root,node); - - { - expr itp = GetAnnotation(node); - dualModel = is.get_model(); // TODO: what does this mean? - std::vector case_lits; - itp = StrengthenFormulaByCaseSplitting(itp, case_lits); - SetAnnotation(node,itp); - node->Annotation.Formula = node->Annotation.Formula.simplify(); - } - - for(unsigned i = 0; i < axioms_to_add.size(); i++) - is.add(axioms_to_add[i]); -#define TEST_BAD -#ifdef TEST_BAD { - static int bad_count = 0, num_bads = 1; - if(bad_count >= num_bads){ - bad_count = 0; - num_bads = num_bads * 2; + check_result foo = Check(root); + if(foo != unsat){ Pop(1); is.pop(1); delete core; timer_stop("InterpolateByCases"); - throw Bad(); + throw ReallyBad(); + // slvr().print("should_be_unsat.smt2"); + // throw "should be unsat"; } - bad_count++; - } -#endif + std::vector assumps, axioms_to_add; + slvr().get_proof().get_assumptions(assumps); + for(unsigned i = 0; i < assumps.size(); i++){ + (*core).insert(assumps[i]); + if(axioms_needed.find(assumps[i]) != axioms_needed.end()){ + axioms_to_add.push_back(assumps[i]); + axioms_needed.erase(assumps[i]); + } + } + // AddToProofCore(*core); + SolveSingleNode(root,node); - if(node->Annotation.IsEmpty()){ + { + expr itp = GetAnnotation(node); + dualModel = is.get_model(); // TODO: what does this mean? + std::vector case_lits; + itp = StrengthenFormulaByCaseSplitting(itp, case_lits); + SetAnnotation(node,itp); + node->Annotation.Formula = node->Annotation.Formula.simplify(); + } + + for(unsigned i = 0; i < axioms_to_add.size(); i++) + is.add(axioms_to_add[i]); + +#define TEST_BAD +#ifdef TEST_BAD + { + static int bad_count = 0, num_bads = 1; + if(bad_count >= num_bads){ + bad_count = 0; + num_bads = num_bads * 2; + Pop(1); + is.pop(1); + delete core; + timer_stop("InterpolateByCases"); + throw Bad(); + } + bad_count++; + } +#endif + } + + if(node->Annotation.IsEmpty() || eq(node->Annotation.Formula,prev_annot) || (repeated_case_count > 0 && !axioms_added) || (repeated_case_count >= 10)){ + looks_bad: if(!axioms_added){ // add the axioms in the off chance they are useful const std::vector &theory = ls->get_axioms(); @@ -3134,6 +3156,7 @@ namespace Duality { axioms_added = true; } else { + //#define KILL_ON_BAD_INTERPOLANT #ifdef KILL_ON_BAD_INTERPOLANT std::cout << "bad in InterpolateByCase -- core:\n"; #if 0 @@ -3175,10 +3198,11 @@ namespace Duality { is.pop(1); delete core; timer_stop("InterpolateByCases"); - throw Bad(); + throw ReallyBad(); } } Pop(1); + prev_annot = node->Annotation.Formula; node->Annotation.UnionWith(old_annot); } if(proof_core) diff --git a/src/duality/duality_solver.cpp b/src/duality/duality_solver.cpp index 69759f9bb..b40ab9370 100755 --- a/src/duality/duality_solver.cpp +++ b/src/duality/duality_solver.cpp @@ -2279,6 +2279,18 @@ namespace Duality { // bad interpolants can get us here throw DoRestart(); } + catch(const RPFP::ReallyBad &){ + // this could be caused by incompleteness + for(unsigned i = 0; i < expansions.size(); i++){ + Node *node = expansions[i]; + node->map->Annotation.SetFull(); + std::vector &chs = node->map->Outgoing->Children; + for(unsigned j = 0; j < chs.size(); j++) + chs[j]->Annotation.SetFull(); + reporter->Message("incompleteness: cleared annotation and child annotations"); + } + throw DoRestart(); + } catch(char const *msg){ // bad interpolants can get us here reporter->Message(std::string("interpolation failure:") + msg); diff --git a/src/interp/iz3mgr.cpp b/src/interp/iz3mgr.cpp index a39065922..e3ac59dfd 100755 --- a/src/interp/iz3mgr.cpp +++ b/src/interp/iz3mgr.cpp @@ -778,6 +778,8 @@ int iz3mgr::occurs_in(ast var, ast e){ bool iz3mgr::solve_arith(const ast &v, const ast &x, const ast &y, ast &res){ + if(occurs_in(v,y)) + return false; if(op(x) == Plus){ int n = num_args(x); for(int i = 0; i < n; i++){ @@ -801,8 +803,8 @@ iz3mgr::ast iz3mgr::cont_eq(stl_ext::hash_set &cont_eq_memo, bool truth, as return ast(); cont_eq_memo.insert(e); if(!truth && op(e) == Equal){ - if(arg(e,0) == v) return(arg(e,1)); - if(arg(e,1) == v) return(arg(e,0)); + if(arg(e,0) == v && !occurs_in(v,arg(e,1))) return(arg(e,1)); + if(arg(e,1) == v && !occurs_in(v,arg(e,0))) return(arg(e,0)); ast res; if(solve_arith(v,arg(e,0),arg(e,1),res)) return res; if(solve_arith(v,arg(e,1),arg(e,0),res)) return res; diff --git a/src/interp/iz3mgr.h b/src/interp/iz3mgr.h index 3ec2c42d1..7f66bb2d8 100755 --- a/src/interp/iz3mgr.h +++ b/src/interp/iz3mgr.h @@ -278,7 +278,8 @@ class iz3mgr { } symb sym(ast t){ - return to_app(t.raw())->get_decl(); + raw_ast *_ast = t.raw(); + return is_app(_ast) ? to_app(_ast)->get_decl() : 0; } std::string string_of_symbol(symb s){ From b4600ffda00b0ba2ba874effb1cb6e3139e6a6cd Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 31 Oct 2014 14:24:21 +0100 Subject: [PATCH 099/117] add print to SMT-LIB format from solver Signed-off-by: Nikolaj Bjorner --- examples/c++/example.cpp | 1 + src/api/c++/z3++.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index b348e7d36..0d8a3ceb3 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -21,6 +21,7 @@ void demorgan() { // adding the negation of the conjecture as a constraint. s.add(!conjecture); std::cout << s << "\n"; + std::cout << s.to_smt2() << "\n"; switch (s.check()) { case unsat: std::cout << "de-Morgan is valid\n"; break; case sat: std::cout << "de-Morgan is not valid\n"; break; diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index c35208d86..7380e52f1 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -1314,6 +1314,26 @@ namespace z3 { expr_vector assertions() const { Z3_ast_vector r = Z3_solver_get_assertions(ctx(), m_solver); check_error(); return expr_vector(ctx(), r); } expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); } friend std::ostream & operator<<(std::ostream & out, solver const & s) { out << Z3_solver_to_string(s.ctx(), s); return out; } + + std::string to_smt2(char const* status = "unknown") { + array es(assertions()); + Z3_ast const* fmls = es.ptr(); + Z3_ast fml = 0; + unsigned sz = es.size(); + if (sz > 0) { + --sz; + fml = fmls[sz]; + } + else { + fml = ctx().bool_val(true); + } + return std::string(Z3_benchmark_to_smtlib_string( + ctx(), + "", "", status, "", + sz, + fmls, + fml)); + } }; class goal : public object { From 591f6d096f437445c56b51292e75fe757cd48dd1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 3 Nov 2014 14:26:57 +0000 Subject: [PATCH 100/117] .NET API project directories fixed. Thanks to Marc Brockschmidt for reporting this. --- src/api/dotnet/Microsoft.Z3.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/dotnet/Microsoft.Z3.csproj b/src/api/dotnet/Microsoft.Z3.csproj index cc7d3c0c5..36bd6ad02 100644 --- a/src/api/dotnet/Microsoft.Z3.csproj +++ b/src/api/dotnet/Microsoft.Z3.csproj @@ -19,12 +19,12 @@ true full false - ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ + ..\Debug\ DEBUG;TRACE prompt 4 true - C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML + ..\Debug\Microsoft.Z3.XML False False True @@ -254,7 +254,7 @@ true - ..\..\..\..\..\cwinter\bugs\z3bugs\Debug\ + ..\x86\Debug\ DEBUG;TRACE true full @@ -266,7 +266,7 @@ MinimumRecommendedRules.ruleset ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules - C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML + ..\x86\Debug\Microsoft.Z3.XML bin\x86\Release\ From adeae184718a40e008823a0405bc679a5842a91b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 6 Nov 2014 13:09:25 +0100 Subject: [PATCH 101/117] delay initializing internal manager so that parser does not choke on proper SMT-LIB logics. Reported by Venkateshan Signed-off-by: Nikolaj Bjorner --- src/api/z3_api.h | 8 ++++++++ src/cmd_context/cmd_context.cpp | 33 ++++++++++++++++++++------------- src/cmd_context/cmd_context.h | 1 + 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 248d2161e..71a6dde2b 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -3988,6 +3988,12 @@ END_MLAPI_EXCLUDE /** \brief Return a unique identifier for \c t. + The identifier is unique up to structural equality. Thus, two ast nodes + created by the same context and having the same children and same function symbols + have the same identifiers. Ast nodes created in the same context, but having + different children or different functions have different identifiers. + Variables and quantifiers are also assigned different identifiers according to + their structure. \mlonly \remark Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. \endmlonly def_API('Z3_get_ast_id', UINT, (_in(CONTEXT), _in(AST))) @@ -3996,6 +4002,8 @@ END_MLAPI_EXCLUDE /** \brief Return a hash code for the given AST. + The hash code is structural. You can use Z3_get_ast_id interchangably with + this function. \mlonly \remark Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. \endmlonly def_API('Z3_get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 731608524..7fa2dc53f 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -314,8 +314,9 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): m_numeral_as_real(false), m_ignore_check(false), m_exit_on_error(false), - m_manager(m), + m_manager(m), m_own_manager(m == 0), + m_manager_initialized(false), m_pmanager(0), m_sexpr_manager(0), m_regular("stdout", std::cout), @@ -326,8 +327,6 @@ cmd_context::cmd_context(bool main_ctx, ast_manager * m, symbol const & l): install_core_tactic_cmds(*this); install_interpolant_cmds(*this); SASSERT(m != 0 || !has_manager()); - if (m) - init_external_manager(); if (m_main_ctx) { set_verbose_stream(diagnostic_stream()); } @@ -620,12 +619,22 @@ void cmd_context::init_manager_core(bool new_manager) { } void cmd_context::init_manager() { - SASSERT(m_manager == 0); - SASSERT(m_pmanager == 0); - m_check_sat_result = 0; - m_manager = m_params.mk_ast_manager(); - m_pmanager = alloc(pdecl_manager, *m_manager); - init_manager_core(true); + if (m_manager_initialized) { + // no-op + } + else if (m_manager) { + SASSERT(!m_own_manager); + init_external_manager(); + m_manager_initialized = true; + } + else { + SASSERT(m_pmanager == 0); + m_check_sat_result = 0; + m_manager = m_params.mk_ast_manager(); + m_pmanager = alloc(pdecl_manager, *m_manager); + init_manager_core(true); + m_manager_initialized = true; + } } void cmd_context::init_external_manager() { @@ -1211,8 +1220,7 @@ void cmd_context::assert_expr(symbol const & name, expr * t) { void cmd_context::push() { m_check_sat_result = 0; - if (!has_manager()) - init_manager(); + init_manager(); m_scopes.push_back(scope()); scope & s = m_scopes.back(); s.m_func_decls_stack_lim = m_func_decls_stack.size(); @@ -1332,8 +1340,7 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions return; IF_VERBOSE(100, verbose_stream() << "(started \"check-sat\")" << std::endl;); TRACE("before_check_sat", dump_assertions(tout);); - if (!has_manager()) - init_manager(); + init_manager(); if (m_solver) { m_check_sat_result = m_solver.get(); // solver itself stores the result. m_solver->set_progress_callback(this); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 8ad07e8cc..7c42f41cf 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -149,6 +149,7 @@ protected: ast_manager * m_manager; bool m_own_manager; + bool m_manager_initialized; pdecl_manager * m_pmanager; sexpr_manager * m_sexpr_manager; check_logic m_check_logic; From 23bc982ad24e27feb6ad0635f23fce0a6b8ad8be Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 6 Nov 2014 16:53:51 +0100 Subject: [PATCH 102/117] move initialization to support more sort usage scenarios Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 4 ++-- src/cmd_context/cmd_context.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 7fa2dc53f..5d24977b5 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -623,17 +623,17 @@ void cmd_context::init_manager() { // no-op } else if (m_manager) { + m_manager_initialized = true; SASSERT(!m_own_manager); init_external_manager(); - m_manager_initialized = true; } else { + m_manager_initialized = true; SASSERT(m_pmanager == 0); m_check_sat_result = 0; m_manager = m_params.mk_ast_manager(); m_pmanager = alloc(pdecl_manager, *m_manager); init_manager_core(true); - m_manager_initialized = true; } } diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 7c42f41cf..c4aa34c61 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -294,7 +294,7 @@ public: std::string reason_unknown() const; bool has_manager() const { return m_manager != 0; } - ast_manager & m() const { if (!m_manager) const_cast(this)->init_manager(); return *m_manager; } + ast_manager & m() const { const_cast(this)->init_manager(); return *m_manager; } virtual ast_manager & get_ast_manager() { return m(); } pdecl_manager & pm() const { if (!m_pmanager) const_cast(this)->init_manager(); return *m_pmanager; } sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; } From ce7303b5e2713be2909a39d862c0fe2bba8659c5 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Nov 2014 15:44:21 +0100 Subject: [PATCH 103/117] fix reset logic and load only logics admitted by context Signed-off-by: Nikolaj Bjorner --- src/cmd_context/cmd_context.cpp | 30 ++++++++++++++++++++++++++---- src/cmd_context/cmd_context.h | 1 + 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 5d24977b5..ee5437bd6 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -470,6 +470,16 @@ void cmd_context::register_plugin(symbol const & name, decl_plugin * p, bool ins } } +void cmd_context::load_plugin(symbol const & name, bool install, svector& fids) { + family_id id = m_manager->get_family_id(name); + decl_plugin* p = m_manager->get_plugin(id); + if (install && p && fids.contains(id)) { + register_builtin_sorts(p); + register_builtin_ops(p); + } + fids.erase(id); +} + bool cmd_context::logic_has_arith_core(symbol const & s) const { return s == "QF_LRA" || @@ -586,17 +596,26 @@ void cmd_context::init_manager_core(bool new_manager) { register_builtin_sorts(basic); register_builtin_ops(basic); // the manager was created by the command context. - register_plugin(symbol("arith"), alloc(arith_decl_plugin), logic_has_arith()); - register_plugin(symbol("bv"), alloc(bv_decl_plugin), logic_has_bv()); - register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); + register_plugin(symbol("arith"), alloc(arith_decl_plugin), logic_has_arith()); + register_plugin(symbol("bv"), alloc(bv_decl_plugin), logic_has_bv()); + register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array()); register_plugin(symbol("datatype"), alloc(datatype_decl_plugin), logic_has_datatype()); register_plugin(symbol("seq"), alloc(seq_decl_plugin), logic_has_seq()); register_plugin(symbol("float"), alloc(float_decl_plugin), logic_has_floats()); } else { - // the manager was created by an external module, we must register all plugins available in the manager. + // the manager was created by an external module + // we register all plugins available in the manager. + // unless the logic specifies otherwise. svector fids; m_manager->get_range(fids); + load_plugin(symbol("arith"), logic_has_arith(), fids); + load_plugin(symbol("bv"), logic_has_bv(), fids); + load_plugin(symbol("array"), logic_has_array(), fids); + load_plugin(symbol("datatype"), logic_has_datatype(), fids); + load_plugin(symbol("seq"), logic_has_seq(), fids); + load_plugin(symbol("float"), logic_has_floats(), fids); + svector::iterator it = fids.begin(); svector::iterator end = fids.end(); for (; it != end; ++it) { @@ -1174,12 +1193,15 @@ void cmd_context::reset(bool finalize) { if (m_own_manager) { dealloc(m_manager); m_manager = 0; + m_manager_initialized = false; } else { // doesn't own manager... so it cannot be deleted // reinit cmd_context if this is not a finalization step if (!finalize) init_external_manager(); + else + m_manager_initialized = false; } } if (m_sexpr_manager) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index c4aa34c61..1c8dba21a 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -214,6 +214,7 @@ protected: void register_builtin_sorts(decl_plugin * p); void register_builtin_ops(decl_plugin * p); void register_plugin(symbol const & name, decl_plugin * p, bool install_names); + void load_plugin(symbol const & name, bool install_names, svector& fids); void init_manager_core(bool new_manager); void init_manager(); void init_external_manager(); From cf8ad072d017aada57ed2d342fc6bec6ddd0929a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 7 Nov 2014 16:03:27 +0100 Subject: [PATCH 104/117] remove unused variable Signed-off-by: Nikolaj Bjorner --- src/smt/theory_array_base.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index b2c17b4e0..b33e6b4e6 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -362,7 +362,6 @@ namespace smt { (store A i v) <--- v is used as an value */ bool theory_array_base::is_shared(theory_var v) const { - context & ctx = get_context(); enode * n = get_enode(v); enode * r = n->get_root(); bool is_array = false; From 005bb82a1751f3d70705bff9819acdec608d9f41 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 7 Nov 2014 16:04:02 +0000 Subject: [PATCH 105/117] eliminated unused variables --- src/ast/fpa/fpa2bv_converter.cpp | 42 ++++++++++++++++---------------- src/interp/iz3base.h | 2 +- src/interp/iz3proof_itp.cpp | 3 ++- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/ast/fpa/fpa2bv_converter.cpp b/src/ast/fpa/fpa2bv_converter.cpp index 5f92b4d94..c23de3bfa 100644 --- a/src/ast/fpa/fpa2bv_converter.cpp +++ b/src/ast/fpa/fpa2bv_converter.cpp @@ -2155,15 +2155,15 @@ void fpa2bv_converter::mk_to_ubv(func_decl * f, unsigned num, expr * const * arg SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2173,15 +2173,15 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg SASSERT(f->get_num_parameters() == 1); SASSERT(f->get_parameter(0).is_int()); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } @@ -2189,15 +2189,15 @@ void fpa2bv_converter::mk_to_sbv(func_decl * f, unsigned num, expr * const * arg void fpa2bv_converter::mk_to_real(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { SASSERT(num == 1); - unsigned ebits = m_util.get_ebits(f->get_range()); - unsigned sbits = m_util.get_sbits(f->get_range()); - int width = f->get_parameter(0).get_int(); + //unsigned ebits = m_util.get_ebits(f->get_range()); + //unsigned sbits = m_util.get_sbits(f->get_range()); + //int width = f->get_parameter(0).get_int(); - expr * rm = args[0]; - expr * x = args[1]; + //expr * rm = args[0]; + //expr * x = args[1]; - expr * sgn, *s, *e; - split(x, sgn, s, e); + //expr * sgn, *s, *e; + //split(x, sgn, s, e); NOT_IMPLEMENTED_YET(); } diff --git a/src/interp/iz3base.h b/src/interp/iz3base.h index bca9b8518..956191290 100755 --- a/src/interp/iz3base.h +++ b/src/interp/iz3base.h @@ -161,7 +161,7 @@ class iz3base : public iz3mgr, public scopes { stl_ext::hash_map simplify_memo; stl_ext::hash_map frame_map; // map assertions to frames - int frames; // number of frames + // int frames; // number of frames protected: void add_frame_range(int frame, ast t); diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index 52ddcd64f..b487b2892 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -2747,7 +2747,8 @@ class iz3proof_itp_impl : public iz3proof_itp { ast orig_e = e; pf = make_refl(e); // proof that e = e - prover::range erng = pv->ast_scope(e); + // prover::range erng = + pv->ast_scope(e); #if 0 if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){ return e; // this term occurs in range, so it's O.K. From a309dbfdc2b3ebca65946b6afe443e815a1f1cee Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 12 Nov 2014 20:28:11 -0800 Subject: [PATCH 106/117] coerce equality and ite upward instead of downward for int2real coercions. Fixes bug reported by Enric Carbonell Signed-off-by: Nikolaj Bjorner --- src/ast/ast.cpp | 25 +++++++++++++++++++------ src/ast/ast.h | 3 ++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 68f7596ee..09965be85 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1013,6 +1013,17 @@ func_decl * basic_decl_plugin::mk_ite_decl(sort * s) { return m_ite_decls[id]; } +sort* basic_decl_plugin::join(sort* s1, sort* s2) { + if (s1 == s2) return s1; + if (s1->get_family_id() == m_manager->m_arith_family_id && + s2->get_family_id() == m_manager->m_arith_family_id) { + if (s1->get_decl_kind() == REAL_SORT) { + return s1; + } + } + return s2; +} + func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (static_cast(k)) { @@ -1025,10 +1036,10 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_IFF: return m_iff_decl; case OP_IMPLIES: return m_implies_decl; case OP_XOR: return m_xor_decl; - case OP_ITE: return arity == 3 ? mk_ite_decl(domain[1]) : 0; + case OP_ITE: return arity == 3 ? mk_ite_decl(join(domain[1], domain[2])) : 0; // eq and oeq must have at least two arguments, they can have more since they are chainable - case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, domain[0], m_eq_decls) : 0; - case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, domain[0], m_oeq_decls) : 0; + case OP_EQ: return arity >= 2 ? mk_eq_decl_core("=", OP_EQ, join(domain[0],domain[1]), m_eq_decls) : 0; + case OP_OEQ: return arity >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(domain[0],domain[1]), m_oeq_decls) : 0; case OP_DISTINCT: { func_decl_info info(m_family_id, OP_DISTINCT); info.set_pairwise(); @@ -1061,10 +1072,12 @@ func_decl * basic_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters case OP_IFF: return m_iff_decl; case OP_IMPLIES: return m_implies_decl; case OP_XOR: return m_xor_decl; - case OP_ITE: return num_args == 3 ? mk_ite_decl(m_manager->get_sort(args[1])): 0; + case OP_ITE: return num_args == 3 ? mk_ite_decl(join(m_manager->get_sort(args[1]), m_manager->get_sort(args[2]))): 0; // eq and oeq must have at least two arguments, they can have more since they are chainable - case OP_EQ: return num_args >= 2 ? mk_eq_decl_core("=", OP_EQ, m_manager->get_sort(args[0]), m_eq_decls) : 0; - case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, m_manager->get_sort(args[0]), m_oeq_decls) : 0; + case OP_EQ: return num_args >= 2 ? mk_eq_decl_core("=", OP_EQ, join(m_manager->get_sort(args[0]), + m_manager->get_sort(args[1])), m_eq_decls) : 0; + case OP_OEQ: return num_args >= 2 ? mk_eq_decl_core("~", OP_OEQ, join(m_manager->get_sort(args[0]), + m_manager->get_sort(args[1])), m_oeq_decls) : 0; case OP_DISTINCT: return decl_plugin::mk_func_decl(k, num_parameters, parameters, num_args, args, range); default: diff --git a/src/ast/ast.h b/src/ast/ast.h index 68f08e1ac..944c089f3 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1100,6 +1100,7 @@ protected: virtual void set_manager(ast_manager * m, family_id id); func_decl * mk_eq_decl_core(char const * name, decl_kind k, sort * s, ptr_vector & cache); func_decl * mk_ite_decl(sort * s); + sort* join(sort* s1, sort* s2); public: basic_decl_plugin(); @@ -1378,7 +1379,7 @@ enum proof_gen_mode { // ----------------------------------- class ast_manager { -protected: + friend basic_decl_plugin; protected: struct config { typedef ast_manager value_manager; From 4c5753f32144da6a4a8f244318a938e780d79dba Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 13 Nov 2014 18:08:24 -0800 Subject: [PATCH 107/117] be classy with your friends Signed-off-by: Nikolaj Bjorner --- src/ast/ast.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ast/ast.h b/src/ast/ast.h index 944c089f3..93f456965 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -1379,7 +1379,7 @@ enum proof_gen_mode { // ----------------------------------- class ast_manager { - friend basic_decl_plugin; + friend class basic_decl_plugin; protected: struct config { typedef ast_manager value_manager; From 213d816c0a418bafc8fe57acb4b10aeea5b1f5b2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 24 Nov 2014 18:10:54 +0000 Subject: [PATCH 108/117] Bugfix for bv_size_reduction. Thanks to user rsas for reporting this isse! Signed-off-by: Christoph M. Wintersteiger --- src/tactic/bv/bv_size_reduction_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index e149afc75..14a2fb28d 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -229,7 +229,7 @@ struct bv_size_reduction_tactic::imp { else { // l < u if (l.is_neg()) { - unsigned i_nb = (u - l).get_num_bits(); + unsigned i_nb = (u - l).get_num_bits() + 1; unsigned v_nb = m_util.get_bv_size(v); if (i_nb < v_nb) { new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); From 53cfa472141fc9dd5c6f07e62a1786243636f846 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 25 Nov 2014 14:22:50 +0000 Subject: [PATCH 109/117] bugfix for bv_size_reduction Signed-off-by: Christoph M. Wintersteiger --- src/tactic/bv/bv_size_reduction_tactic.cpp | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index 14a2fb28d..5e32bf6c4 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -229,17 +229,35 @@ struct bv_size_reduction_tactic::imp { else { // l < u if (l.is_neg()) { - unsigned i_nb = (u - l).get_num_bits() + 1; + unsigned l_nb = (-l).get_num_bits(); unsigned v_nb = m_util.get_bv_size(v); - if (i_nb < v_nb) { - new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); - new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const); + + if (u.is_neg()) + { + // l <= v <= u <= 0 + unsigned i_nb = l_nb; + TRACE("bv_size_reduction", tout << " l <= " << v->get_decl()->get_name() << " <= u <= 0 " << " --> " << i_nb << " bits\n";); + if (i_nb < v_nb) { + new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); + new_def = m_util.mk_concat(m_util.mk_numeral(numeral(-1), v_nb - i_nb), new_const); + } + } + else { + // l <= v <= 0 <= u + unsigned u_nb = u.get_num_bits(); + unsigned i_nb = ((l_nb > u_nb) ? l_nb : u_nb) + 1; + TRACE("bv_size_reduction", tout << " l <= " << v->get_decl()->get_name() << " <= 0 <= u " << " --> " << i_nb << " bits\n";); + if (i_nb < v_nb) { + new_const = m.mk_fresh_const(0, m_util.mk_sort(i_nb)); + new_def = m_util.mk_sign_extend(v_nb - i_nb, new_const); + } } } else { // 0 <= l <= v <= u unsigned u_nb = u.get_num_bits(); unsigned v_nb = m_util.get_bv_size(v); + TRACE("bv_size_reduction", tout << l << " <= " << v->get_decl()->get_name() << " <= " << u << " --> " << u_nb << " bits\n";); if (u_nb < v_nb) { new_const = m.mk_fresh_const(0, m_util.mk_sort(u_nb)); new_def = m_util.mk_concat(m_util.mk_numeral(numeral(0), v_nb - u_nb), new_const); From 59dfd2abe451b9f0c5cb0218f53699f8bdf49a37 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 25 Nov 2014 14:54:47 +0000 Subject: [PATCH 110/117] fixed problem with Python 3.4.x complainging of inconsistent use of spaces/tabs. Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index e58e47640..851e8e243 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -298,8 +298,8 @@ class AstRef(Z3PPObject): return self.ast def get_id(self): - """Return unique identifier for object. It can be used for hash-tables and maps.""" - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + """Return unique identifier for object. It can be used for hash-tables and maps.""" + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def ctx_ref(self): @@ -453,7 +453,7 @@ class SortRef(AstRef): return Z3_sort_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def kind(self): @@ -595,7 +595,7 @@ class FuncDeclRef(AstRef): return Z3_func_decl_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def as_func_decl(self): return self.ast @@ -743,7 +743,7 @@ class ExprRef(AstRef): return self.ast def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def sort(self): """Return the sort of expression `self`. @@ -1540,7 +1540,7 @@ class PatternRef(ExprRef): return Z3_pattern_to_ast(self.ctx_ref(), self.ast) def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def is_pattern(a): """Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation. @@ -1605,7 +1605,7 @@ class QuantifierRef(BoolRef): return self.ast def get_id(self): - return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) + return Z3_get_ast_id(self.ctx_ref(), self.as_ast()) def sort(self): """Return the Boolean sort.""" @@ -6033,20 +6033,20 @@ class Solver(Z3PPObject): return Z3_solver_to_string(self.ctx.ref(), self.solver) def to_smt2(self): - """return SMTLIB2 formatted benchmark for solver's assertions""" - es = self.assertions() - sz = len(es) - sz1 = sz - if sz1 > 0: - sz1 -= 1 - v = (Ast * sz1)() - for i in range(sz1): - v[i] = es[i].as_ast() - if sz > 0: - e = es[sz1].as_ast() - else: - e = BoolVal(True, self.ctx).as_ast() - return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) + """return SMTLIB2 formatted benchmark for solver's assertions""" + es = self.assertions() + sz = len(es) + sz1 = sz + if sz1 > 0: + sz1 -= 1 + v = (Ast * sz1)() + for i in range(sz1): + v[i] = es[i].as_ast() + if sz > 0: + e = es[sz1].as_ast() + else: + e = BoolVal(True, self.ctx).as_ast() + return Z3_benchmark_to_smtlib_string(self.ctx.ref(), "benchmark generated from python API", "", "unknown", "", sz1, v, e) From 1a396b0bd2eebe4f3ad7826cfec1fd8cbb7574cf Mon Sep 17 00:00:00 2001 From: Nuno Lopes Date: Tue, 25 Nov 2014 18:13:24 +0000 Subject: [PATCH 111/117] [BV size reduction] fix bug in detection of signed upperbound Signed-off-by: Nuno Lopes --- src/tactic/bv/bv_size_reduction_tactic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tactic/bv/bv_size_reduction_tactic.cpp b/src/tactic/bv/bv_size_reduction_tactic.cpp index 5e32bf6c4..707a9284b 100644 --- a/src/tactic/bv/bv_size_reduction_tactic.cpp +++ b/src/tactic/bv/bv_size_reduction_tactic.cpp @@ -151,7 +151,7 @@ struct bv_size_reduction_tactic::imp { // bound is infeasible. } else { - update_signed_upper(to_app(lhs), val); + update_signed_upper(to_app(rhs), val); } } else update_signed_lower(to_app(rhs), val); From c88b2f6b5ebbaf34ab5a610008d054cee8da869a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 2 Dec 2014 14:35:15 +0000 Subject: [PATCH 112/117] .NET API: Added build instructions for .NET 3.5 Signed-off-by: Christoph M. Wintersteiger --- src/api/dotnet/Readme.NET35 | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/api/dotnet/Readme.NET35 diff --git a/src/api/dotnet/Readme.NET35 b/src/api/dotnet/Readme.NET35 new file mode 100644 index 000000000..73743fd15 --- /dev/null +++ b/src/api/dotnet/Readme.NET35 @@ -0,0 +1,9 @@ +The default Z3 bindings for .NET are built for the .NET framework version 4. +Should the need arise, it is also possible to build them for .NET 3.5; the +instructions are as follows: + +In the project properties of Microsoft.Z3.csproj: +- Under 'Application': Change Target framework to .NET Framework 3.5 +- Under 'Build': Add FRAMEWORK_LT_4 to the condidional compilation symbols +- Remove the reference to System.Numerics +- Install the NuGet Package "Microsoft Code Contracts for Net3.5" From 45755bbd140231ad08fcbc487d60fc00a2eee78f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 3 Dec 2014 08:55:14 +0900 Subject: [PATCH 113/117] fix context sensitivity. Codeplex issue 148, thanks to clockish Signed-off-by: Nikolaj Bjorner --- src/api/python/z3.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 851e8e243..db629cd2d 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -6166,7 +6166,7 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name) else: body = _get_args(body) - f = self.abstract(Implies(And(body),head)) + f = self.abstract(Implies(And(body, self.ctx),head)) Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) def rule(self, head, body = None, name = None): @@ -6194,7 +6194,7 @@ class Fixedpoint(Z3PPObject): if sz == 1: query = query[0] else: - query = And(query) + query = And(query, self.ctx) query = self.abstract(query, False) r = Z3_fixedpoint_query(self.ctx.ref(), self.fixedpoint, query.as_ast()) return CheckSatResult(r) @@ -6213,7 +6213,7 @@ class Fixedpoint(Z3PPObject): name = "" name = to_symbol(name, self.ctx) body = _get_args(body) - f = self.abstract(Implies(And(body),head)) + f = self.abstract(Implies(And(body, self.ctx),head)) Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) def get_answer(self): From 8181b15a1bc86123a4f2c15de2f9cabe8bdbc481 Mon Sep 17 00:00:00 2001 From: Ken McMillan Date: Mon, 8 Dec 2014 15:46:55 -0800 Subject: [PATCH 114/117] attempted interp fixes --- src/interp/iz3proof_itp.cpp | 2 +- src/interp/iz3translate.cpp | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/interp/iz3proof_itp.cpp b/src/interp/iz3proof_itp.cpp index 52ddcd64f..df436d206 100755 --- a/src/interp/iz3proof_itp.cpp +++ b/src/interp/iz3proof_itp.cpp @@ -1027,7 +1027,7 @@ class iz3proof_itp_impl : public iz3proof_itp { linear_comb(Aineqs,coeff,make(Leq,make_int(rational(0)),make(Sub,term2,term1))); } else { - ast pf = extract_rewrites(make(concat,mk_true(),rest),p1); + ast pf = extract_rewrites(make(concat,mk_true(),last),p1); ast new_normal = fix_normal(term1,term2,pf); normals = merge_normal_chains(normals,cons_normal(new_normal,mk_true()), Aproves, Bproves); } diff --git a/src/interp/iz3translate.cpp b/src/interp/iz3translate.cpp index 26786d57a..f65ec72d4 100755 --- a/src/interp/iz3translate.cpp +++ b/src/interp/iz3translate.cpp @@ -1712,11 +1712,17 @@ public: std::cout << "foo!\n"; // no idea why this shows up - if(dk == PR_MODUS_PONENS_OEQ) + if(dk == PR_MODUS_PONENS_OEQ){ if(conc(prem(proof,0)) == con){ res = translate_main(prem(proof,0),expect_clause); return res; } + if(expect_clause && op(con) == Or){ // skolemization does this + Iproof::node clause = translate_main(prem(proof,0),true); + res = RewriteClause(clause,prem(proof,1)); + return res; + } + } #if 0 if(1 && dk == PR_TRANSITIVITY && pr(prem(proof,1)) == PR_COMMUTATIVITY){ @@ -1800,7 +1806,9 @@ public: } break; } - case PR_MONOTONICITY: { + case PR_QUANT_INTRO: + case PR_MONOTONICITY: + { std::vector eqs; eqs.resize(args.size()); for(unsigned i = 0; i < args.size(); i++) eqs[i] = conc(prem(proof,i)); From 1244d5a22ef196ce730ebf9fd94970419cbdcb8d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 16 Dec 2014 15:28:52 +0000 Subject: [PATCH 115/117] Python API: Added BVRedAnd, BVRedOr Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index db629cd2d..713226e23 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -3813,6 +3813,18 @@ def RepeatBitVec(n, a): _z3_assert(is_bv(a), "Second argument must be a Z3 Bitvector expression") return BitVecRef(Z3_mk_repeat(a.ctx_ref(), n, a.as_ast()), a.ctx) +def BVRedAnd(a): + """Return the reduction-and expression of `a`.""" + if __debug__: + _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression") + return BitVecRef(Z3_mk_bvredand(a.ctx_ref(), a.as_ast()), a.ctx) + +def BVRedOr(a): + """Return the reduction-and expression of `a`.""" + if __debug__: + _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression") + return BitVecRef(Z3_mk_bvredor(a.ctx_ref(), a.as_ast()), a.ctx) + ######################################### # # Arrays From d53fdb284858f331b3d577067926a626d23e8571 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 16 Dec 2014 15:36:31 +0000 Subject: [PATCH 116/117] typo Signed-off-by: Christoph M. Wintersteiger --- src/api/python/z3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 713226e23..720335d41 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -3820,7 +3820,7 @@ def BVRedAnd(a): return BitVecRef(Z3_mk_bvredand(a.ctx_ref(), a.as_ast()), a.ctx) def BVRedOr(a): - """Return the reduction-and expression of `a`.""" + """Return the reduction-or expression of `a`.""" if __debug__: _z3_assert(is_bv(a), "First argument must be a Z3 Bitvector expression") return BitVecRef(Z3_mk_bvredor(a.ctx_ref(), a.as_ast()), a.ctx) From f4d256ef306dfb22aef306e73d1d7a90668aae5b Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 16 Dec 2014 11:20:34 -0800 Subject: [PATCH 117/117] fix issue 153: assert rem/mod axiom no matter what is status of second argument Signed-off-by: Nikolaj Bjorner --- README | 2 ++ src/smt/smt_context.cpp | 7 +++---- src/smt/theory_arith_core.h | 33 ++++++++++++++++----------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README b/README index 1ca0cd577..074abd2a3 100644 --- a/README +++ b/README @@ -41,3 +41,5 @@ Remark: clang does not support OpenMP yet. cd build make + +To clean Z3 you can delete the build directory and run the mk_make.py script again. \ No newline at end of file diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index f3f2d4948..957d5ebe7 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -3321,13 +3321,13 @@ namespace smt { CASSERT("dyn_ack", check_clauses(m_lemmas) && check_clauses(m_aux_clauses)); } - if (resource_limits_exceeded()) { - SASSERT(!inconsistent()); + if (resource_limits_exceeded() && !inconsistent()) { return l_undef; } if (m_base_lvl == m_scope_lvl && m_fparams.m_simplify_clauses) simplify_clauses(); + if (!decide()) { final_check_status fcs = final_check(); @@ -3342,8 +3342,7 @@ namespace smt { } } - if (resource_limits_exceeded()) { - SASSERT(!inconsistent()); + if (resource_limits_exceeded() && !inconsistent()) { return l_undef; } } diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index 66d232227..a7f442e1f 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -336,8 +336,9 @@ namespace smt { theory_var theory_arith::internalize_rem(app * n) { theory_var s = mk_binary_op(n); context & ctx = get_context(); - if (!ctx.relevancy()) + if (!ctx.relevancy()) { mk_rem_axiom(n->get_arg(0), n->get_arg(1)); + } return s; } @@ -456,22 +457,20 @@ namespace smt { template void theory_arith::mk_rem_axiom(expr * dividend, expr * divisor) { - if (!m_util.is_zero(divisor)) { - // if divisor is zero, then rem is an uninterpreted function. - ast_manager & m = get_manager(); - expr * zero = m_util.mk_numeral(rational(0), true); - expr * rem = m_util.mk_rem(dividend, divisor); - expr * mod = m_util.mk_mod(dividend, divisor); - expr_ref dltz(m), eq1(m), eq2(m); - dltz = m_util.mk_lt(divisor, zero); - eq1 = m.mk_eq(rem, mod); - eq2 = m.mk_eq(rem, m_util.mk_sub(zero, mod)); - // n < 0 || rem(a,n) = mod(a, n) - mk_axiom(dltz, eq1); - dltz = m.mk_not(dltz); - // !n < 0 || rem(a,n) = -mod(a, n) - mk_axiom(dltz, eq2); - } + // if divisor is zero, then rem is an uninterpreted function. + ast_manager & m = get_manager(); + expr * zero = m_util.mk_numeral(rational(0), true); + expr * rem = m_util.mk_rem(dividend, divisor); + expr * mod = m_util.mk_mod(dividend, divisor); + expr_ref dltz(m), eq1(m), eq2(m); + dltz = m_util.mk_lt(divisor, zero); + eq1 = m.mk_eq(rem, mod); + eq2 = m.mk_eq(rem, m_util.mk_sub(zero, mod)); + // n < 0 || rem(a,n) = mod(a, n) + mk_axiom(dltz, eq1); + dltz = m.mk_not(dltz); + // !n < 0 || rem(a,n) = -mod(a, n) + mk_axiom(dltz, eq2); } //