diff --git a/scripts/update_api.py b/scripts/update_api.py index fa6111482..3d8a5dfaf 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -949,6 +949,11 @@ def def_API(name, result, params): log_c.write(" }\n") log_c.write(" Au(a%s);\n" % sz) exe_c.write("in.get_uint_array(%s)" % i) + elif ty == INT: + log_c.write("U(a%s[i]);" % i) + log_c.write(" }\n") + log_c.write(" Au(a%s);\n" % sz) + exe_c.write("in.get_int_array(%s)" % i) else: error ("unsupported parameter for %s, %s" % (name, p)) elif kind == OUT_ARRAY: diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 2b8c74e65..57ab9a1b7 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -874,6 +874,12 @@ typedef enum - Z3_OP_DT_ACCESSOR: datatype accessor. + - Z3_OP_PB_AT_MOST: Cardinality constraint. + E.g., x + y + z <= 2 + + - Z3_OP_PB_LE: Generalized Pseudo-Boolean cardinality constraint. + Example 2*x + 3*y <= 4 + - Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols. */ typedef enum { @@ -1054,6 +1060,10 @@ typedef enum { Z3_OP_DT_RECOGNISER, Z3_OP_DT_ACCESSOR, + // Pseudo Booleans + Z3_OP_PB_AT_MOST=0x900, + Z3_OP_PB_LE, + Z3_OP_UNINTERPRETED } Z3_decl_kind; @@ -3758,6 +3768,29 @@ END_MLAPI_EXCLUDE Z3_sort Z3_API Z3_get_relation_column(__in Z3_context c, __in Z3_sort s, unsigned col); + /** + \brief Pseudo-Boolean relations. + + Encode p1 + p2 + ... + pn <= k + + def_API('Z3_mk_atmost', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT))) + */ + + Z3_ast Z3_API Z3_mk_atmost(__in Z3_context c, __in unsigned num_args, + __in_ecount(num_args) Z3_ast const args[], __in unsigned k); + + /** + \brief Pseudo-Boolean relations. + + Encode k1*p1 + k2*p2 + ... + kn*pn <= k + + def_API('Z3_mk_pble', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT))) + */ + + Z3_ast Z3_API Z3_mk_pble(__in Z3_context c, __in unsigned num_args, + __in_ecount(num_args) Z3_ast const args[], __in_ecount(num_args) int coeffs[], + __in int k); + /** \mlonly {3 {L Function Declarations}} \endmlonly */ diff --git a/src/api/z3_replayer.cpp b/src/api/z3_replayer.cpp index acdb10bf6..f13b2cbb8 100644 --- a/src/api/z3_replayer.cpp +++ b/src/api/z3_replayer.cpp @@ -44,7 +44,7 @@ struct z3_replayer::imp { size_t_map m_heap; svector m_cmds; - enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY }; + enum value_kind { INT64, UINT64, DOUBLE, STRING, SYMBOL, OBJECT, UINT_ARRAY, INT_ARRAY, SYMBOL_ARRAY, OBJECT_ARRAY }; struct value { value_kind m_kind; @@ -68,6 +68,7 @@ struct z3_replayer::imp { vector > m_obj_arrays; vector > m_sym_arrays; vector m_unsigned_arrays; + vector > m_int_arrays; imp(z3_replayer & o, std::istream & in): m_owner(o), @@ -295,6 +296,15 @@ struct z3_replayer::imp { v.push_back(static_cast(m_args[i].m_uint)); } } + if (k == INT64) { + aidx = m_int_arrays.size(); + nk = INT_ARRAY; + m_int_arrays.push_back(svector()); + svector & v = m_int_arrays.back(); + for (unsigned i = asz - sz; i < asz; i++) { + v.push_back(static_cast(m_args[i].m_int)); + } + } else if (k == SYMBOL) { aidx = m_sym_arrays.size(); nk = SYMBOL_ARRAY; @@ -547,6 +557,13 @@ struct z3_replayer::imp { return m_unsigned_arrays[idx].c_ptr(); } + int * get_int_array(unsigned pos) const { + if (pos >= m_args.size() || m_args[pos].m_kind != INT_ARRAY) + throw_invalid_reference(); + unsigned idx = static_cast(m_args[pos].m_uint); + return m_int_arrays[idx].c_ptr(); + } + Z3_symbol * get_symbol_array(unsigned pos) const { if (pos >= m_args.size() || m_args[pos].m_kind != SYMBOL_ARRAY) throw_invalid_reference(); @@ -615,6 +632,7 @@ struct z3_replayer::imp { m_obj_arrays.reset(); m_sym_arrays.reset(); m_unsigned_arrays.reset(); + m_int_arrays.reset(); } @@ -673,6 +691,10 @@ unsigned * z3_replayer::get_uint_array(unsigned pos) const { return m_imp->get_uint_array(pos); } +int * z3_replayer::get_int_array(unsigned pos) const { + return m_imp->get_int_array(pos); +} + Z3_symbol * z3_replayer::get_symbol_array(unsigned pos) const { return m_imp->get_symbol_array(pos); } diff --git a/src/api/z3_replayer.h b/src/api/z3_replayer.h index 6de4bdb39..412032eb7 100644 --- a/src/api/z3_replayer.h +++ b/src/api/z3_replayer.h @@ -49,6 +49,7 @@ public: void * get_obj(unsigned pos) const; unsigned * get_uint_array(unsigned pos) const; + int * get_int_array(unsigned pos) const; Z3_symbol * get_symbol_array(unsigned pos) const; void ** get_obj_array(unsigned pos) const; diff --git a/src/ast/card_decl_plugin.cpp b/src/ast/card_decl_plugin.cpp index d32a2f5f2..6a15792e5 100644 --- a/src/ast/card_decl_plugin.cpp +++ b/src/ast/card_decl_plugin.cpp @@ -72,6 +72,16 @@ app * card_util::mk_at_most_k(unsigned num_args, expr * const * args, unsigned k return m.mk_app(m_fid, OP_AT_MOST_K, 1, ¶m, num_args, args, m.mk_bool_sort()); } +app * card_util::mk_le(unsigned num_args, int const * coeffs, expr * const * args, int k) { + vector params; + params.push_back(parameter(k)); + for (unsigned i = 0; i < num_args; ++i) { + params.push_back(parameter(coeffs[i])); + } + return m.mk_app(m_fid, OP_PB_LE, params.size(), params.c_ptr(), num_args, args, m.mk_bool_sort()); +} + + bool card_util::is_at_most_k(app *a) const { return is_app_of(a, m_fid, OP_AT_MOST_K); } diff --git a/src/ast/card_decl_plugin.h b/src/ast/card_decl_plugin.h index 28a22b0be..3ac681284 100644 --- a/src/ast/card_decl_plugin.h +++ b/src/ast/card_decl_plugin.h @@ -71,8 +71,9 @@ class card_util { public: card_util(ast_manager& m):m(m), m_fid(m.mk_family_id("card")) {} ast_manager & get_manager() const { return m; } + family_id get_family_id() const { return m_fid; } app * mk_at_most_k(unsigned num_args, expr * const * args, unsigned k); - app * mk_le(unsigned num_args, int * const* coeffs, expr * const * args, int k); + app * mk_le(unsigned num_args, int const * coeffs, expr * const * args, int k); bool is_at_most_k(app *a) const; bool is_at_most_k(app *a, unsigned& k) const; int get_k(app *a) const; diff --git a/src/opt/core_maxsat.cpp b/src/opt/core_maxsat.cpp index e131526cf..b4472971e 100644 --- a/src/opt/core_maxsat.cpp +++ b/src/opt/core_maxsat.cpp @@ -65,6 +65,7 @@ namespace opt { for (unsigned i = 0; i < ans.size(); ++i) { tout << mk_pp(ans[i].get(), m) << "\n"; }); + IF_VERBOSE(1, verbose_stream() << "(maxsat.core sat: " << ans.size() << "\n";); if (ans.size() > m_answer.size()) { m_answer.reset(); m_answer.append(ans); @@ -91,6 +92,7 @@ namespace opt { core_vars.insert(get_not(core[i])); block_vars.remove(core[i]); } + IF_VERBOSE(1, verbose_stream() << "(maxsat.core unsat (core size = " << core.size() << ")\n";); if (core.empty()) { m_upper = m_answer.size(); return l_true; diff --git a/src/opt/fu_malik.cpp b/src/opt/fu_malik.cpp index 5c5bace02..6ba3bba39 100644 --- a/src/opt/fu_malik.cpp +++ b/src/opt/fu_malik.cpp @@ -73,7 +73,7 @@ namespace opt { */ lbool step() { - IF_VERBOSE(1, verbose_stream() << "(opt.max_sat step)\n";); + IF_VERBOSE(1, verbose_stream() << "(opt.max_sat step)\n";); // add some count, add some information of # of soft constraints still possibly sat. expr_ref_vector assumptions(m), block_vars(m); for (unsigned i = 0; i < m_soft.size(); ++i) { assumptions.push_back(m.mk_not(m_aux[i].get()));