mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 10:55:50 +00:00
merge with master
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
3533bf486f
223 changed files with 7175 additions and 2167 deletions
|
@ -309,6 +309,22 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_domain_n(Z3_context c, Z3_sort t, unsigned idx) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_domain_n(c, t, idx);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_VALID_AST(t, nullptr);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT &&
|
||||
get_array_arity(to_sort(t)) > idx) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(get_array_domain(to_sort(t), idx));
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG, nullptr);
|
||||
RETURN_Z3(nullptr);
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_get_array_sort_range(Z3_context c, Z3_sort t) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_array_sort_range(c, t);
|
||||
|
|
|
@ -164,7 +164,7 @@ extern "C" {
|
|||
return;
|
||||
}
|
||||
recfun_replace replace(m);
|
||||
p.set_definition(replace, pd, true, n, _vars.data(), abs_body);
|
||||
p.set_definition(replace, pd, false, n, _vars.data(), abs_body);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ extern "C" {
|
|||
return mk_c(c)->mk_external_string(buffer.str());
|
||||
}
|
||||
else {
|
||||
return mk_c(c)->mk_external_string(_s.bare_str());
|
||||
return mk_c(c)->mk_external_string(_s.str());
|
||||
}
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
@ -1224,15 +1224,21 @@ extern "C" {
|
|||
case OP_RE_PLUS: return Z3_OP_RE_PLUS;
|
||||
case OP_RE_STAR: return Z3_OP_RE_STAR;
|
||||
case OP_RE_OPTION: return Z3_OP_RE_OPTION;
|
||||
case OP_RE_RANGE: return Z3_OP_RE_RANGE;
|
||||
case OP_RE_CONCAT: return Z3_OP_RE_CONCAT;
|
||||
case OP_RE_UNION: return Z3_OP_RE_UNION;
|
||||
case OP_RE_DIFF: return Z3_OP_RE_DIFF;
|
||||
case OP_RE_POWER: return Z3_OP_RE_POWER;
|
||||
case OP_RE_INTERSECT: return Z3_OP_RE_INTERSECT;
|
||||
case OP_RE_LOOP: return Z3_OP_RE_LOOP;
|
||||
case OP_RE_FULL_SEQ_SET: return Z3_OP_RE_FULL_SET;
|
||||
//case OP_RE_FULL_CHAR_SET: return Z3_OP_RE_FULL_SET;
|
||||
case OP_RE_POWER: return Z3_OP_RE_POWER;
|
||||
case OP_RE_COMPLEMENT: return Z3_OP_RE_COMPLEMENT;
|
||||
case OP_RE_EMPTY_SET: return Z3_OP_RE_EMPTY_SET;
|
||||
|
||||
case OP_RE_FULL_SEQ_SET: return Z3_OP_RE_FULL_SET;
|
||||
case OP_RE_FULL_CHAR_SET: return Z3_OP_RE_FULL_CHAR_SET;
|
||||
case OP_RE_OF_PRED: return Z3_OP_RE_OF_PRED;
|
||||
case OP_RE_REVERSE: return Z3_OP_RE_REVERSE;
|
||||
case OP_RE_DERIVATIVE: return Z3_OP_RE_DERIVATIVE;
|
||||
default:
|
||||
return Z3_OP_INTERNAL;
|
||||
}
|
||||
|
@ -1323,6 +1329,9 @@ extern "C" {
|
|||
}
|
||||
}
|
||||
|
||||
if (mk_c(c)->recfun().get_family_id() == _d->get_family_id())
|
||||
return Z3_OP_RECURSIVE;
|
||||
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
Z3_CATCH_RETURN(Z3_OP_UNINTERPRETED);
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ void Sy(Z3_symbol sym) {
|
|||
*g_z3_log << "# " << s.get_num();
|
||||
}
|
||||
else {
|
||||
*g_z3_log << "$ |" << ll_escaped{s.bare_str()} << '|';
|
||||
*g_z3_log << "$ |" << ll_escaped{s.str().c_str()} << '|';
|
||||
}
|
||||
*g_z3_log << std::endl;
|
||||
}
|
||||
|
|
|
@ -315,6 +315,17 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_re_power(Z3_context c, Z3_ast r, unsigned n) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_re_power(c, r, n);
|
||||
RESET_ERROR_CODE();
|
||||
app* a = mk_c(c)->sutil().re.mk_power(to_expr(r), n);
|
||||
mk_c(c)->save_ast_trail(a);
|
||||
RETURN_Z3(of_ast(a));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
MK_UNARY(Z3_mk_re_plus, mk_c(c)->get_seq_fid(), OP_RE_PLUS, SKIP);
|
||||
MK_UNARY(Z3_mk_re_star, mk_c(c)->get_seq_fid(), OP_RE_STAR, SKIP);
|
||||
MK_UNARY(Z3_mk_re_option, mk_c(c)->get_seq_fid(), OP_RE_OPTION, SKIP);
|
||||
|
|
|
@ -114,7 +114,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
solver2smt2_pp::solver2smt2_pp(ast_manager& m, const std::string& file):
|
||||
m_pp_util(m), m_out(file), m_tracked(m) {
|
||||
m_pp_util(m), m_out(file, std::ofstream::trunc | std::ofstream::out), m_tracked(m) {
|
||||
if (!m_out) {
|
||||
throw default_exception("could not open " + file + " for output");
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ extern "C" {
|
|||
init_solver(c, s);
|
||||
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
|
||||
mk_c(c)->save_object(v);
|
||||
expr_ref_vector trail = to_solver_ref(s)->get_trail();
|
||||
expr_ref_vector trail = to_solver_ref(s)->get_trail(UINT_MAX);
|
||||
for (expr* f : trail) {
|
||||
v->m_ast_vector.push_back(f);
|
||||
}
|
||||
|
@ -883,8 +883,8 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
init_solver(c, s);
|
||||
user_propagator::push_eh_t _push = push_eh;
|
||||
user_propagator::pop_eh_t _pop = pop_eh;
|
||||
user_propagator::push_eh_t _push = (void(*)(void*,user_propagator::callback*)) push_eh;
|
||||
user_propagator::pop_eh_t _pop = (void(*)(void*,user_propagator::callback*,unsigned)) pop_eh;
|
||||
user_propagator::fresh_eh_t _fresh = [=](void * user_ctx, ast_manager& m, user_propagator::context_obj*& _ctx) {
|
||||
ast_context_params params;
|
||||
params.set_foreign_manager(&m);
|
||||
|
@ -902,7 +902,7 @@ extern "C" {
|
|||
Z3_fixed_eh fixed_eh) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
user_propagator::fixed_eh_t _fixed = (void(*)(void*,user_propagator::callback*,unsigned,expr*))fixed_eh;
|
||||
user_propagator::fixed_eh_t _fixed = (void(*)(void*,user_propagator::callback*,expr*,expr*))fixed_eh;
|
||||
to_solver_ref(s)->user_propagate_register_fixed(_fixed);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
@ -924,7 +924,7 @@ extern "C" {
|
|||
Z3_eq_eh eq_eh) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
user_propagator::eq_eh_t _eq = (void(*)(void*,user_propagator::callback*,unsigned,unsigned))eq_eh;
|
||||
user_propagator::eq_eh_t _eq = (void(*)(void*,user_propagator::callback*,expr*,expr*))eq_eh;
|
||||
to_solver_ref(s)->user_propagate_register_eq(_eq);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
@ -935,43 +935,54 @@ extern "C" {
|
|||
Z3_eq_eh diseq_eh) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
user_propagator::eq_eh_t _diseq = (void(*)(void*,user_propagator::callback*,unsigned,unsigned))diseq_eh;
|
||||
user_propagator::eq_eh_t _diseq = (void(*)(void*,user_propagator::callback*,expr*,expr*))diseq_eh;
|
||||
to_solver_ref(s)->user_propagate_register_diseq(_diseq);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e) {
|
||||
void Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_propagate_register(c, s, e);
|
||||
RESET_ERROR_CODE();
|
||||
return to_solver_ref(s)->user_propagate_register_expr(to_expr(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
to_solver_ref(s)->user_propagate_register_expr(to_expr(e));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
unsigned Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback s, Z3_ast e) {
|
||||
void Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback s, Z3_ast e) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_propagate_register_cb(c, s, e);
|
||||
RESET_ERROR_CODE();
|
||||
return reinterpret_cast<user_propagator::callback*>(s)->register_cb(to_expr(e));
|
||||
Z3_CATCH_RETURN(0);
|
||||
reinterpret_cast<user_propagator::callback*>(s)->register_cb(to_expr(e));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback s, unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, unsigned const* eq_lhs, unsigned const* eq_rhs, Z3_ast conseq) {
|
||||
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback s, unsigned num_fixed, Z3_ast const* fixed_ids, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_propagate_consequence(c, s, num_fixed, fixed_ids, num_eqs, eq_lhs, eq_rhs, conseq);
|
||||
RESET_ERROR_CODE();
|
||||
reinterpret_cast<user_propagator::callback*>(s)->propagate_cb(num_fixed, fixed_ids, num_eqs, eq_lhs, eq_rhs, to_expr(conseq));
|
||||
expr* const * _fixed_ids = (expr* const*) fixed_ids;
|
||||
expr* const * _eq_lhs = (expr*const*) eq_lhs;
|
||||
expr* const * _eq_rhs = (expr*const*) eq_rhs;
|
||||
reinterpret_cast<user_propagator::callback*>(s)->propagate_cb(num_fixed, _fixed_ids, num_eqs, _eq_lhs, _eq_rhs, to_expr(conseq));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_propagate_created(Z3_context c, Z3_solver s, Z3_created_eh created_eh) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
user_propagator::created_eh_t c = (void(*)(void*, user_propagator::callback*, expr*, unsigned))created_eh;
|
||||
user_propagator::created_eh_t c = (void(*)(void*, user_propagator::callback*, expr*))created_eh;
|
||||
to_solver_ref(s)->user_propagate_register_created(c);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
void Z3_API Z3_solver_propagate_decide(Z3_context c, Z3_solver s, Z3_decide_eh decide_eh) {
|
||||
Z3_TRY;
|
||||
RESET_ERROR_CODE();
|
||||
user_propagator::decide_eh_t c = (void(*)(void*, user_propagator::callback*, expr**, unsigned*, lbool*))decide_eh;
|
||||
to_solver_ref(s)->user_propagate_register_decide(c);
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
Z3_func_decl Z3_API Z3_solver_propagate_declare(Z3_context c, Z3_symbol name, unsigned n, Z3_sort* domain, Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_propagate_declare(c, name, n, domain, range);
|
||||
|
|
|
@ -331,8 +331,8 @@ extern "C" {
|
|||
if (idx >= mk_c(c)->num_tactics()) {
|
||||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
return "";
|
||||
}
|
||||
return mk_c(c)->get_tactic(idx)->get_name().bare_str();
|
||||
}
|
||||
return mk_c(c)->mk_external_string(mk_c(c)->get_tactic(idx)->get_name().str().c_str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ extern "C" {
|
|||
SET_ERROR_CODE(Z3_IOB, nullptr);
|
||||
return "";
|
||||
}
|
||||
return mk_c(c)->get_probe(idx)->get_name().bare_str();
|
||||
return mk_c(c)->mk_external_string(mk_c(c)->get_probe(idx)->get_name().str().c_str());
|
||||
Z3_CATCH_RETURN("");
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ Notes:
|
|||
#include<string>
|
||||
#include<sstream>
|
||||
#include<memory>
|
||||
#include<vector>
|
||||
#include<z3.h>
|
||||
#include<limits.h>
|
||||
#include<functional>
|
||||
|
@ -155,9 +156,10 @@ namespace z3 {
|
|||
|
||||
class context {
|
||||
private:
|
||||
friend class user_propagator_base;
|
||||
bool m_enable_exceptions;
|
||||
rounding_mode m_rounding_mode;
|
||||
Z3_context m_ctx;
|
||||
Z3_context m_ctx = nullptr;
|
||||
void init(config & c) {
|
||||
set_context(Z3_mk_context_rc(c));
|
||||
}
|
||||
|
@ -173,7 +175,6 @@ namespace z3 {
|
|||
context(context const &) = delete;
|
||||
context & operator=(context const &) = delete;
|
||||
|
||||
friend class scoped_context;
|
||||
context(Z3_context c) { set_context(c); }
|
||||
void detach() { m_ctx = nullptr; }
|
||||
public:
|
||||
|
@ -394,14 +395,6 @@ namespace z3 {
|
|||
expr_vector parse_file(char const* s, sort_vector const& sorts, func_decl_vector const& decls);
|
||||
};
|
||||
|
||||
class scoped_context final {
|
||||
context m_ctx;
|
||||
public:
|
||||
scoped_context(Z3_context c): m_ctx(c) {}
|
||||
~scoped_context() { m_ctx.detach(); }
|
||||
context& operator()() { return m_ctx; }
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class array {
|
||||
|
@ -509,7 +502,7 @@ namespace z3 {
|
|||
ast(context & c):object(c), m_ast(0) {}
|
||||
ast(context & c, Z3_ast n):object(c), m_ast(n) { Z3_inc_ref(ctx(), m_ast); }
|
||||
ast(ast const & s) :object(s), m_ast(s.m_ast) { Z3_inc_ref(ctx(), m_ast); }
|
||||
~ast() { if (m_ast) Z3_dec_ref(*m_ctx, m_ast); }
|
||||
~ast() { if (m_ast) { Z3_dec_ref(*m_ctx, m_ast); } }
|
||||
operator Z3_ast() const { return m_ast; }
|
||||
operator bool() const { return m_ast != 0; }
|
||||
ast & operator=(ast const & s) {
|
||||
|
@ -550,7 +543,7 @@ namespace z3 {
|
|||
~ast_vector_tpl() { Z3_ast_vector_dec_ref(ctx(), m_vector); }
|
||||
operator Z3_ast_vector() const { return m_vector; }
|
||||
unsigned size() const { return Z3_ast_vector_size(ctx(), m_vector); }
|
||||
T operator[](int i) const { assert(0 <= i); Z3_ast r = Z3_ast_vector_get(ctx(), m_vector, i); check_error(); return cast_ast<T>()(ctx(), r); }
|
||||
T operator[](unsigned i) const { Z3_ast r = Z3_ast_vector_get(ctx(), m_vector, i); check_error(); return cast_ast<T>()(ctx(), r); }
|
||||
void push_back(T const & e) { Z3_ast_vector_push(ctx(), m_vector, e); check_error(); }
|
||||
void resize(unsigned sz) { Z3_ast_vector_resize(ctx(), m_vector, sz); check_error(); }
|
||||
T back() const { return operator[](size() - 1); }
|
||||
|
@ -1157,6 +1150,19 @@ namespace z3 {
|
|||
\pre i < num_args()
|
||||
*/
|
||||
expr arg(unsigned i) const { Z3_ast r = Z3_get_app_arg(ctx(), *this, i); check_error(); return expr(ctx(), r); }
|
||||
/**
|
||||
\brief Return a vector of all the arguments of this application.
|
||||
This method assumes the expression is an application.
|
||||
|
||||
\pre is_app()
|
||||
*/
|
||||
expr_vector args() const {
|
||||
expr_vector vec(ctx());
|
||||
unsigned argCnt = num_args();
|
||||
for (unsigned i = 0; i < argCnt; i++)
|
||||
vec.push_back(arg(i));
|
||||
return vec;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Return the 'body' of this quantifier.
|
||||
|
@ -2327,7 +2333,7 @@ namespace z3 {
|
|||
|
||||
inline expr pble(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
context& ctx = es[0u].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_pble(ctx, _es.size(), _es.ptr(), coeffs, bound);
|
||||
ctx.check_error();
|
||||
|
@ -2335,7 +2341,7 @@ namespace z3 {
|
|||
}
|
||||
inline expr pbge(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
context& ctx = es[0u].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_pbge(ctx, _es.size(), _es.ptr(), coeffs, bound);
|
||||
ctx.check_error();
|
||||
|
@ -2343,7 +2349,7 @@ namespace z3 {
|
|||
}
|
||||
inline expr pbeq(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
context& ctx = es[0u].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_pbeq(ctx, _es.size(), _es.ptr(), coeffs, bound);
|
||||
ctx.check_error();
|
||||
|
@ -2351,7 +2357,7 @@ namespace z3 {
|
|||
}
|
||||
inline expr atmost(expr_vector const& es, unsigned bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
context& ctx = es[0u].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_atmost(ctx, _es.size(), _es.ptr(), bound);
|
||||
ctx.check_error();
|
||||
|
@ -2359,7 +2365,7 @@ namespace z3 {
|
|||
}
|
||||
inline expr atleast(expr_vector const& es, unsigned bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
context& ctx = es[0u].ctx();
|
||||
array<Z3_ast> _es(es);
|
||||
Z3_ast r = Z3_mk_atleast(ctx, _es.size(), _es.ptr(), bound);
|
||||
ctx.check_error();
|
||||
|
@ -2367,7 +2373,7 @@ namespace z3 {
|
|||
}
|
||||
inline expr sum(expr_vector const& args) {
|
||||
assert(args.size() > 0);
|
||||
context& ctx = args[0].ctx();
|
||||
context& ctx = args[0u].ctx();
|
||||
array<Z3_ast> _args(args);
|
||||
Z3_ast r = Z3_mk_add(ctx, _args.size(), _args.ptr());
|
||||
ctx.check_error();
|
||||
|
@ -2376,7 +2382,7 @@ namespace z3 {
|
|||
|
||||
inline expr distinct(expr_vector const& args) {
|
||||
assert(args.size() > 0);
|
||||
context& ctx = args[0].ctx();
|
||||
context& ctx = args[0u].ctx();
|
||||
array<Z3_ast> _args(args);
|
||||
Z3_ast r = Z3_mk_distinct(ctx, _args.size(), _args.ptr());
|
||||
ctx.check_error();
|
||||
|
@ -2405,14 +2411,14 @@ namespace z3 {
|
|||
Z3_ast r;
|
||||
assert(args.size() > 0);
|
||||
if (args.size() == 1) {
|
||||
return args[0];
|
||||
return args[0u];
|
||||
}
|
||||
context& ctx = args[0].ctx();
|
||||
context& ctx = args[0u].ctx();
|
||||
array<Z3_ast> _args(args);
|
||||
if (Z3_is_seq_sort(ctx, args[0].get_sort())) {
|
||||
if (Z3_is_seq_sort(ctx, args[0u].get_sort())) {
|
||||
r = Z3_mk_seq_concat(ctx, _args.size(), _args.ptr());
|
||||
}
|
||||
else if (Z3_is_re_sort(ctx, args[0].get_sort())) {
|
||||
else if (Z3_is_re_sort(ctx, args[0u].get_sort())) {
|
||||
r = Z3_mk_re_concat(ctx, _args.size(), _args.ptr());
|
||||
}
|
||||
else {
|
||||
|
@ -2442,7 +2448,7 @@ namespace z3 {
|
|||
inline expr mk_xor(expr_vector const& args) {
|
||||
if (args.empty())
|
||||
return args.ctx().bool_val(false);
|
||||
expr r = args[0];
|
||||
expr r = args[0u];
|
||||
for (unsigned i = 1; i < args.size(); ++i)
|
||||
r = r ^ args[i];
|
||||
return r;
|
||||
|
@ -2581,9 +2587,9 @@ namespace z3 {
|
|||
|
||||
friend std::ostream & operator<<(std::ostream & out, model const & m);
|
||||
|
||||
std::string to_string() const { return std::string(Z3_model_to_string(ctx(), m_model)); }
|
||||
std::string to_string() const { return m_model ? std::string(Z3_model_to_string(ctx(), m_model)) : "null"; }
|
||||
};
|
||||
inline std::ostream & operator<<(std::ostream & out, model const & m) { out << Z3_model_to_string(m.ctx(), m); return out; }
|
||||
inline std::ostream & operator<<(std::ostream & out, model const & m) { return out << m.to_string(); }
|
||||
|
||||
class stats : public object {
|
||||
Z3_stats m_stats;
|
||||
|
@ -2627,7 +2633,8 @@ namespace z3 {
|
|||
Z3_solver m_solver;
|
||||
void init(Z3_solver s) {
|
||||
m_solver = s;
|
||||
Z3_solver_inc_ref(ctx(), s);
|
||||
if (s)
|
||||
Z3_solver_inc_ref(ctx(), s);
|
||||
}
|
||||
public:
|
||||
struct simple {};
|
||||
|
@ -2636,7 +2643,7 @@ namespace z3 {
|
|||
solver(context & c, simple):object(c) { init(Z3_mk_simple_solver(c)); }
|
||||
solver(context & c, Z3_solver s):object(c) { init(s); }
|
||||
solver(context & c, char const * logic):object(c) { init(Z3_mk_solver_for_logic(c, c.str_symbol(logic))); }
|
||||
solver(context & c, solver const& src, translate): object(c) { init(Z3_solver_translate(src.ctx(), src, c)); }
|
||||
solver(context & c, solver const& src, translate): object(c) { Z3_solver s = Z3_solver_translate(src.ctx(), src, c); check_error(); init(s); }
|
||||
solver(solver const & s):object(s) { init(s.m_solver); }
|
||||
~solver() { Z3_solver_dec_ref(ctx(), m_solver); }
|
||||
operator Z3_solver() const { return m_solver; }
|
||||
|
@ -2764,7 +2771,7 @@ namespace z3 {
|
|||
assert(!m_end && !m_empty);
|
||||
m_cube = m_solver.cube(m_vars, m_cutoff);
|
||||
m_cutoff = 0xFFFFFFFF;
|
||||
if (m_cube.size() == 1 && m_cube[0].is_false()) {
|
||||
if (m_cube.size() == 1 && m_cube[0u].is_false()) {
|
||||
m_cube = z3::expr_vector(m_solver.ctx());
|
||||
m_end = true;
|
||||
}
|
||||
|
@ -2998,7 +3005,7 @@ namespace z3 {
|
|||
}
|
||||
array<Z3_tactic> buffer(n);
|
||||
for (unsigned i = 0; i < n; ++i) buffer[i] = tactics[i];
|
||||
return tactic(tactics[0].ctx(), Z3_tactic_par_or(tactics[0].ctx(), n, buffer.ptr()));
|
||||
return tactic(tactics[0u].ctx(), Z3_tactic_par_or(tactics[0u].ctx(), n, buffer.ptr()));
|
||||
}
|
||||
|
||||
inline tactic par_and_then(tactic const & t1, tactic const & t2) {
|
||||
|
@ -3797,7 +3804,7 @@ namespace z3 {
|
|||
}
|
||||
inline expr re_intersect(expr_vector const& args) {
|
||||
assert(args.size() > 0);
|
||||
context& ctx = args[0].ctx();
|
||||
context& ctx = args[0u].ctx();
|
||||
array<Z3_ast> _args(args);
|
||||
Z3_ast r = Z3_mk_re_intersect(ctx, _args.size(), _args.ptr());
|
||||
ctx.check_error();
|
||||
|
@ -3932,56 +3939,65 @@ namespace z3 {
|
|||
|
||||
class user_propagator_base {
|
||||
|
||||
typedef std::function<void(unsigned, expr const&)> fixed_eh_t;
|
||||
typedef std::function<void(expr const&, expr const&)> fixed_eh_t;
|
||||
typedef std::function<void(void)> final_eh_t;
|
||||
typedef std::function<void(unsigned, unsigned)> eq_eh_t;
|
||||
typedef std::function<void(unsigned, expr const&)> created_eh_t;
|
||||
typedef std::function<void(expr const&, expr const&)> eq_eh_t;
|
||||
typedef std::function<void(expr const&)> created_eh_t;
|
||||
typedef std::function<void(expr&, unsigned&, Z3_lbool&)> decide_eh_t;
|
||||
|
||||
final_eh_t m_final_eh;
|
||||
eq_eh_t m_eq_eh;
|
||||
fixed_eh_t m_fixed_eh;
|
||||
created_eh_t m_created_eh;
|
||||
decide_eh_t m_decide_eh;
|
||||
solver* s;
|
||||
Z3_context c;
|
||||
Z3_solver_callback cb { nullptr };
|
||||
context* c;
|
||||
std::vector<z3::context*> subcontexts;
|
||||
|
||||
Z3_context ctx() {
|
||||
return c ? c : (Z3_context)s->ctx();
|
||||
}
|
||||
Z3_solver_callback cb { nullptr };
|
||||
|
||||
struct scoped_cb {
|
||||
user_propagator_base& p;
|
||||
scoped_cb(void* _p, Z3_solver_callback cb):p(*static_cast<user_propagator_base*>(_p)) {
|
||||
p.cb = cb;
|
||||
}
|
||||
~scoped_cb() {
|
||||
p.cb = nullptr;
|
||||
~scoped_cb() {
|
||||
p.cb = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
static void push_eh(void* p) {
|
||||
static void push_eh(void* _p, Z3_solver_callback cb) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
scoped_cb _cb(p, cb);
|
||||
static_cast<user_propagator_base*>(p)->push();
|
||||
}
|
||||
|
||||
static void pop_eh(void* p, unsigned num_scopes) {
|
||||
static_cast<user_propagator_base*>(p)->pop(num_scopes);
|
||||
}
|
||||
|
||||
static void* fresh_eh(void* p, Z3_context ctx) {
|
||||
return static_cast<user_propagator_base*>(p)->fresh(ctx);
|
||||
}
|
||||
|
||||
static void fixed_eh(void* _p, Z3_solver_callback cb, unsigned id, Z3_ast _value) {
|
||||
static void pop_eh(void* _p, Z3_solver_callback cb, unsigned num_scopes) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
scoped_cb _cb(p, cb);
|
||||
scoped_context ctx(p->ctx());
|
||||
expr value(ctx(), _value);
|
||||
static_cast<user_propagator_base*>(p)->m_fixed_eh(id, value);
|
||||
static_cast<user_propagator_base*>(_p)->pop(num_scopes);
|
||||
}
|
||||
|
||||
static void eq_eh(void* p, Z3_solver_callback cb, unsigned x, unsigned y) {
|
||||
static void* fresh_eh(void* _p, Z3_context ctx) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
context* c = new context(ctx);
|
||||
p->subcontexts.push_back(c);
|
||||
return p->fresh(*c);
|
||||
}
|
||||
|
||||
static void fixed_eh(void* _p, Z3_solver_callback cb, Z3_ast _var, Z3_ast _value) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
scoped_cb _cb(p, cb);
|
||||
static_cast<user_propagator_base*>(p)->m_eq_eh(x, y);
|
||||
expr value(p->ctx(), _value);
|
||||
expr var(p->ctx(), _var);
|
||||
p->m_fixed_eh(var, value);
|
||||
}
|
||||
|
||||
static void eq_eh(void* _p, Z3_solver_callback cb, Z3_ast _x, Z3_ast _y) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
scoped_cb _cb(p, cb);
|
||||
expr x(p->ctx(), _x), y(p->ctx(), _y);
|
||||
p->m_eq_eh(x, y);
|
||||
}
|
||||
|
||||
static void final_eh(void* p, Z3_solver_callback cb) {
|
||||
|
@ -3989,69 +4005,89 @@ namespace z3 {
|
|||
static_cast<user_propagator_base*>(p)->m_final_eh();
|
||||
}
|
||||
|
||||
static void created_eh(void* _p, Z3_solver_callback cb, Z3_ast _e, unsigned id) {
|
||||
static void created_eh(void* _p, Z3_solver_callback cb, Z3_ast _e) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
scoped_cb _cb(p, cb);
|
||||
scoped_context ctx(p->ctx());
|
||||
expr e(ctx(), _e);
|
||||
static_cast<user_propagator_base*>(p)->m_created_eh(id, e);
|
||||
expr e(p->ctx(), _e);
|
||||
p->m_created_eh(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void decide_eh(void* _p, Z3_solver_callback cb, Z3_ast* _val, unsigned* bit, Z3_lbool* is_pos) {
|
||||
user_propagator_base* p = static_cast<user_propagator_base*>(_p);
|
||||
scoped_cb _cb(p, cb);
|
||||
expr val(p->ctx(), *_val);
|
||||
p->m_decide_eh(val, *bit, *is_pos);
|
||||
// TBD: life time of val is within the scope of this callback.
|
||||
*_val = val;
|
||||
}
|
||||
|
||||
public:
|
||||
user_propagator_base(Z3_context c) : s(nullptr), c(c) {}
|
||||
user_propagator_base(context& c) : s(nullptr), c(&c) {}
|
||||
|
||||
user_propagator_base(solver* s): s(s), c(nullptr) {
|
||||
Z3_solver_propagate_init(ctx(), *s, this, push_eh, pop_eh, fresh_eh);
|
||||
Z3_solver_propagate_init(ctx(), *s, this, push_eh, pop_eh, fresh_eh);
|
||||
}
|
||||
|
||||
virtual void push() = 0;
|
||||
virtual void pop(unsigned num_scopes) = 0;
|
||||
|
||||
virtual ~user_propagator_base() = default;
|
||||
virtual ~user_propagator_base() {
|
||||
for (auto& subcontext : subcontexts) {
|
||||
subcontext->detach(); // detach first; the subcontexts will be freed internally!
|
||||
delete subcontext;
|
||||
}
|
||||
}
|
||||
|
||||
context& ctx() {
|
||||
return c ? *c : s->ctx();
|
||||
}
|
||||
|
||||
/**
|
||||
\brief user_propagators created using \c fresh() are created during
|
||||
\brief user_propagators created using \c fresh() are created during
|
||||
search and their lifetimes are restricted to search time. They should
|
||||
be garbage collected by the propagator used to invoke \c fresh().
|
||||
The life-time of the Z3_context object can only be assumed valid during
|
||||
callbacks, such as \c fixed(), which contains expressions based on the
|
||||
context.
|
||||
*/
|
||||
virtual user_propagator_base* fresh(Z3_context ctx) = 0;
|
||||
virtual user_propagator_base* fresh(context& ctx) = 0;
|
||||
|
||||
/**
|
||||
\brief register callbacks.
|
||||
Callbacks can only be registered with user_propagators
|
||||
that were created using a solver.
|
||||
that were created using a solver.
|
||||
*/
|
||||
|
||||
void register_fixed(fixed_eh_t& f) {
|
||||
assert(s);
|
||||
m_fixed_eh = f;
|
||||
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
|
||||
void register_fixed(fixed_eh_t& f) {
|
||||
m_fixed_eh = f;
|
||||
if (s) {
|
||||
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_fixed() {
|
||||
assert(s);
|
||||
m_fixed_eh = [this](unsigned id, expr const& e) {
|
||||
m_fixed_eh = [this](expr const &id, expr const &e) {
|
||||
fixed(id, e);
|
||||
};
|
||||
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
|
||||
if (s) {
|
||||
Z3_solver_propagate_fixed(ctx(), *s, fixed_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_eq(eq_eh_t& f) {
|
||||
assert(s);
|
||||
m_eq_eh = f;
|
||||
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
|
||||
void register_eq(eq_eh_t& f) {
|
||||
m_eq_eh = f;
|
||||
if (s) {
|
||||
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_eq() {
|
||||
assert(s);
|
||||
m_eq_eh = [this](unsigned x, unsigned y) {
|
||||
m_eq_eh = [this](expr const& x, expr const& y) {
|
||||
eq(x, y);
|
||||
};
|
||||
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
|
||||
if (s) {
|
||||
Z3_solver_propagate_eq(ctx(), *s, eq_eh);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4059,51 +4095,74 @@ namespace z3 {
|
|||
During the final check stage, all propagations have been processed.
|
||||
This is an opportunity for the user-propagator to delay some analysis
|
||||
that could be expensive to perform incrementally. It is also an opportunity
|
||||
for the propagator to implement branch and bound optimization.
|
||||
for the propagator to implement branch and bound optimization.
|
||||
*/
|
||||
|
||||
void register_final(final_eh_t& f) {
|
||||
assert(s);
|
||||
m_final_eh = f;
|
||||
Z3_solver_propagate_final(ctx(), *s, final_eh);
|
||||
void register_final(final_eh_t& f) {
|
||||
m_final_eh = f;
|
||||
if (s) {
|
||||
Z3_solver_propagate_final(ctx(), *s, final_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_final() {
|
||||
assert(s);
|
||||
|
||||
void register_final() {
|
||||
m_final_eh = [this]() {
|
||||
final();
|
||||
};
|
||||
Z3_solver_propagate_final(ctx(), *s, final_eh);
|
||||
if (s) {
|
||||
Z3_solver_propagate_final(ctx(), *s, final_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_created(created_eh_t& c) {
|
||||
assert(s);
|
||||
m_created_eh = c;
|
||||
Z3_solver_propagate_created(ctx(), *s, created_eh);
|
||||
if (s) {
|
||||
Z3_solver_propagate_created(ctx(), *s, created_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_created() {
|
||||
m_created_eh = [this](unsigned id, expr const& e) {
|
||||
created(id, e);
|
||||
m_created_eh = [this](expr const& e) {
|
||||
created(e);
|
||||
};
|
||||
Z3_solver_propagate_created(ctx(), *s, created_eh);
|
||||
if (s) {
|
||||
Z3_solver_propagate_created(ctx(), *s, created_eh);
|
||||
}
|
||||
}
|
||||
|
||||
void register_decide(decide_eh_t& c) {
|
||||
m_decide_eh = c;
|
||||
if (s) {
|
||||
Z3_solver_propagate_decide(ctx(), *s, decide_eh);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void fixed(unsigned /*id*/, expr const& /*e*/) { }
|
||||
void register_decide() {
|
||||
m_decide_eh = [this](expr& val, unsigned& bit, Z3_lbool& is_pos) {
|
||||
decide(val, bit, is_pos);
|
||||
};
|
||||
if (s) {
|
||||
Z3_solver_propagate_decide(ctx(), *s, decide_eh);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void eq(unsigned /*x*/, unsigned /*y*/) { }
|
||||
virtual void fixed(expr const& /*id*/, expr const& /*e*/) { }
|
||||
|
||||
virtual void eq(expr const& /*x*/, expr const& /*y*/) { }
|
||||
|
||||
virtual void final() { }
|
||||
|
||||
virtual void created(unsigned /*id*/, expr const& /*e*/) {}
|
||||
virtual void created(expr const& /*e*/) {}
|
||||
|
||||
virtual void decide(expr& /*val*/, unsigned& /*bit*/, Z3_lbool& /*is_pos*/) {}
|
||||
|
||||
/**
|
||||
\brief tracks \c e by a unique identifier that is returned by the call.
|
||||
|
||||
If the \c fixed() callback is registered and if \c e is a Boolean or Bit-vector,
|
||||
If the \c fixed() callback is registered and if \c e is a Boolean or Bit-vector,
|
||||
the \c fixed() callback gets invoked when \c e is bound to a value.
|
||||
If the \c eq() callback is registered, then equalities between registered expressions
|
||||
are reported.
|
||||
are reported.
|
||||
A consumer can use the \c propagate or \c conflict functions to invoke propagations
|
||||
or conflicts as a consequence of these callbacks. These functions take a list of identifiers
|
||||
for registered expressions that have been fixed. The list of identifiers must correspond to
|
||||
|
@ -4111,40 +4170,43 @@ namespace z3 {
|
|||
correspond to equalities that have been registered during a callback.
|
||||
*/
|
||||
|
||||
unsigned add(expr const& e) {
|
||||
void add(expr const& e) {
|
||||
if (cb)
|
||||
return Z3_solver_propagate_register_cb(ctx(), cb, e);
|
||||
if (s)
|
||||
return Z3_solver_propagate_register(ctx(), *s, e);
|
||||
assert(false);
|
||||
return 0;
|
||||
Z3_solver_propagate_register_cb(ctx(), cb, e);
|
||||
else if (s)
|
||||
Z3_solver_propagate_register(ctx(), *s, e);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void conflict(unsigned num_fixed, unsigned const* fixed) {
|
||||
void conflict(expr_vector const& fixed) {
|
||||
assert(cb);
|
||||
scoped_context _ctx(ctx());
|
||||
expr conseq = _ctx().bool_val(false);
|
||||
Z3_solver_propagate_consequence(ctx(), cb, num_fixed, fixed, 0, nullptr, nullptr, conseq);
|
||||
expr conseq = ctx().bool_val(false);
|
||||
array<Z3_ast> _fixed(fixed);
|
||||
Z3_solver_propagate_consequence(ctx(), cb, fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
|
||||
}
|
||||
|
||||
void propagate(unsigned num_fixed, unsigned const* fixed, expr const& conseq) {
|
||||
void propagate(expr_vector const& fixed, expr const& conseq) {
|
||||
assert(cb);
|
||||
assert(conseq.ctx() == ctx());
|
||||
Z3_solver_propagate_consequence(ctx(), cb, num_fixed, fixed, 0, nullptr, nullptr, conseq);
|
||||
assert((Z3_context)conseq.ctx() == (Z3_context)ctx());
|
||||
array<Z3_ast> _fixed(fixed);
|
||||
Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), 0, nullptr, nullptr, conseq);
|
||||
}
|
||||
|
||||
void propagate(unsigned num_fixed, unsigned const* fixed,
|
||||
unsigned num_eqs, unsigned const* lhs, unsigned const * rhs,
|
||||
void propagate(expr_vector const& fixed,
|
||||
expr_vector const& lhs, expr_vector const& rhs,
|
||||
expr const& conseq) {
|
||||
assert(cb);
|
||||
assert(conseq.ctx() == ctx());
|
||||
Z3_solver_propagate_consequence(ctx(), cb, num_fixed, fixed, num_eqs, lhs, rhs, conseq);
|
||||
assert((Z3_context)conseq.ctx() == (Z3_context)ctx());
|
||||
assert(lhs.size() == rhs.size());
|
||||
array<Z3_ast> _fixed(fixed);
|
||||
array<Z3_ast> _lhs(lhs);
|
||||
array<Z3_ast> _rhs(rhs);
|
||||
|
||||
Z3_solver_propagate_consequence(ctx(), cb, _fixed.size(), _fixed.ptr(), lhs.size(), _lhs.ptr(), _rhs.ptr(), conseq);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace Microsoft.Z3
|
|||
{
|
||||
get
|
||||
{
|
||||
ASTVector res = new ASTVector(Context, Native.Z3_ast_map_keys(Context.nCtx, NativeObject));
|
||||
using ASTVector res = new ASTVector(Context, Native.Z3_ast_map_keys(Context.nCtx, NativeObject));
|
||||
return res.ToArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -41,24 +40,48 @@ namespace Microsoft.Z3
|
|||
|
||||
#region Operators
|
||||
|
||||
private static ArithExpr MkNum(ArithExpr e, int i) { return (ArithExpr)e.Context.MkNumeral(i, e.Context.MkIntSort()); }
|
||||
private static ArithExpr MkNum(ArithExpr e, int i)
|
||||
{
|
||||
using var sort = e.Context.MkIntSort();
|
||||
return (ArithExpr)e.Context.MkNumeral(i, sort);
|
||||
}
|
||||
|
||||
private static ArithExpr MkNum(ArithExpr e, double d) { return (ArithExpr)e.Context.MkNumeral(d.ToString(), e.Context.MkRealSort()); }
|
||||
private static ArithExpr MkNum(ArithExpr e, double d)
|
||||
{
|
||||
using var sort = e.Context.MkRealSort();
|
||||
return (ArithExpr)e.Context.MkNumeral(d.ToString(), sort);
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical division operator (over reals) </summary>
|
||||
public static ArithExpr operator /(ArithExpr a, ArithExpr b) { return a.Context.MkDiv(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator /(ArithExpr a, int b) { return a / MkNum(a, b); }
|
||||
public static ArithExpr operator /(ArithExpr a, int b)
|
||||
{
|
||||
using var denominator = MkNum(a, b);
|
||||
return a / denominator;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator /(ArithExpr a, double b) { return a / MkNum(a, b); }
|
||||
public static ArithExpr operator /(ArithExpr a, double b)
|
||||
{
|
||||
using var denominator = MkNum(a, b);
|
||||
return a / denominator;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator /(int a, ArithExpr b) { return MkNum(b, a) / b; }
|
||||
public static ArithExpr operator /(int a, ArithExpr b)
|
||||
{
|
||||
using var numerator = MkNum(b, a);
|
||||
return numerator / b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator /(double a, ArithExpr b) { return MkNum(b, a) / b; }
|
||||
public static ArithExpr operator /(double a, ArithExpr b)
|
||||
{
|
||||
using var numerator = MkNum(b, a);
|
||||
return numerator / b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator -(ArithExpr a) { return a.Context.MkUnaryMinus(a); }
|
||||
|
@ -67,106 +90,218 @@ namespace Microsoft.Z3
|
|||
public static ArithExpr operator -(ArithExpr a, ArithExpr b) { return a.Context.MkSub(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator -(ArithExpr a, int b) { return a - MkNum(a, b); }
|
||||
public static ArithExpr operator -(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a - rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator -(ArithExpr a, double b) { return a - MkNum(a, b); }
|
||||
public static ArithExpr operator -(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a - rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator -(int a, ArithExpr b) { return MkNum(b, a) - b; }
|
||||
public static ArithExpr operator -(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs - b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator -(double a, ArithExpr b) { return MkNum(b, a) - b; }
|
||||
public static ArithExpr operator -(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs - b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator +(ArithExpr a, ArithExpr b) { return a.Context.MkAdd(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator +(ArithExpr a, int b) { return a + MkNum(a, b); }
|
||||
public static ArithExpr operator +(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a + rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator +(ArithExpr a, double b) { return a + MkNum(a, b); }
|
||||
public static ArithExpr operator +(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a + rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator +(int a, ArithExpr b) { return MkNum(b, a) + b; }
|
||||
public static ArithExpr operator +(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs + b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator +(double a, ArithExpr b) { return MkNum(b, a) + b; }
|
||||
public static ArithExpr operator +(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs + b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator *(ArithExpr a, ArithExpr b) { return a.Context.MkMul(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator *(ArithExpr a, int b) { return a * MkNum(a, b); }
|
||||
public static ArithExpr operator *(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a * rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator *(ArithExpr a, double b) { return a * MkNum(a, b); }
|
||||
public static ArithExpr operator *(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a * rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator *(int a, ArithExpr b) { return MkNum(b, a) * b; }
|
||||
public static ArithExpr operator *(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs * b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static ArithExpr operator *(double a, ArithExpr b) { return MkNum(b, a) * b; }
|
||||
public static ArithExpr operator *(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs * b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <=(ArithExpr a, ArithExpr b) { return a.Context.MkLe(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <=(ArithExpr a, int b) { return a <= MkNum(a, b); }
|
||||
public static BoolExpr operator <=(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a <= rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <=(ArithExpr a, double b) { return a <= MkNum(a, b); }
|
||||
public static BoolExpr operator <=(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a <= rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <=(int a, ArithExpr b) { return MkNum(b, a) <= b; }
|
||||
public static BoolExpr operator <=(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs <= b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <=(double a, ArithExpr b) { return MkNum(b, a) <= b; }
|
||||
public static BoolExpr operator <=(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs <= b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <(ArithExpr a, ArithExpr b) { return a.Context.MkLt(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <(ArithExpr a, int b) { return a < MkNum(a, b); }
|
||||
public static BoolExpr operator <(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a < rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <(ArithExpr a, double b) { return a < MkNum(a, b); }
|
||||
public static BoolExpr operator <(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a < rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <(int a, ArithExpr b) { return MkNum(b, a) < b; }
|
||||
public static BoolExpr operator <(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs < b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator <(double a, ArithExpr b) { return MkNum(b, a) < b; }
|
||||
public static BoolExpr operator <(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs < b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >(ArithExpr a, ArithExpr b) { return a.Context.MkGt(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >(ArithExpr a, int b) { return a > MkNum(a, b); }
|
||||
public static BoolExpr operator >(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a > rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >(ArithExpr a, double b) { return a > MkNum(a, b); }
|
||||
public static BoolExpr operator >(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a > rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >(int a, ArithExpr b) { return MkNum(b, a) > b; }
|
||||
public static BoolExpr operator >(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs > b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >(double a, ArithExpr b) { return MkNum(b, a) > b; }
|
||||
public static BoolExpr operator >(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs > b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >=(ArithExpr a, ArithExpr b) { return a.Context.MkGe(a, b); }
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >=(ArithExpr a, int b) { return a >= MkNum(a, b); }
|
||||
public static BoolExpr operator >=(ArithExpr a, int b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a >= rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >=(ArithExpr a, double b) { return a >= MkNum(a, b); }
|
||||
public static BoolExpr operator >=(ArithExpr a, double b)
|
||||
{
|
||||
using var rhs = MkNum(a, b);
|
||||
return a >= rhs;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >=(int a, ArithExpr b) { return MkNum(b, a) >= b; }
|
||||
public static BoolExpr operator >=(int a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs >= b;
|
||||
}
|
||||
|
||||
/// <summary> Operator overloading for arithmetical operator </summary>
|
||||
public static BoolExpr operator >=(double a, ArithExpr b) { return MkNum(b, a) >= b; }
|
||||
public static BoolExpr operator >=(double a, ArithExpr b)
|
||||
{
|
||||
using var lhs = MkNum(b, a);
|
||||
return lhs >= b;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -85,6 +85,10 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
|||
ListSort.cs
|
||||
Log.cs
|
||||
Model.cs
|
||||
NativeContext.cs
|
||||
NativeFuncInterp.cs
|
||||
NativeModel.cs
|
||||
NativeSolver.cs
|
||||
Optimize.cs
|
||||
ParamDescrs.cs
|
||||
Params.cs
|
||||
|
|
|
@ -18,10 +18,10 @@ Notes:
|
|||
--*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
|
@ -202,8 +202,8 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public UninterpretedSort MkUninterpretedSort(string str)
|
||||
{
|
||||
|
||||
return MkUninterpretedSort(MkSymbol(str));
|
||||
using var sym = MkSymbol(str);
|
||||
return MkUninterpretedSort(sym);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -231,7 +231,6 @@ namespace Microsoft.Z3
|
|||
return new BitVecSort(this, Native.Z3_mk_bv_sort(nCtx, size));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new sequence sort.
|
||||
/// </summary>
|
||||
|
@ -314,7 +313,17 @@ namespace Microsoft.Z3
|
|||
{
|
||||
Debug.Assert(enumNames != null);
|
||||
|
||||
return new EnumSort(this, MkSymbol(name), MkSymbols(enumNames));
|
||||
var enumSymbols = MkSymbols(enumNames);
|
||||
try
|
||||
{
|
||||
using var symbol = MkSymbol(name);
|
||||
return new EnumSort(this, symbol, enumSymbols);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var enumSymbol in enumSymbols)
|
||||
enumSymbol.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -338,7 +347,8 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(elemSort != null);
|
||||
|
||||
CheckContextMatch(elemSort);
|
||||
return new ListSort(this, MkSymbol(name), elemSort);
|
||||
using var symbol = MkSymbol(name);
|
||||
return new ListSort(this, symbol, elemSort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -365,8 +375,8 @@ namespace Microsoft.Z3
|
|||
/// <param name="size">The size of the sort</param>
|
||||
public FiniteDomainSort MkFiniteDomainSort(string name, ulong size)
|
||||
{
|
||||
|
||||
return new FiniteDomainSort(this, MkSymbol(name), size);
|
||||
using var symbol = MkSymbol(name);
|
||||
return new FiniteDomainSort(this, symbol, size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,7 +411,18 @@ namespace Microsoft.Z3
|
|||
public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null)
|
||||
{
|
||||
|
||||
return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs);
|
||||
using var nameSymbol = MkSymbol(name);
|
||||
using var recognizerSymbol = MkSymbol(recognizer);
|
||||
var fieldSymbols = MkSymbols(fieldNames);
|
||||
try
|
||||
{
|
||||
return new Constructor(this, nameSymbol, recognizerSymbol, fieldSymbols, sorts, sortRefs);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var fieldSymbol in fieldSymbols)
|
||||
fieldSymbol.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -428,7 +449,8 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(constructors.All(c => c != null));
|
||||
|
||||
CheckContextMatch<Constructor>(constructors);
|
||||
return new DatatypeSort(this, MkSymbol(name), constructors);
|
||||
using var symbol = MkSymbol(name);
|
||||
return new DatatypeSort(this, symbol, constructors);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -477,7 +499,16 @@ namespace Microsoft.Z3
|
|||
//Debug.Assert(Contract.ForAll(0, c.Length, j => c[j] != null));
|
||||
//Debug.Assert(names.All(name => name != null));
|
||||
|
||||
return MkDatatypeSorts(MkSymbols(names), c);
|
||||
var symbols = MkSymbols(names);
|
||||
try
|
||||
{
|
||||
return MkDatatypeSorts(symbols, c);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (var symbol in symbols)
|
||||
symbol.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -485,7 +516,7 @@ namespace Microsoft.Z3
|
|||
/// The function performs a record update at t. The field
|
||||
/// that is passed in as argument is updated with value v,
|
||||
/// the remaining fields of t are unchanged.
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
public Expr MkUpdateField(FuncDecl field, Expr t, Expr v)
|
||||
{
|
||||
return Expr.Create(this, Native.Z3_datatype_update_field(
|
||||
|
@ -538,7 +569,8 @@ namespace Microsoft.Z3
|
|||
|
||||
CheckContextMatch<Sort>(domain);
|
||||
CheckContextMatch(range);
|
||||
return new FuncDecl(this, MkSymbol(name), domain, range);
|
||||
using var symbol = MkSymbol(name);
|
||||
return new FuncDecl(this, symbol, domain, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -551,7 +583,8 @@ namespace Microsoft.Z3
|
|||
|
||||
CheckContextMatch<Sort>(domain);
|
||||
CheckContextMatch(range);
|
||||
return new FuncDecl(this, MkSymbol(name), domain, range, true);
|
||||
using var symbol = MkSymbol(name);
|
||||
return new FuncDecl(this, symbol, domain, range, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -560,14 +593,14 @@ namespace Microsoft.Z3
|
|||
/// MkRecFuncDecl. The body may contain recursive uses of the function or
|
||||
/// other mutually recursive functions.
|
||||
/// </summary>
|
||||
public void AddRecDef(FuncDecl f, Expr[] args, Expr body)
|
||||
{
|
||||
CheckContextMatch(f);
|
||||
CheckContextMatch<Expr>(args);
|
||||
CheckContextMatch(body);
|
||||
public void AddRecDef(FuncDecl f, Expr[] args, Expr body)
|
||||
{
|
||||
CheckContextMatch(f);
|
||||
CheckContextMatch<Expr>(args);
|
||||
CheckContextMatch(body);
|
||||
IntPtr[] argsNative = AST.ArrayToNative(args);
|
||||
Native.Z3_add_rec_def(nCtx, f.NativeObject, (uint)args.Length, argsNative, body.NativeObject);
|
||||
}
|
||||
Native.Z3_add_rec_def(nCtx, f.NativeObject, (uint)args.Length, argsNative, body.NativeObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new function declaration.
|
||||
|
@ -579,8 +612,9 @@ namespace Microsoft.Z3
|
|||
|
||||
CheckContextMatch(domain);
|
||||
CheckContextMatch(range);
|
||||
using var symbol = MkSymbol(name);
|
||||
Sort[] q = new Sort[] { domain };
|
||||
return new FuncDecl(this, MkSymbol(name), q, range);
|
||||
return new FuncDecl(this, symbol, q, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -619,7 +653,8 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(range != null);
|
||||
|
||||
CheckContextMatch(range);
|
||||
return new FuncDecl(this, MkSymbol(name), null, range);
|
||||
using var symbol = MkSymbol(name);
|
||||
return new FuncDecl(this, symbol, null, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -687,7 +722,8 @@ namespace Microsoft.Z3
|
|||
{
|
||||
Debug.Assert(range != null);
|
||||
|
||||
return MkConst(MkSymbol(name), range);
|
||||
using var symbol = MkSymbol(name);
|
||||
return MkConst(symbol, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -728,8 +764,8 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public BoolExpr MkBoolConst(string name)
|
||||
{
|
||||
|
||||
return (BoolExpr)MkConst(MkSymbol(name), BoolSort);
|
||||
using var symbol = MkSymbol(name);
|
||||
return (BoolExpr)MkConst(symbol, BoolSort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -778,7 +814,8 @@ namespace Microsoft.Z3
|
|||
{
|
||||
Debug.Assert(name != null);
|
||||
|
||||
return (BitVecExpr)MkConst(name, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecExpr)MkConst(name, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -786,8 +823,8 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public BitVecExpr MkBVConst(string name, uint size)
|
||||
{
|
||||
|
||||
return (BitVecExpr)MkConst(name, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecExpr)MkConst(name, sort);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -811,7 +848,7 @@ namespace Microsoft.Z3
|
|||
public Expr MkApp(FuncDecl f, IEnumerable<Expr> args)
|
||||
{
|
||||
Debug.Assert(f != null);
|
||||
Debug.Assert(args == null || args.All( a => a != null));
|
||||
Debug.Assert(args == null || args.All(a => a != null));
|
||||
|
||||
CheckContextMatch(f);
|
||||
CheckContextMatch(args);
|
||||
|
@ -948,16 +985,12 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(ts != null);
|
||||
Debug.Assert(ts.All(a => a != null));
|
||||
CheckContextMatch<BoolExpr>(ts);
|
||||
BoolExpr r = null;
|
||||
foreach (var t in ts) {
|
||||
if (r == null)
|
||||
r = t;
|
||||
else
|
||||
r = MkXor(r, t);
|
||||
}
|
||||
if (r == null)
|
||||
r = MkTrue();
|
||||
return r;
|
||||
|
||||
return ts.Aggregate(MkFalse(), (r, t) =>
|
||||
{
|
||||
using (r)
|
||||
return MkXor(r, t);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2032,7 +2065,8 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(domain != null);
|
||||
Debug.Assert(range != null);
|
||||
|
||||
return (ArrayExpr)MkConst(name, MkArraySort(domain, range));
|
||||
using var sort = MkArraySort(domain, range);
|
||||
return (ArrayExpr)MkConst(name, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2043,7 +2077,9 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(domain != null);
|
||||
Debug.Assert(range != null);
|
||||
|
||||
return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range));
|
||||
using var symbol = MkSymbol(name);
|
||||
using var sort = MkArraySort(domain, range);
|
||||
return (ArrayExpr)MkConst(symbol, sort);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2343,7 +2379,7 @@ namespace Microsoft.Z3
|
|||
|
||||
CheckContextMatch(elem);
|
||||
CheckContextMatch(set);
|
||||
return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_member(nCtx, elem.NativeObject, set.NativeObject));
|
||||
return (BoolExpr)Expr.Create(this, Native.Z3_mk_set_member(nCtx, elem.NativeObject, set.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2356,7 +2392,7 @@ namespace Microsoft.Z3
|
|||
|
||||
CheckContextMatch(arg1);
|
||||
CheckContextMatch(arg2);
|
||||
return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_subset(nCtx, arg1.NativeObject, arg2.NativeObject));
|
||||
return (BoolExpr)Expr.Create(this, Native.Z3_mk_set_subset(nCtx, arg1.NativeObject, arg2.NativeObject));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -2366,7 +2402,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create the empty sequence.
|
||||
/// </summary>
|
||||
public SeqExpr MkEmptySeq(Sort s)
|
||||
public SeqExpr MkEmptySeq(Sort s)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
return new SeqExpr(this, Native.Z3_mk_seq_empty(nCtx, s.NativeObject));
|
||||
|
@ -2375,7 +2411,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create the singleton sequence.
|
||||
/// </summary>
|
||||
public SeqExpr MkUnit(Expr elem)
|
||||
public SeqExpr MkUnit(Expr elem)
|
||||
{
|
||||
Debug.Assert(elem != null);
|
||||
return new SeqExpr(this, Native.Z3_mk_seq_unit(nCtx, elem.NativeObject));
|
||||
|
@ -2384,7 +2420,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a string constant.
|
||||
/// </summary>
|
||||
public SeqExpr MkString(string s)
|
||||
public SeqExpr MkString(string s)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
return new SeqExpr(this, Native.Z3_mk_string(nCtx, s));
|
||||
|
@ -2393,7 +2429,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Convert an integer expression to a string.
|
||||
/// </summary>
|
||||
public SeqExpr IntToString(Expr e)
|
||||
public SeqExpr IntToString(Expr e)
|
||||
{
|
||||
Debug.Assert(e != null);
|
||||
Debug.Assert(e is ArithExpr);
|
||||
|
@ -2413,7 +2449,8 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Convert a bit-vector expression, represented as an signed number, to a string.
|
||||
/// </summary>
|
||||
public SeqExpr SbvToString(Expr e) {
|
||||
public SeqExpr SbvToString(Expr e)
|
||||
{
|
||||
Debug.Assert(e != null);
|
||||
Debug.Assert(e is ArithExpr);
|
||||
return new SeqExpr(this, Native.Z3_mk_sbv_to_str(nCtx, e.NativeObject));
|
||||
|
@ -2422,7 +2459,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Convert an integer expression to a string.
|
||||
/// </summary>
|
||||
public IntExpr StringToInt(Expr e)
|
||||
public IntExpr StringToInt(Expr e)
|
||||
{
|
||||
Debug.Assert(e != null);
|
||||
Debug.Assert(e is SeqExpr);
|
||||
|
@ -2449,13 +2486,13 @@ namespace Microsoft.Z3
|
|||
public IntExpr MkLength(SeqExpr s)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
return (IntExpr) Expr.Create(this, Native.Z3_mk_seq_length(nCtx, s.NativeObject));
|
||||
return (IntExpr)Expr.Create(this, Native.Z3_mk_seq_length(nCtx, s.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for sequence prefix.
|
||||
/// </summary>
|
||||
public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
Debug.Assert(s1 != null);
|
||||
Debug.Assert(s2 != null);
|
||||
|
@ -2466,7 +2503,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Check for sequence suffix.
|
||||
/// </summary>
|
||||
public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
Debug.Assert(s1 != null);
|
||||
Debug.Assert(s2 != null);
|
||||
|
@ -2477,7 +2514,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Check for sequence containment of s2 in s1.
|
||||
/// </summary>
|
||||
public BoolExpr MkContains(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr MkContains(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
Debug.Assert(s1 != null);
|
||||
Debug.Assert(s2 != null);
|
||||
|
@ -2488,7 +2525,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Check if the string s1 is lexicographically strictly less than s2.
|
||||
/// </summary>
|
||||
public BoolExpr MkStringLt(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr MkStringLt(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
Debug.Assert(s1 != null);
|
||||
Debug.Assert(s2 != null);
|
||||
|
@ -2497,9 +2534,9 @@ namespace Microsoft.Z3
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the string s1 is lexicographically strictly less than s2.
|
||||
/// Check if the string s1 is lexicographically less or equal to s2.
|
||||
/// </summary>
|
||||
public BoolExpr MkStringLe(SeqExpr s1, SeqExpr s2)
|
||||
public BoolExpr MkStringLe(SeqExpr s1, SeqExpr s2)
|
||||
{
|
||||
Debug.Assert(s1 != null);
|
||||
Debug.Assert(s2 != null);
|
||||
|
@ -2568,10 +2605,10 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Convert a regular expression that accepts sequence s.
|
||||
/// </summary>
|
||||
public ReExpr MkToRe(SeqExpr s)
|
||||
public ReExpr MkToRe(SeqExpr s)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
return new ReExpr(this, Native.Z3_mk_seq_to_re(nCtx, s.NativeObject));
|
||||
return new ReExpr(this, Native.Z3_mk_seq_to_re(nCtx, s.NativeObject));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2583,7 +2620,7 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(s != null);
|
||||
Debug.Assert(re != null);
|
||||
CheckContextMatch(s, re);
|
||||
return new BoolExpr(this, Native.Z3_mk_seq_in_re(nCtx, s.NativeObject, re.NativeObject));
|
||||
return new BoolExpr(this, Native.Z3_mk_seq_in_re(nCtx, s.NativeObject, re.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2592,7 +2629,7 @@ namespace Microsoft.Z3
|
|||
public ReExpr MkStar(ReExpr re)
|
||||
{
|
||||
Debug.Assert(re != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_star(nCtx, re.NativeObject));
|
||||
return new ReExpr(this, Native.Z3_mk_re_star(nCtx, re.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2601,7 +2638,7 @@ namespace Microsoft.Z3
|
|||
public ReExpr MkLoop(ReExpr re, uint lo, uint hi = 0)
|
||||
{
|
||||
Debug.Assert(re != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_loop(nCtx, re.NativeObject, lo, hi));
|
||||
return new ReExpr(this, Native.Z3_mk_re_loop(nCtx, re.NativeObject, lo, hi));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2610,7 +2647,7 @@ namespace Microsoft.Z3
|
|||
public ReExpr MkPlus(ReExpr re)
|
||||
{
|
||||
Debug.Assert(re != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_plus(nCtx, re.NativeObject));
|
||||
return new ReExpr(this, Native.Z3_mk_re_plus(nCtx, re.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2619,7 +2656,7 @@ namespace Microsoft.Z3
|
|||
public ReExpr MkOption(ReExpr re)
|
||||
{
|
||||
Debug.Assert(re != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_option(nCtx, re.NativeObject));
|
||||
return new ReExpr(this, Native.Z3_mk_re_option(nCtx, re.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2628,7 +2665,7 @@ namespace Microsoft.Z3
|
|||
public ReExpr MkComplement(ReExpr re)
|
||||
{
|
||||
Debug.Assert(re != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_complement(nCtx, re.NativeObject));
|
||||
return new ReExpr(this, Native.Z3_mk_re_complement(nCtx, re.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2670,7 +2707,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a difference regular expression.
|
||||
/// </summary>
|
||||
public ReExpr MkDiff(ReExpr a, ReExpr b)
|
||||
public ReExpr MkDiff(ReExpr a, ReExpr b)
|
||||
{
|
||||
Debug.Assert(a != null);
|
||||
Debug.Assert(b != null);
|
||||
|
@ -2682,7 +2719,7 @@ namespace Microsoft.Z3
|
|||
/// Create the empty regular expression.
|
||||
/// The sort s should be a regular expression.
|
||||
/// </summary>
|
||||
public ReExpr MkEmptyRe(Sort s)
|
||||
public ReExpr MkEmptyRe(Sort s)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_empty(nCtx, s.NativeObject));
|
||||
|
@ -2692,7 +2729,7 @@ namespace Microsoft.Z3
|
|||
/// Create the full regular expression.
|
||||
/// The sort s should be a regular expression.
|
||||
/// </summary>
|
||||
public ReExpr MkFullRe(Sort s)
|
||||
public ReExpr MkFullRe(Sort s)
|
||||
{
|
||||
Debug.Assert(s != null);
|
||||
return new ReExpr(this, Native.Z3_mk_re_full(nCtx, s.NativeObject));
|
||||
|
@ -2702,7 +2739,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a range expression.
|
||||
/// </summary>
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
{
|
||||
Debug.Assert(lo != null);
|
||||
Debug.Assert(hi != null);
|
||||
|
@ -2713,7 +2750,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create less than or equal to between two characters.
|
||||
/// </summary>
|
||||
public BoolExpr MkCharLe(Expr ch1, Expr ch2)
|
||||
public BoolExpr MkCharLe(Expr ch1, Expr ch2)
|
||||
{
|
||||
Debug.Assert(ch1 != null);
|
||||
Debug.Assert(ch2 != null);
|
||||
|
@ -2723,7 +2760,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create an integer (code point) from character.
|
||||
/// </summary>
|
||||
public IntExpr CharToInt(Expr ch)
|
||||
public IntExpr CharToInt(Expr ch)
|
||||
{
|
||||
Debug.Assert(ch != null);
|
||||
return new IntExpr(this, Native.Z3_mk_char_to_int(nCtx, ch.NativeObject));
|
||||
|
@ -2732,7 +2769,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a bit-vector (code point) from character.
|
||||
/// </summary>
|
||||
public BitVecExpr CharToBV(Expr ch)
|
||||
public BitVecExpr CharToBV(Expr ch)
|
||||
{
|
||||
Debug.Assert(ch != null);
|
||||
return new BitVecExpr(this, Native.Z3_mk_char_to_bv(nCtx, ch.NativeObject));
|
||||
|
@ -2741,7 +2778,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a character from a bit-vector (code point).
|
||||
/// </summary>
|
||||
public Expr CharFromBV(BitVecExpr bv)
|
||||
public Expr CharFromBV(BitVecExpr bv)
|
||||
{
|
||||
Debug.Assert(bv != null);
|
||||
return new Expr(this, Native.Z3_mk_char_from_bv(nCtx, bv.NativeObject));
|
||||
|
@ -2750,7 +2787,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a check if the character is a digit.
|
||||
/// </summary>
|
||||
public BoolExpr MkIsDigit(Expr ch)
|
||||
public BoolExpr MkIsDigit(Expr ch)
|
||||
{
|
||||
Debug.Assert(ch != null);
|
||||
return new BoolExpr(this, Native.Z3_mk_char_is_digit(nCtx, ch.NativeObject));
|
||||
|
@ -2768,7 +2805,7 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(args != null);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
var ts = args.ToArray();
|
||||
return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) ts.Length,
|
||||
return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint)ts.Length,
|
||||
AST.ArrayToNative(ts), k));
|
||||
}
|
||||
|
||||
|
@ -2780,7 +2817,7 @@ namespace Microsoft.Z3
|
|||
Debug.Assert(args != null);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
var ts = args.ToArray();
|
||||
return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint) ts.Length,
|
||||
return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint)ts.Length,
|
||||
AST.ArrayToNative(ts), k));
|
||||
}
|
||||
|
||||
|
@ -2789,13 +2826,13 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public BoolExpr MkPBLe(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
Debug.Assert(args != null);
|
||||
Debug.Assert(coeffs != null);
|
||||
Debug.Assert(args.Length == coeffs.Length);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length,
|
||||
AST.ArrayToNative(args),
|
||||
coeffs, k));
|
||||
Debug.Assert(args != null);
|
||||
Debug.Assert(coeffs != null);
|
||||
Debug.Assert(args.Length == coeffs.Length);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint)args.Length,
|
||||
AST.ArrayToNative(args),
|
||||
coeffs, k));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -2803,26 +2840,26 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public BoolExpr MkPBGe(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
Debug.Assert(args != null);
|
||||
Debug.Assert(coeffs != null);
|
||||
Debug.Assert(args.Length == coeffs.Length);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint) args.Length,
|
||||
AST.ArrayToNative(args),
|
||||
coeffs, k));
|
||||
Debug.Assert(args != null);
|
||||
Debug.Assert(coeffs != null);
|
||||
Debug.Assert(args.Length == coeffs.Length);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint)args.Length,
|
||||
AST.ArrayToNative(args),
|
||||
coeffs, k));
|
||||
}
|
||||
/// <summary>
|
||||
/// Create a pseudo-Boolean equal constraint.
|
||||
/// </summary>
|
||||
public BoolExpr MkPBEq(int[] coeffs, BoolExpr[] args, int k)
|
||||
{
|
||||
Debug.Assert(args != null);
|
||||
Debug.Assert(coeffs != null);
|
||||
Debug.Assert(args.Length == coeffs.Length);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_pbeq(nCtx, (uint) args.Length,
|
||||
AST.ArrayToNative(args),
|
||||
coeffs, k));
|
||||
Debug.Assert(args != null);
|
||||
Debug.Assert(coeffs != null);
|
||||
Debug.Assert(args.Length == coeffs.Length);
|
||||
CheckContextMatch<BoolExpr>(args);
|
||||
return new BoolExpr(this, Native.Z3_mk_pbeq(nCtx, (uint)args.Length,
|
||||
AST.ArrayToNative(args),
|
||||
coeffs, k));
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -3040,8 +3077,8 @@ namespace Microsoft.Z3
|
|||
/// <param name="size">the size of the bit-vector</param>
|
||||
public BitVecNum MkBV(string v, uint size)
|
||||
{
|
||||
|
||||
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecNum)MkNumeral(v, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3051,8 +3088,8 @@ namespace Microsoft.Z3
|
|||
/// <param name="size">the size of the bit-vector</param>
|
||||
public BitVecNum MkBV(int v, uint size)
|
||||
{
|
||||
|
||||
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecNum)MkNumeral(v, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3062,8 +3099,8 @@ namespace Microsoft.Z3
|
|||
/// <param name="size">the size of the bit-vector</param>
|
||||
public BitVecNum MkBV(uint v, uint size)
|
||||
{
|
||||
|
||||
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecNum)MkNumeral(v, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3073,8 +3110,8 @@ namespace Microsoft.Z3
|
|||
/// <param name="size">the size of the bit-vector</param>
|
||||
public BitVecNum MkBV(long v, uint size)
|
||||
{
|
||||
|
||||
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecNum)MkNumeral(v, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3084,8 +3121,8 @@ namespace Microsoft.Z3
|
|||
/// <param name="size">the size of the bit-vector</param>
|
||||
public BitVecNum MkBV(ulong v, uint size)
|
||||
{
|
||||
|
||||
return (BitVecNum)MkNumeral(v, MkBitVecSort(size));
|
||||
using var sort = MkBitVecSort(size);
|
||||
return (BitVecNum)MkNumeral(v, sort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -3332,7 +3369,7 @@ namespace Microsoft.Z3
|
|||
uint cd = AST.ArrayLength(decls);
|
||||
if (csn != cs || cdn != cd)
|
||||
throw new Z3Exception("Argument size mismatch");
|
||||
ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_string(nCtx, str,
|
||||
using ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_string(nCtx, str,
|
||||
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
|
||||
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)));
|
||||
return assertions.ToBoolExprArray();
|
||||
|
@ -3351,7 +3388,7 @@ namespace Microsoft.Z3
|
|||
uint cd = AST.ArrayLength(decls);
|
||||
if (csn != cs || cdn != cd)
|
||||
throw new Z3Exception("Argument size mismatch");
|
||||
ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_file(nCtx, fileName,
|
||||
using ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_file(nCtx, fileName,
|
||||
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
|
||||
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)));
|
||||
return assertions.ToBoolExprArray();
|
||||
|
@ -3836,8 +3873,8 @@ namespace Microsoft.Z3
|
|||
/// <seealso cref="MkSolver(Symbol)"/>
|
||||
public Solver MkSolver(string logic)
|
||||
{
|
||||
|
||||
return MkSolver(MkSymbol(logic));
|
||||
using var symbol = MkSymbol(logic);
|
||||
return MkSolver(symbol);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -4085,7 +4122,7 @@ namespace Microsoft.Z3
|
|||
/// <param name="negative">indicates whether the result should be negative.</param>
|
||||
public FPNum MkFPZero(FPSort s, bool negative)
|
||||
{
|
||||
return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, (byte)(negative ? 1 : 0)));
|
||||
return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, (byte)(negative ? 1 : 0)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -4127,7 +4164,7 @@ namespace Microsoft.Z3
|
|||
/// <param name="s">FloatingPoint sort.</param>
|
||||
public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s)
|
||||
{
|
||||
return new FPNum(this, Native.Z3_mk_fpa_numeral_int_uint(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
|
||||
return new FPNum(this, Native.Z3_mk_fpa_numeral_int_uint(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -4139,7 +4176,7 @@ namespace Microsoft.Z3
|
|||
/// <param name="s">FloatingPoint sort.</param>
|
||||
public FPNum MkFPNumeral(bool sgn, Int64 exp, UInt64 sig, FPSort s)
|
||||
{
|
||||
return new FPNum(this, Native.Z3_mk_fpa_numeral_int64_uint64(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
|
||||
return new FPNum(this, Native.Z3_mk_fpa_numeral_int64_uint64(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -4825,12 +4862,12 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// ASTVector DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue ASTVector_DRQ { get { return m_ASTVector_DRQ; } }
|
||||
public IDecRefQueue ASTVector_DRQ { get { return m_ASTVector_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// ApplyResult DRQ
|
||||
/// </summary>
|
||||
public IDecRefQueue ApplyResult_DRQ { get { return m_ApplyResult_DRQ; } }
|
||||
public IDecRefQueue ApplyResult_DRQ { get { return m_ApplyResult_DRQ; } }
|
||||
|
||||
/// <summary>
|
||||
/// FuncEntry DRQ
|
||||
|
@ -4926,10 +4963,16 @@ namespace Microsoft.Z3
|
|||
Fixedpoint_DRQ.Clear(this);
|
||||
Optimize_DRQ.Clear(this);
|
||||
|
||||
if (m_boolSort != null) m_boolSort.Dispose();
|
||||
if (m_intSort != null) m_intSort.Dispose();
|
||||
if (m_realSort != null) m_realSort.Dispose();
|
||||
if (m_stringSort != null) m_stringSort.Dispose();
|
||||
if (m_charSort != null) m_charSort.Dispose();
|
||||
m_boolSort = null;
|
||||
m_intSort = null;
|
||||
m_realSort = null;
|
||||
m_stringSort = null;
|
||||
m_charSort = null;
|
||||
if (refCount == 0 && m_ctx != IntPtr.Zero)
|
||||
{
|
||||
m_n_err_handler = null;
|
||||
|
@ -4937,7 +4980,7 @@ namespace Microsoft.Z3
|
|||
m_ctx = IntPtr.Zero;
|
||||
Native.Z3_del_context(ctx);
|
||||
}
|
||||
else
|
||||
else
|
||||
GC.ReRegisterForFinalize(this);
|
||||
}
|
||||
#endregion
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace Microsoft.Z3
|
|||
FuncDecl[][] res = new FuncDecl[n][];
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
FuncDecl fd = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i));
|
||||
using FuncDecl fd = new FuncDecl(Context, Native.Z3_get_datatype_sort_constructor(Context.nCtx, NativeObject, i));
|
||||
uint ds = fd.DomainSize;
|
||||
FuncDecl[] tmp = new FuncDecl[ds];
|
||||
for (uint j = 0; j < ds; j++)
|
||||
|
|
|
@ -74,7 +74,8 @@ namespace Microsoft.Z3
|
|||
/// <returns></returns>
|
||||
public Expr Const(uint inx)
|
||||
{
|
||||
return Context.MkApp(ConstDecl(inx));
|
||||
using var decl = ConstDecl(inx);
|
||||
return Context.MkApp(decl);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -255,7 +255,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_rules(Context.nCtx, NativeObject));
|
||||
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_rules(Context.nCtx, NativeObject));
|
||||
return av.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject));
|
||||
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject));
|
||||
return av.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public BoolExpr[] ParseFile(string file)
|
||||
{
|
||||
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_file(Context.nCtx, NativeObject, file));
|
||||
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_file(Context.nCtx, NativeObject, file));
|
||||
return av.ToBoolExprArray();
|
||||
}
|
||||
|
||||
|
@ -301,7 +301,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public BoolExpr[] ParseString(string s)
|
||||
{
|
||||
ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_string(Context.nCtx, NativeObject, s));
|
||||
using ASTVector av = new ASTVector(Context, Native.Z3_fixedpoint_from_string(Context.nCtx, NativeObject, s));
|
||||
return av.ToBoolExprArray();
|
||||
}
|
||||
|
||||
|
|
|
@ -203,8 +203,8 @@ namespace Microsoft.Z3
|
|||
/// <remarks>Essentially invokes the `simplify' tactic on the goal.</remarks>
|
||||
public Goal Simplify(Params p = null)
|
||||
{
|
||||
Tactic t = Context.MkTactic("simplify");
|
||||
ApplyResult res = t.Apply(this, p);
|
||||
using Tactic t = Context.MkTactic("simplify");
|
||||
using ApplyResult res = t.Apply(this, p);
|
||||
|
||||
if (res.NumSubgoals == 0)
|
||||
throw new Z3Exception("No subgoals");
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
<Authors>Microsoft</Authors>
|
||||
<Company>Microsoft</Company>
|
||||
|
||||
<LangVersion>8.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Code contract & signing properties -->
|
||||
|
|
|
@ -87,7 +87,8 @@ namespace Microsoft.Z3
|
|||
if (Native.Z3_is_as_array(Context.nCtx, n) == 0)
|
||||
throw new Z3Exception("Argument was not an array constant");
|
||||
IntPtr fd = Native.Z3_get_as_array_func_decl(Context.nCtx, n);
|
||||
return FuncInterp(new FuncDecl(Context, fd));
|
||||
using var decl = new FuncDecl(Context, fd);
|
||||
return FuncInterp(decl);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -241,7 +242,7 @@ namespace Microsoft.Z3
|
|||
/// Evaluate expression to a double, assuming it is a numeral already.
|
||||
/// </summary>
|
||||
public double Double(Expr t) {
|
||||
var r = Eval(t, true);
|
||||
using var r = Eval(t, true);
|
||||
return Native.Z3_get_numeral_double(Context.nCtx, r.NativeObject);
|
||||
}
|
||||
|
||||
|
@ -283,7 +284,7 @@ namespace Microsoft.Z3
|
|||
{
|
||||
Debug.Assert(s != null);
|
||||
|
||||
ASTVector av = new ASTVector(Context, Native.Z3_model_get_sort_universe(Context.nCtx, NativeObject, s.NativeObject));
|
||||
using ASTVector av = new ASTVector(Context, Native.Z3_model_get_sort_universe(Context.nCtx, NativeObject, s.NativeObject));
|
||||
return av.ToExprArray();
|
||||
}
|
||||
|
||||
|
|
1405
src/api/dotnet/NativeContext.cs
Normal file
1405
src/api/dotnet/NativeContext.cs
Normal file
File diff suppressed because it is too large
Load diff
104
src/api/dotnet/NativeFuncInterp.cs
Normal file
104
src/api/dotnet/NativeFuncInterp.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
NativeFuncInterp.cs
|
||||
|
||||
Abstract:
|
||||
|
||||
Z3 Managed API: Function Interpretations
|
||||
|
||||
Author:
|
||||
|
||||
Christoph Wintersteiger (cwinter) 2012-03-21
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
|
||||
using Z3_context = System.IntPtr;
|
||||
using Z3_ast = System.IntPtr;
|
||||
using Z3_app = System.IntPtr;
|
||||
using Z3_sort = System.IntPtr;
|
||||
using Z3_func_decl = System.IntPtr;
|
||||
using Z3_model = System.IntPtr;
|
||||
using Z3_func_interp = System.IntPtr;
|
||||
using Z3_func_entry = System.IntPtr;
|
||||
|
||||
/// <summary>
|
||||
/// A function interpretation is represented as a finite map and an 'else' value.
|
||||
/// Each entry in the finite map represents the value of a function given a set of arguments.
|
||||
/// </summary>
|
||||
public class NativeFuncInterp
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Evaluation entry of a function
|
||||
/// </summary>
|
||||
public class Entry
|
||||
{
|
||||
/// <summary>
|
||||
/// Argument values that define entry
|
||||
/// </summary>
|
||||
public Z3_ast[] Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Result of applying function to Arguments in the interpretation
|
||||
/// </summary>
|
||||
public Z3_ast Result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function that is interpreted
|
||||
/// </summary>
|
||||
public Z3_func_decl Declaration;
|
||||
|
||||
/// <summary>
|
||||
/// Set of non-default entries defining the function graph
|
||||
/// </summary>
|
||||
public Entry[] Entries;
|
||||
|
||||
/// <summary>
|
||||
/// Default cause of the function interpretation
|
||||
/// </summary>
|
||||
public Z3_ast Else;
|
||||
|
||||
#region Internal
|
||||
internal NativeFuncInterp(NativeContext ctx, NativeModel mdl, Z3_func_decl decl, Z3_func_interp fi)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
Z3_context nCtx = ctx.nCtx;
|
||||
Native.Z3_func_interp_inc_ref(nCtx, fi);
|
||||
|
||||
Declaration = decl;
|
||||
Else = Native.Z3_func_interp_get_else(nCtx, fi);
|
||||
uint numEntries = Native.Z3_func_interp_get_num_entries(nCtx, fi);
|
||||
uint numArgs = Native.Z3_func_interp_get_arity(nCtx, fi);
|
||||
Entries = new Entry[numEntries];
|
||||
|
||||
for (uint j = 0; j < numEntries; ++j)
|
||||
{
|
||||
var ntvEntry = Native.Z3_func_interp_get_entry(nCtx, fi, j);
|
||||
Entries[j] = new Entry();
|
||||
Native.Z3_func_entry_inc_ref(nCtx, ntvEntry);
|
||||
Entries[j].Arguments = new Z3_ast[numArgs];
|
||||
for (uint i = 0; i < numArgs; ++i)
|
||||
Entries[j].Arguments[i] = Native.Z3_func_entry_get_arg(nCtx, ntvEntry, i);
|
||||
Entries[j].Result = Native.Z3_func_entry_get_value(nCtx, ntvEntry);
|
||||
Native.Z3_func_entry_dec_ref(nCtx, ntvEntry);
|
||||
}
|
||||
|
||||
Native.Z3_func_interp_dec_ref(nCtx, fi);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
383
src/api/dotnet/NativeModel.cs
Normal file
383
src/api/dotnet/NativeModel.cs
Normal file
|
@ -0,0 +1,383 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
NativeModel.cs
|
||||
|
||||
Abstract:
|
||||
|
||||
Z3 Managed API: Models
|
||||
Native interface to model objects.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph Wintersteiger (cwinter) 2012-03-21
|
||||
Nikolaj Bjorner (nbjorner) 2022-03-01
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
using Z3_ast = System.IntPtr;
|
||||
using Z3_func_decl = System.IntPtr;
|
||||
using Z3_sort = System.IntPtr;
|
||||
|
||||
/// <summary>
|
||||
/// A Model contains interpretations (assignments) of constants and functions.
|
||||
/// </summary>
|
||||
public class NativeModel : IDisposable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the interpretation (the assignment) of <paramref name="a"/> in the model.
|
||||
/// </summary>
|
||||
/// <param name="a">A Constant</param>
|
||||
/// <returns>An expression if the constant has an interpretation in the model, null otherwise.</returns>
|
||||
public Z3_ast ConstInterp(Z3_ast a) => ConstFuncInterp(Native.Z3_get_app_decl(ntvContext.nCtx, a));
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the interpretation (the assignment) of <paramref name="f"/> in the model.
|
||||
/// </summary>
|
||||
/// <param name="f">A function declaration of zero arity</param>
|
||||
/// <returns>An expression if the function has an interpretation in the model, null otherwise.</returns>
|
||||
public Z3_ast ConstFuncInterp(Z3_func_decl f)
|
||||
{
|
||||
if (Native.Z3_get_arity(ntvContext.nCtx, f) != 0)
|
||||
throw new Z3Exception("Non-zero arity functions have FunctionInterpretations as a model. Use FuncInterp.");
|
||||
|
||||
return Native.Z3_model_get_const_interp(ntvContext.nCtx, NativeObject, f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the interpretation (the assignment) of a non-constant <paramref name="f"/> in the model.
|
||||
/// </summary>
|
||||
/// <param name="f">A function declaration of non-zero arity</param>
|
||||
/// <returns>A FunctionInterpretation if the function has an interpretation in the model, null otherwise.</returns>
|
||||
public NativeFuncInterp FuncInterp(Z3_func_decl f)
|
||||
{
|
||||
Z3_sort_kind sk = (Z3_sort_kind)Native.Z3_get_sort_kind(ntvContext.nCtx, Native.Z3_get_range(ntvContext.nCtx, f));
|
||||
|
||||
if (Native.Z3_get_arity(ntvContext.nCtx, f) == 0)
|
||||
{
|
||||
IntPtr n = Native.Z3_model_get_const_interp(ntvContext.nCtx, NativeObject, f);
|
||||
|
||||
if (sk == Z3_sort_kind.Z3_ARRAY_SORT)
|
||||
{
|
||||
if (n == IntPtr.Zero)
|
||||
return null;
|
||||
else
|
||||
{
|
||||
if (Native.Z3_is_as_array(ntvContext.nCtx, n) == 0)
|
||||
throw new Z3Exception("Argument was not an array constant");
|
||||
var fd = Native.Z3_get_as_array_func_decl(ntvContext.nCtx, n);
|
||||
return new NativeFuncInterp(ntvContext, this, f, fd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Z3Exception("Constant functions do not have a function interpretation; use ConstInterp");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IntPtr n = Native.Z3_model_get_func_interp(ntvContext.nCtx, NativeObject, f);
|
||||
if (n == IntPtr.Zero)
|
||||
return null;
|
||||
else
|
||||
return new NativeFuncInterp(ntvContext, this, f, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The number of constants that have an interpretation in the model.
|
||||
/// </summary>
|
||||
public uint NumConsts
|
||||
{
|
||||
get { return Native.Z3_model_get_num_consts(ntvContext.nCtx, NativeObject); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The function declarations of the constants in the model.
|
||||
/// </summary>
|
||||
public Z3_func_decl[] ConstDecls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
uint n = NumConsts;
|
||||
Z3_func_decl[] res = new Z3_func_decl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
res[i] = Native.Z3_model_get_const_decl(ntvContext.nCtx, NativeObject, i);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate constants in model.
|
||||
/// </summary>
|
||||
public IEnumerable<KeyValuePair<Z3_func_decl, Z3_ast>> Consts
|
||||
{
|
||||
get
|
||||
{
|
||||
uint nc = NumConsts;
|
||||
for (uint i = 0; i < nc; ++i)
|
||||
{
|
||||
var f = Native.Z3_model_get_const_decl(ntvContext.nCtx, NativeObject, i);
|
||||
IntPtr n = Native.Z3_model_get_const_interp(ntvContext.nCtx, NativeObject, f);
|
||||
if (n == IntPtr.Zero) continue;
|
||||
yield return new KeyValuePair<Z3_func_decl, Z3_ast>(f, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of function interpretations in the model.
|
||||
/// </summary>
|
||||
public uint NumFuncs
|
||||
{
|
||||
get { return Native.Z3_model_get_num_funcs(ntvContext.nCtx, NativeObject); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The function declarations of the function interpretations in the model.
|
||||
/// </summary>
|
||||
public Z3_func_decl[] FuncDecls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
uint n = NumFuncs;
|
||||
Z3_func_decl[] res = new Z3_func_decl[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
res[i] = Native.Z3_model_get_func_decl(ntvContext.nCtx, NativeObject, i);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All symbols that have an interpretation in the model.
|
||||
/// </summary>
|
||||
public Z3_func_decl[] Decls
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
uint nFuncs = NumFuncs;
|
||||
uint nConsts = NumConsts;
|
||||
uint n = nFuncs + nConsts;
|
||||
Z3_func_decl[] res = new Z3_func_decl[n];
|
||||
for (uint i = 0; i < nConsts; i++)
|
||||
res[i] = Native.Z3_model_get_const_decl(ntvContext.nCtx, NativeObject, i);
|
||||
for (uint i = 0; i < nFuncs; i++)
|
||||
res[nConsts + i] = Native.Z3_model_get_func_decl(ntvContext.nCtx, NativeObject, i);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model.
|
||||
/// </summary>
|
||||
public class ModelEvaluationFailedException : Z3Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception that is thrown when model evaluation fails.
|
||||
/// </summary>
|
||||
public ModelEvaluationFailedException() : base() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the expression <paramref name="t"/> in the current model.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function may fail if <paramref name="t"/> contains quantifiers,
|
||||
/// is partial (MODEL_PARTIAL enabled), or if <paramref name="t"/> is not well-sorted.
|
||||
/// In this case a <c>ModelEvaluationFailedException</c> is thrown.
|
||||
/// </remarks>
|
||||
/// <param name="t">An expression</param>
|
||||
/// <param name="completion">
|
||||
/// When this flag is enabled, a model value will be assigned to any constant
|
||||
/// or function that does not have an interpretation in the model.
|
||||
/// </param>
|
||||
/// <returns>The evaluation of <paramref name="t"/> in the model.</returns>
|
||||
public Z3_ast Eval(Z3_ast t, bool completion = false)
|
||||
{
|
||||
|
||||
IntPtr v = IntPtr.Zero;
|
||||
if (Native.Z3_model_eval(ntvContext.nCtx, NativeObject, t, (byte)(completion ? 1 : 0), ref v) == (byte)0)
|
||||
throw new ModelEvaluationFailedException();
|
||||
else
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alias for <c>Eval</c>.
|
||||
/// </summary>
|
||||
public Z3_ast Evaluate(Z3_ast t, bool completion = false) => Eval(t, completion);
|
||||
|
||||
/// <summary>
|
||||
/// Evaluate expression to a double, assuming it is a numeral already.
|
||||
/// </summary>
|
||||
public double Double(Z3_ast t)
|
||||
{
|
||||
var r = Eval(t, true);
|
||||
return Native.Z3_get_numeral_double(ntvContext.nCtx, r);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An array value obtained by untangling a model assignment.
|
||||
/// </summary>
|
||||
public class ArrayValue
|
||||
{
|
||||
/// <summary>
|
||||
/// One dimensional array of indices where the array is updated
|
||||
/// </summary>
|
||||
public KeyValuePair<Z3_ast, Z3_ast>[] Updates;
|
||||
|
||||
/// <summary>
|
||||
/// default Else case
|
||||
/// </summary>
|
||||
public Z3_ast Else;
|
||||
|
||||
/// <summary>
|
||||
/// Domain for array
|
||||
/// Updates.Keys
|
||||
/// </summary>
|
||||
public Z3_ast[] Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Range for array
|
||||
/// Updates.Values
|
||||
/// </summary>
|
||||
public Z3_ast[] Range;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the interpretation of t into a sequence of array updates
|
||||
/// </summary>
|
||||
/// <param name="t"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns>null if the argument does evaluate to a sequence of stores to an array</returns>
|
||||
public bool TryGetArrayValue(Z3_ast t, out ArrayValue result)
|
||||
{
|
||||
var r = Eval(t, true);
|
||||
// check that r is a sequence of store over a constant default array.
|
||||
var updates = new Dictionary<Z3_ast, Z3_ast>();
|
||||
result = null;
|
||||
while (true)
|
||||
{
|
||||
if (ntvContext.GetAstKind(r) != Z3_ast_kind.Z3_APP_AST)
|
||||
return false;
|
||||
Z3_func_decl f = ntvContext.GetAppDecl(r);
|
||||
var kind = ntvContext.GetDeclKind(f);
|
||||
if (kind == Z3_decl_kind.Z3_OP_CONST_ARRAY)
|
||||
{
|
||||
result = new ArrayValue();
|
||||
result.Else = ntvContext.GetAppArg(r, 0);
|
||||
result.Updates = updates.ToArray();
|
||||
result.Domain = updates.Keys.ToArray();
|
||||
result.Range = updates.Values.ToArray();
|
||||
return true;
|
||||
}
|
||||
else if (kind == Z3_decl_kind.Z3_OP_STORE)
|
||||
{
|
||||
Debug.Assert(ntvContext.GetNumArgs(r) == 3);
|
||||
updates[ntvContext.GetAppArg(r, 1)] = ntvContext.GetAppArg(r, 2);
|
||||
r = ntvContext.GetAppArg(r, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of uninterpreted sorts that the model has an interpretation for.
|
||||
/// </summary>
|
||||
public uint NumSorts { get { return Native.Z3_model_get_num_sorts(ntvContext.nCtx, NativeObject); } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The uninterpreted sorts that the model has an interpretation for.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Z3 also provides an interpretation for uninterpreted sorts used in a formula.
|
||||
/// The interpretation for a sort is a finite set of distinct values. We say this finite set is
|
||||
/// the "universe" of the sort.
|
||||
/// </remarks>
|
||||
/// <seealso cref="NumSorts"/>
|
||||
public Z3_sort[] Sorts
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
uint n = NumSorts;
|
||||
Z3_sort[] res = new Z3_sort[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
res[i] = Native.Z3_model_get_sort(ntvContext.nCtx, NativeObject, i);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Conversion of models to strings.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of the model.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Native.Z3_model_to_string(ntvContext.nCtx, NativeObject);
|
||||
}
|
||||
|
||||
|
||||
IntPtr NativeObject;
|
||||
NativeContext ntvContext;
|
||||
|
||||
internal NativeModel(NativeContext ctx, IntPtr obj)
|
||||
{
|
||||
ntvContext = ctx;
|
||||
NativeObject = obj;
|
||||
Debug.Assert(ctx != null);
|
||||
Native.Z3_model_inc_ref(ctx.nCtx, obj);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer.
|
||||
/// </summary>
|
||||
~NativeModel()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of the underlying native Z3 object.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (NativeObject != IntPtr.Zero)
|
||||
{
|
||||
Native.Z3_model_dec_ref(ntvContext.nCtx, NativeObject);
|
||||
NativeObject = IntPtr.Zero;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
451
src/api/dotnet/NativeSolver.cs
Normal file
451
src/api/dotnet/NativeSolver.cs
Normal file
|
@ -0,0 +1,451 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
NativeSolver.cs
|
||||
|
||||
Abstract:
|
||||
|
||||
Z3 Managed API: Native Solver
|
||||
|
||||
Author:
|
||||
|
||||
Christoph Wintersteiger (cwinter) 2012-03-22
|
||||
Nikolaj Bjorner (nbjorner) 2022-03-01
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
|
||||
using Z3_ast = System.IntPtr;
|
||||
using Z3_context = System.IntPtr;
|
||||
using Z3_func_decl = System.IntPtr;
|
||||
using Z3_params = System.IntPtr;
|
||||
using Z3_solver = System.IntPtr;
|
||||
using Z3_sort = System.IntPtr;
|
||||
using Z3_symbol = System.IntPtr;
|
||||
|
||||
/// <summary>
|
||||
/// Solvers.
|
||||
/// </summary>
|
||||
public class NativeSolver : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// A string that describes all available solver parameters.
|
||||
/// </summary>
|
||||
public string Help => Native.Z3_solver_get_help(nCtx, z3solver);
|
||||
|
||||
private void SetParam(Action<Z3_params> setter)
|
||||
{
|
||||
Z3_params p = Native.Z3_mk_params(nCtx);
|
||||
Native.Z3_params_inc_ref(nCtx, p);
|
||||
setter(p);
|
||||
Native.Z3_solver_set_params(nCtx, z3solver, p);
|
||||
Native.Z3_params_dec_ref(nCtx, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, bool value)
|
||||
{
|
||||
SetParam((Z3_params p) => Native.Z3_params_set_bool(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), (byte)(value ? 1 : 0)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, uint value)
|
||||
{
|
||||
SetParam((Z3_params p) => Native.Z3_params_set_uint(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, double value)
|
||||
{
|
||||
SetParam((Z3_params p) => Native.Z3_params_set_double(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, string value)
|
||||
{
|
||||
var value_sym = Native.Z3_mk_string_symbol(nCtx, value);
|
||||
SetParam((Z3_params p) => Native.Z3_params_set_symbol(nCtx, p, Native.Z3_mk_string_symbol(nCtx, name), value_sym));
|
||||
}
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, bool value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, uint value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, double value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, string value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves parameter descriptions for solver.
|
||||
/// </summary>
|
||||
public ParamDescrs ParameterDescriptions
|
||||
{
|
||||
get { return new ParamDescrs(Context, Native.Z3_solver_get_param_descrs(nCtx, NativeObject)); }
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The current number of backtracking points (scopes).
|
||||
/// </summary>
|
||||
/// <seealso cref="Pop"/>
|
||||
/// <seealso cref="Push"/>
|
||||
public uint NumScopes => Native.Z3_solver_get_num_scopes(nCtx, z3solver);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a backtracking point.
|
||||
/// </summary>
|
||||
/// <seealso cref="Pop"/>
|
||||
public void Push() => Native.Z3_solver_push(nCtx, z3solver);
|
||||
|
||||
/// <summary>
|
||||
/// Backtracks <paramref name="n"/> backtracking points.
|
||||
/// </summary>
|
||||
/// <remarks>Note that an exception is thrown if <paramref name="n"/> is not smaller than <c>NumScopes</c></remarks>
|
||||
/// <seealso cref="Push"/>
|
||||
public void Pop(uint n = 1) => Native.Z3_solver_pop(nCtx, z3solver, n);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the Solver.
|
||||
/// </summary>
|
||||
/// <remarks>This removes all assertions from the solver.</remarks>
|
||||
public void Reset() => Native.Z3_solver_reset(nCtx, z3solver);
|
||||
|
||||
/// <summary>
|
||||
/// Assert a constraint (or multiple) into the solver.
|
||||
/// </summary>
|
||||
public void Assert(params Z3_ast[] constraints)
|
||||
{
|
||||
Debug.Assert(constraints != null);
|
||||
Debug.Assert(constraints.All(c => c != IntPtr.Zero));
|
||||
|
||||
foreach (Z3_ast a in constraints)
|
||||
{
|
||||
Native.Z3_solver_assert(nCtx, z3solver, a);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alias for Assert.
|
||||
/// </summary>
|
||||
public void Add(params Z3_ast[] constraints) => Assert(constraints);
|
||||
|
||||
/// <summary>
|
||||
/// Alias for Assert.
|
||||
/// </summary>
|
||||
public void Add(IEnumerable<Z3_ast> constraints) => Assert(constraints.ToArray());
|
||||
|
||||
/// <summary>
|
||||
/// Add constraints to ensure the function f can only be injective.
|
||||
/// Example:
|
||||
/// for function f : D1 x D2 -> R
|
||||
/// assert axioms
|
||||
/// forall (x1 : D1, x2 : D2) x1 = inv1(f(x1,x2))
|
||||
/// forall (x1 : D1, x2 : D2) x2 = inv2(f(x1,x2))
|
||||
/// </summary>
|
||||
/// <param name="f"></param>
|
||||
public void AssertInjective(Z3_func_decl f)
|
||||
{
|
||||
uint arity = Native.Z3_get_arity(nCtx, f);
|
||||
Z3_sort range = Native.Z3_get_range(nCtx, f);
|
||||
Z3_ast[] vars = new Z3_ast[arity];
|
||||
Z3_sort[] sorts = new Z3_sort[arity];
|
||||
Z3_symbol[] names = new Z3_symbol[arity];
|
||||
for (uint i = 0; i < arity; ++i)
|
||||
{
|
||||
Z3_sort domain = Native.Z3_get_domain(nCtx, f, i);
|
||||
vars[i] = ntvContext.MkBound(arity - i - 1, domain);
|
||||
sorts[i] = domain;
|
||||
names[i] = Native.Z3_mk_int_symbol(nCtx, (int)i);
|
||||
}
|
||||
Z3_ast app_f = IntPtr.Zero; // Context.MkApp(f, vars);
|
||||
for (uint i = 0; i < arity; ++i)
|
||||
{
|
||||
Z3_sort domain = Native.Z3_get_domain(nCtx, f, i);
|
||||
Z3_func_decl proj = ntvContext.MkFreshFuncDecl("inv", new Z3_sort[] { range }, domain);
|
||||
Z3_ast body = ntvContext.MkEq(vars[i], ntvContext.MkApp(proj, app_f));
|
||||
Z3_ast q = ntvContext.MkForall(names, sorts, body);
|
||||
Assert(q);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert multiple constraints into the solver, and track them (in the unsat) core
|
||||
/// using the Boolean constants in ps.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This API is an alternative to <see cref="Check(Z3_ast[])"/> with assumptions for extracting unsat cores.
|
||||
/// Both APIs can be used in the same solver. The unsat core will contain a combination
|
||||
/// of the Boolean variables provided using <see cref="AssertAndTrack(Z3_ast[],Z3_ast[])"/>
|
||||
/// and the Boolean literals
|
||||
/// provided using <see cref="Check(Z3_ast[])"/> with assumptions.
|
||||
/// </remarks>
|
||||
public void AssertAndTrack(Z3_ast[] constraints, Z3_ast[] ps)
|
||||
{
|
||||
Debug.Assert(constraints != null);
|
||||
Debug.Assert(constraints.All(c => c != IntPtr.Zero));
|
||||
Debug.Assert(ps.All(c => c != IntPtr.Zero));
|
||||
if (constraints.Length != ps.Length)
|
||||
throw new Z3Exception("Argument size mismatch");
|
||||
|
||||
for (int i = 0; i < constraints.Length; i++)
|
||||
Native.Z3_solver_assert_and_track(nCtx, z3solver, constraints[i], ps[i]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert a constraint into the solver, and track it (in the unsat) core
|
||||
/// using the Boolean constant p.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This API is an alternative to <see cref="Check(Z3_ast[])"/> with assumptions for extracting unsat cores.
|
||||
/// Both APIs can be used in the same solver. The unsat core will contain a combination
|
||||
/// of the Boolean variables provided using <see cref="AssertAndTrack(Z3_ast[],Z3_ast[])"/>
|
||||
/// and the Boolean literals
|
||||
/// provided using <see cref="Check(Z3_ast[])"/> with assumptions.
|
||||
/// </remarks>
|
||||
public void AssertAndTrack(Z3_ast constraint, Z3_ast p)
|
||||
{
|
||||
Debug.Assert(constraint != null);
|
||||
Debug.Assert(p != null);
|
||||
|
||||
Native.Z3_solver_assert_and_track(nCtx, z3solver, constraint, p);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load solver assertions from a file.
|
||||
/// </summary>
|
||||
public void FromFile(string file)
|
||||
=> Native.Z3_solver_from_file(nCtx, z3solver, file);
|
||||
|
||||
/// <summary>
|
||||
/// Load solver assertions from a string.
|
||||
/// </summary>
|
||||
public void FromString(string str)
|
||||
=> Native.Z3_solver_from_string(nCtx, z3solver, str);
|
||||
|
||||
/// <summary>
|
||||
/// The number of assertions in the solver.
|
||||
/// </summary>
|
||||
public uint NumAssertions
|
||||
=> (uint)ntvContext.ToArray(Native.Z3_solver_get_assertions(nCtx, z3solver)).Length;
|
||||
|
||||
/// <summary>
|
||||
/// The set of asserted formulas.
|
||||
/// </summary>
|
||||
public Z3_ast[] Assertions
|
||||
=> ntvContext.ToArray(Native.Z3_solver_get_assertions(nCtx, z3solver));
|
||||
|
||||
/// <summary>
|
||||
/// Currently inferred units.
|
||||
/// </summary>
|
||||
public Z3_ast[] Units
|
||||
=> ntvContext.ToArray(Native.Z3_solver_get_units(nCtx, z3solver));
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the assertions in the solver are consistent or not.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <seealso cref="Model"/>
|
||||
/// <seealso cref="UnsatCore"/>
|
||||
/// <seealso cref="Proof"/>
|
||||
/// </remarks>
|
||||
public Status Check(params Z3_ast[] assumptions)
|
||||
{
|
||||
Z3_lbool r;
|
||||
if (assumptions == null || assumptions.Length == 0)
|
||||
r = (Z3_lbool)Native.Z3_solver_check(nCtx, z3solver);
|
||||
else
|
||||
r = (Z3_lbool)Native.Z3_solver_check_assumptions(nCtx, z3solver, (uint)assumptions.Length, assumptions);
|
||||
return lboolToStatus(r);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the assertions in the solver are consistent or not.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <seealso cref="Model"/>
|
||||
/// <seealso cref="UnsatCore"/>
|
||||
/// <seealso cref="Proof"/>
|
||||
/// </remarks>
|
||||
public Status Check(IEnumerable<Z3_ast> assumptions)
|
||||
{
|
||||
Z3_lbool r;
|
||||
Z3_ast[] asms = assumptions.ToArray();
|
||||
if (asms.Length == 0)
|
||||
r = (Z3_lbool)Native.Z3_solver_check(nCtx, z3solver);
|
||||
else
|
||||
r = (Z3_lbool)Native.Z3_solver_check_assumptions(nCtx, z3solver, (uint)asms.Length, asms);
|
||||
return lboolToStatus(r);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The model of the last <c>Check(params Expr[] assumptions)</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The result is <c>null</c> if <c>Check(params Expr[] assumptions)</c> was not invoked before,
|
||||
/// if its results was not <c>SATISFIABLE</c>, or if model production is not enabled.
|
||||
/// </remarks>
|
||||
public NativeModel Model
|
||||
{
|
||||
get
|
||||
{
|
||||
IntPtr x = Native.Z3_solver_get_model(nCtx, z3solver);
|
||||
return x == IntPtr.Zero
|
||||
? null
|
||||
: new NativeModel(ntvContext, x);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The proof of the last <c>Check(params Expr[] assumptions)</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The result is <c>null</c> if <c>Check(params Expr[] assumptions)</c> was not invoked before,
|
||||
/// if its results was not <c>UNSATISFIABLE</c>, or if proof production is disabled.
|
||||
/// </remarks>
|
||||
public Z3_ast Proof
|
||||
=> Native.Z3_solver_get_proof(nCtx, z3solver);
|
||||
|
||||
/// <summary>
|
||||
/// The unsat core of the last <c>Check</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The unsat core is a subset of <c>Assertions</c>
|
||||
/// The result is empty if <c>Check</c> was not invoked before,
|
||||
/// if its results was not <c>UNSATISFIABLE</c>, or if core production is disabled.
|
||||
/// </remarks>
|
||||
public Z3_ast[] UnsatCore
|
||||
=> ntvContext.ToArray(Native.Z3_solver_get_unsat_core(nCtx, z3solver));
|
||||
|
||||
/// <summary>
|
||||
/// A brief justification of why the last call to <c>Check</c> returned <c>UNKNOWN</c>.
|
||||
/// </summary>
|
||||
public string ReasonUnknown
|
||||
=> Native.Z3_solver_get_reason_unknown(nCtx, z3solver);
|
||||
|
||||
/// <summary>
|
||||
/// Create a clone of the current solver with respect to <c>ctx</c>.
|
||||
/// </summary>
|
||||
public NativeSolver Translate(NativeContext ctx)
|
||||
{
|
||||
Debug.Assert(ctx != null);
|
||||
return new NativeSolver(ctx, Native.Z3_solver_translate(nCtx, z3solver, ctx.nCtx));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import model converter from other solver.
|
||||
/// </summary>
|
||||
public void ImportModelConverter(NativeSolver src)
|
||||
{
|
||||
Debug.Assert(src != null);
|
||||
|
||||
Native.Z3_solver_import_model_converter(nCtx, src.z3solver, z3solver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Solver statistics.
|
||||
/// </summary>
|
||||
public Statistics.Entry[] Statistics
|
||||
{
|
||||
get
|
||||
{
|
||||
var stats = Native.Z3_solver_get_statistics(nCtx, z3solver);
|
||||
return ntvContext.GetStatistics(stats);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A string representation of the solver.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return Native.Z3_solver_to_string(nCtx, z3solver);
|
||||
}
|
||||
|
||||
#region Internal
|
||||
readonly NativeContext ntvContext;
|
||||
Z3_solver z3solver;
|
||||
Z3_context nCtx => ntvContext.nCtx;
|
||||
|
||||
internal NativeSolver(NativeContext nativeCtx, Z3_solver z3solver)
|
||||
{
|
||||
Debug.Assert(nativeCtx != null);
|
||||
Debug.Assert(z3solver != IntPtr.Zero);
|
||||
|
||||
this.ntvContext = nativeCtx;
|
||||
this.z3solver = z3solver;
|
||||
|
||||
Native.Z3_solver_inc_ref(nCtx, z3solver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizer.
|
||||
/// </summary>
|
||||
~NativeSolver()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of the underlying native Z3 object.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (z3solver != IntPtr.Zero)
|
||||
{
|
||||
Native.Z3_solver_dec_ref(nCtx, z3solver);
|
||||
z3solver = IntPtr.Zero;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
private Status lboolToStatus(Z3_lbool r)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case Z3_lbool.Z3_L_TRUE: return Status.SATISFIABLE;
|
||||
case Z3_lbool.Z3_L_FALSE: return Status.UNSATISFIABLE;
|
||||
default: return Status.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -212,7 +212,7 @@ namespace Microsoft.Z3
|
|||
public Handle AssertSoft(BoolExpr constraint, uint weight, string group)
|
||||
{
|
||||
Context.CheckContextMatch(constraint);
|
||||
Symbol s = Context.MkSymbol(group);
|
||||
using Symbol s = Context.MkSymbol(group);
|
||||
return new Handle(this, Native.Z3_optimize_assert_soft(Context.nCtx, NativeObject, constraint.NativeObject, weight.ToString(), s.NativeObject));
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector core = new ASTVector(Context, Native.Z3_optimize_get_unsat_core(Context.nCtx, NativeObject));
|
||||
using ASTVector core = new ASTVector(Context, Native.Z3_optimize_get_unsat_core(Context.nCtx, NativeObject));
|
||||
return core.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
private Expr[] GetLowerAsVector(uint index)
|
||||
{
|
||||
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_lower_as_vector(Context.nCtx, NativeObject, index));
|
||||
using ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_lower_as_vector(Context.nCtx, NativeObject, index));
|
||||
return v.ToExprArray();
|
||||
}
|
||||
|
||||
|
@ -347,7 +347,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
private Expr[] GetUpperAsVector(uint index)
|
||||
{
|
||||
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_upper_as_vector(Context.nCtx, NativeObject, index));
|
||||
using ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_upper_as_vector(Context.nCtx, NativeObject, index));
|
||||
return v.ToExprArray();
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector assertions = new ASTVector(Context, Native.Z3_optimize_get_assertions(Context.nCtx, NativeObject));
|
||||
using ASTVector assertions = new ASTVector(Context, Native.Z3_optimize_get_assertions(Context.nCtx, NativeObject));
|
||||
return assertions.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -409,7 +409,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector objectives = new ASTVector(Context, Native.Z3_optimize_get_objectives(Context.nCtx, NativeObject));
|
||||
using ASTVector objectives = new ASTVector(Context, Native.Z3_optimize_get_objectives(Context.nCtx, NativeObject));
|
||||
return objectives.ToExprArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace Microsoft.Z3
|
|||
{
|
||||
get
|
||||
{
|
||||
IntNum n = Numerator;
|
||||
using IntNum n = Numerator;
|
||||
return BigInteger.Parse(n.ToString());
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace Microsoft.Z3
|
|||
{
|
||||
get
|
||||
{
|
||||
IntNum n = Denominator;
|
||||
using IntNum n = Denominator;
|
||||
return BigInteger.Parse(n.ToString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,43 +58,92 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, bool value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(string name, bool value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, uint value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(string name, uint value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, double value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(string name, double value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, string value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(string name, string value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(string name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(string name, Symbol value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, bool value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(Symbol name, bool value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, uint value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(Symbol name, uint value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, double value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(Symbol name, double value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, string value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(Symbol name, string value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets parameter on the solver
|
||||
/// </summary>
|
||||
public void Set(Symbol name, Symbol value) { Parameters = Context.MkParams().Add(name, value); }
|
||||
public void Set(Symbol name, Symbol value)
|
||||
{
|
||||
using var parameters = Context.MkParams().Add(name, value);
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -245,7 +294,7 @@ namespace Microsoft.Z3
|
|||
{
|
||||
get
|
||||
{
|
||||
ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
|
||||
using ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
|
||||
return assertions.Size;
|
||||
}
|
||||
}
|
||||
|
@ -258,7 +307,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
|
||||
using ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_assertions(Context.nCtx, NativeObject));
|
||||
return assertions.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +320,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_units(Context.nCtx, NativeObject));
|
||||
using ASTVector assertions = new ASTVector(Context, Native.Z3_solver_get_units(Context.nCtx, NativeObject));
|
||||
return assertions.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -330,9 +379,9 @@ namespace Microsoft.Z3
|
|||
/// </remarks>
|
||||
public Status Consequences(IEnumerable<BoolExpr> assumptions, IEnumerable<Expr> variables, out BoolExpr[] consequences)
|
||||
{
|
||||
ASTVector result = new ASTVector(Context);
|
||||
ASTVector asms = new ASTVector(Context);
|
||||
ASTVector vars = new ASTVector(Context);
|
||||
using ASTVector result = new ASTVector(Context);
|
||||
using ASTVector asms = new ASTVector(Context);
|
||||
using ASTVector vars = new ASTVector(Context);
|
||||
foreach (var asm in assumptions) asms.Push(asm);
|
||||
foreach (var v in variables) vars.Push(v);
|
||||
Z3_lbool r = (Z3_lbool)Native.Z3_solver_get_consequences(Context.nCtx, NativeObject, asms.NativeObject, vars.NativeObject, result.NativeObject);
|
||||
|
@ -391,7 +440,7 @@ namespace Microsoft.Z3
|
|||
get
|
||||
{
|
||||
|
||||
ASTVector core = new ASTVector(Context, Native.Z3_solver_get_unsat_core(Context.nCtx, NativeObject));
|
||||
using ASTVector core = new ASTVector(Context, Native.Z3_solver_get_unsat_core(Context.nCtx, NativeObject));
|
||||
return core.ToBoolExprArray();
|
||||
}
|
||||
}
|
||||
|
@ -424,14 +473,14 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public IEnumerable<BoolExpr[]> Cube()
|
||||
{
|
||||
ASTVector cv = new ASTVector(Context);
|
||||
using ASTVector cv = new ASTVector(Context);
|
||||
if (CubeVariables != null)
|
||||
foreach (var b in CubeVariables) cv.Push(b);
|
||||
|
||||
while (true) {
|
||||
var lvl = BacktrackLevel;
|
||||
BacktrackLevel = uint.MaxValue;
|
||||
ASTVector r = new ASTVector(Context, Native.Z3_solver_cube(Context.nCtx, NativeObject, cv.NativeObject, lvl));
|
||||
using ASTVector r = new ASTVector(Context, Native.Z3_solver_cube(Context.nCtx, NativeObject, cv.NativeObject, lvl));
|
||||
var v = r.ToBoolExprArray();
|
||||
CubeVariables = cv.ToBoolExprArray();
|
||||
if (v.Length == 1 && v[0].IsFalse) {
|
||||
|
|
|
@ -23,6 +23,9 @@ using System.Diagnostics;
|
|||
|
||||
namespace Microsoft.Z3
|
||||
{
|
||||
|
||||
using Z3_context = System.IntPtr;
|
||||
using Z3_stats = System.IntPtr;
|
||||
/// <summary>
|
||||
/// Objects of this class track statistical information about solvers.
|
||||
/// </summary>
|
||||
|
@ -123,25 +126,29 @@ namespace Microsoft.Z3
|
|||
{
|
||||
get
|
||||
{
|
||||
|
||||
uint n = Size;
|
||||
Entry[] res = new Entry[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
Entry e;
|
||||
string k = Native.Z3_stats_get_key(Context.nCtx, NativeObject, i);
|
||||
if (Native.Z3_stats_is_uint(Context.nCtx, NativeObject, i) != 0)
|
||||
e = new Entry(k, Native.Z3_stats_get_uint_value(Context.nCtx, NativeObject, i));
|
||||
else if (Native.Z3_stats_is_double(Context.nCtx, NativeObject, i) != 0)
|
||||
e = new Entry(k, Native.Z3_stats_get_double_value(Context.nCtx, NativeObject, i));
|
||||
else
|
||||
throw new Z3Exception("Unknown data entry value");
|
||||
res[i] = e;
|
||||
}
|
||||
return res;
|
||||
return NativeEntries(Context.nCtx, NativeObject);
|
||||
}
|
||||
}
|
||||
|
||||
internal static Entry[] NativeEntries(Z3_context ctx, Z3_stats stats)
|
||||
{
|
||||
uint n = Native.Z3_stats_size(ctx, stats);
|
||||
Entry[] res = new Entry[n];
|
||||
for (uint i = 0; i < n; i++)
|
||||
{
|
||||
Entry e;
|
||||
string k = Native.Z3_stats_get_key(ctx, stats, i);
|
||||
if (Native.Z3_stats_is_uint(ctx, stats, i) != 0)
|
||||
e = new Entry(k, Native.Z3_stats_get_uint_value(ctx, stats, i));
|
||||
else if (Native.Z3_stats_is_double(ctx, stats, i) != 0)
|
||||
e = new Entry(k, Native.Z3_stats_get_double_value(ctx, stats, i));
|
||||
else
|
||||
throw new Z3Exception("Unknown data entry value");
|
||||
res[i] = e;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The statistical counters.
|
||||
/// </summary>
|
||||
|
|
|
@ -2106,6 +2106,26 @@ public class Context implements AutoCloseable {
|
|||
return (BoolExpr) Expr.create(this, Native.mkSeqContains(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string s1 is lexicographically strictly less than s2.
|
||||
*/
|
||||
|
||||
public BoolExpr MkStringLt(SeqSort<CharSort> s1, SeqSort<CharSort> s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return new BoolExpr(this, Native.mkStrLt(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the string s1 is lexicographically less or equal to s2.
|
||||
*/
|
||||
public BoolExpr MkStringLe(SeqSort<CharSort> s1, SeqSort<CharSort> s2)
|
||||
{
|
||||
checkContextMatch(s1, s2);
|
||||
return new BoolExpr(this, Native.mkStrLe(nCtx(), s1.getNativeObject(), s2.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve sequence of length one at index.
|
||||
*/
|
||||
|
@ -2180,6 +2200,14 @@ public class Context implements AutoCloseable {
|
|||
return (ReExpr<R>) Expr.create(this, Native.mkReStar(nCtx(), re.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create power regular expression.
|
||||
*/
|
||||
public <R extends Sort> ReExpr<R> mkPower(Expr<ReSort<R>> re, int n)
|
||||
{
|
||||
return (ReExpr<R>) Expr.create(this, Native.mkRePower(nCtx(), re.getNativeObject(), n));
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the lower and upper-bounded Kleene star of a regular expression.
|
||||
*/
|
||||
|
@ -4038,6 +4066,37 @@ public class Context implements AutoCloseable {
|
|||
return new BitVecExpr(this, Native.mkFpaToFpIntReal(nCtx(), rm.getNativeObject(), exp.getNativeObject(), sig.getNativeObject(), s.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or a linear order.
|
||||
* @param index The index of the order.
|
||||
* @param sort The sort of the order.
|
||||
*/
|
||||
public <R extends Sort> FuncDecl<BoolSort> mkLinearOrder(R sort, int index) {
|
||||
return (FuncDecl<BoolSort>) FuncDecl.create(
|
||||
this,
|
||||
Native.mkLinearOrder(
|
||||
nCtx(),
|
||||
sort.getNativeObject(),
|
||||
index
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates or a partial order.
|
||||
* @param index The index of the order.
|
||||
* @param sort The sort of the order.
|
||||
*/
|
||||
public <R extends Sort> FuncDecl<BoolSort> mkPartialOrder(R sort, int index) {
|
||||
return (FuncDecl<BoolSort>) FuncDecl.create(
|
||||
this,
|
||||
Native.mkPartialOrder(
|
||||
nCtx(),
|
||||
sort.getNativeObject(),
|
||||
index
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an AST.
|
||||
|
|
|
@ -294,7 +294,8 @@ static struct custom_operations Z3_ast_plus_custom_ops = {
|
|||
Z3_ast_compare_ext
|
||||
};
|
||||
|
||||
MK_CTX_OF(ast, 16) // let's say 16 bytes per ast
|
||||
// FUDGE
|
||||
MK_CTX_OF(ast, 8) // let's say 16 bytes per ast
|
||||
|
||||
#define MK_PLUS_OBJ_NO_REF(X, USED) \
|
||||
typedef struct { \
|
||||
|
@ -410,25 +411,26 @@ MK_CTX_OF(ast, 16) // let's say 16 bytes per ast
|
|||
\
|
||||
MK_CTX_OF(X, USED)
|
||||
|
||||
MK_PLUS_OBJ_NO_REF(symbol, 32)
|
||||
MK_PLUS_OBJ_NO_REF(constructor, 32)
|
||||
MK_PLUS_OBJ_NO_REF(constructor_list, 32)
|
||||
MK_PLUS_OBJ_NO_REF(rcf_num, 32)
|
||||
MK_PLUS_OBJ(params, 128)
|
||||
MK_PLUS_OBJ(param_descrs, 128)
|
||||
MK_PLUS_OBJ(model, 512)
|
||||
MK_PLUS_OBJ(func_interp, 128)
|
||||
MK_PLUS_OBJ(func_entry, 128)
|
||||
MK_PLUS_OBJ(goal, 128)
|
||||
MK_PLUS_OBJ(tactic, 128)
|
||||
MK_PLUS_OBJ(probe, 128)
|
||||
MK_PLUS_OBJ(apply_result, 128)
|
||||
MK_PLUS_OBJ(solver, 20 * 1000 * 1000) // pretend a solver is 20MB
|
||||
MK_PLUS_OBJ(stats, 128)
|
||||
MK_PLUS_OBJ(ast_map, 1024 * 2)
|
||||
MK_PLUS_OBJ(ast_vector, 128)
|
||||
MK_PLUS_OBJ(fixedpoint, 20 * 1000 * 1000)
|
||||
MK_PLUS_OBJ(optimize, 20 * 1000 * 1000)
|
||||
// FUDGE
|
||||
MK_PLUS_OBJ_NO_REF(symbol, 16)
|
||||
MK_PLUS_OBJ_NO_REF(constructor, 16)
|
||||
MK_PLUS_OBJ_NO_REF(constructor_list, 16)
|
||||
MK_PLUS_OBJ_NO_REF(rcf_num, 16)
|
||||
MK_PLUS_OBJ(params, 64)
|
||||
MK_PLUS_OBJ(param_descrs, 64)
|
||||
MK_PLUS_OBJ(model, 64)
|
||||
MK_PLUS_OBJ(func_interp, 32)
|
||||
MK_PLUS_OBJ(func_entry, 32)
|
||||
MK_PLUS_OBJ(goal, 64)
|
||||
MK_PLUS_OBJ(tactic, 64)
|
||||
MK_PLUS_OBJ(probe, 64)
|
||||
MK_PLUS_OBJ(apply_result, 32)
|
||||
MK_PLUS_OBJ(solver, 20 * 1000)
|
||||
MK_PLUS_OBJ(stats, 32)
|
||||
MK_PLUS_OBJ(ast_map, 32)
|
||||
MK_PLUS_OBJ(ast_vector, 32)
|
||||
MK_PLUS_OBJ(fixedpoint, 20 * 1000)
|
||||
MK_PLUS_OBJ(optimize, 20 * 1000)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -42,8 +42,6 @@ add_custom_command(OUTPUT "${z3py_bindings_build_dest}/z3/z3core.py"
|
|||
${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN}
|
||||
"${PROJECT_SOURCE_DIR}/scripts/update_api.py"
|
||||
${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES}
|
||||
# FIXME: When update_api.py no longer uses ``mk_util`` drop this dependency
|
||||
"${PROJECT_SOURCE_DIR}/scripts/mk_util.py"
|
||||
COMMENT "Generating z3core.py"
|
||||
${ADD_CUSTOM_COMMAND_USES_TERMINAL_ARG}
|
||||
)
|
||||
|
|
|
@ -5,3 +5,4 @@ recursive-include core *.cmake
|
|||
recursive-include core/src *
|
||||
recursive-include core/cmake *
|
||||
recursive-include core/scripts *
|
||||
include pyproject.toml
|
||||
|
|
3
src/api/python/pyproject.toml
Normal file
3
src/api/python/pyproject.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=46.4.0", "wheel", "cmake"]
|
||||
build-backend = "setuptools.build_meta"
|
|
@ -154,16 +154,10 @@ def _copy_bins():
|
|||
|
||||
_clean_bins()
|
||||
|
||||
python_dir = None
|
||||
if RELEASE_DIR is not None:
|
||||
python_dir = os.path.join(RELEASE_DIR, 'bin', 'python')
|
||||
elif SRC_DIR == SRC_DIR_LOCAL:
|
||||
python_dir = os.path.join(SRC_DIR, 'src', 'api', 'python')
|
||||
if python_dir is not None:
|
||||
py_z3_build_dir = os.path.join(BUILD_DIR, 'python', 'z3')
|
||||
root_z3_dir = os.path.join(ROOT_DIR, 'z3')
|
||||
shutil.copy(os.path.join(py_z3_build_dir, 'z3core.py'), root_z3_dir)
|
||||
shutil.copy(os.path.join(py_z3_build_dir, 'z3consts.py'), root_z3_dir)
|
||||
py_z3_build_dir = os.path.join(BUILD_DIR, 'python', 'z3')
|
||||
root_z3_dir = os.path.join(ROOT_DIR, 'z3')
|
||||
shutil.copy(os.path.join(py_z3_build_dir, 'z3core.py'), root_z3_dir)
|
||||
shutil.copy(os.path.join(py_z3_build_dir, 'z3consts.py'), root_z3_dir)
|
||||
|
||||
# STEP 2: Copy the shared library, the executable and the headers
|
||||
|
||||
|
@ -184,6 +178,20 @@ def _copy_bins():
|
|||
continue
|
||||
shutil.copy(os.path.join(header_dir, fname), os.path.join(HEADERS_DIR, fname))
|
||||
|
||||
# This hack lets z3 installed libs link on M1 macs; it is a hack, not a proper fix
|
||||
# @TODO: Linked issue: https://github.com/Z3Prover/z3/issues/5926
|
||||
major_minor = '.'.join(_z3_version().split('.')[:2])
|
||||
link_name = None
|
||||
if BUILD_PLATFORM in ('win32', 'cygwin', 'win'):
|
||||
pass # TODO: When windows VMs work on M1, fill this in
|
||||
elif BUILD_PLATFORM in ('darwin', 'osx'):
|
||||
split = LIBRARY_FILE.split('.')
|
||||
link_name = split[0] + '.' + major_minor + '.' + split[1]
|
||||
else:
|
||||
link_name = LIBRARY_FILE + '.' + major_minor
|
||||
if link_name:
|
||||
os.symlink(LIBRARY_FILE, os.path.join(LIBS_DIR, link_name), True)
|
||||
|
||||
def _copy_sources():
|
||||
"""
|
||||
Prepare for a source distribution by assembling a minimal set of source files needed
|
||||
|
@ -281,6 +289,8 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
|||
osver = '.'.join(osver.split('.')[:2])
|
||||
if arch == 'x64':
|
||||
plat_name ='macosx_%s_x86_64' % osver.replace('.', '_')
|
||||
elif arch == 'arm64':
|
||||
plat_name ='macosx_%s_arm64' % osver.replace('.', '_')
|
||||
else:
|
||||
raise Exception(f"idk how os {distos} {osver} works. what goes here?")
|
||||
else:
|
||||
|
@ -291,7 +301,6 @@ if 'bdist_wheel' in sys.argv and '--plat-name' not in sys.argv:
|
|||
sys.argv.insert(idx + 1, plat_name)
|
||||
sys.argv.insert(idx + 2, '--universal') # supports py2+py3. if --plat-name is not specified this will also mean that the package can be installed on any machine regardless of architecture, so watch out!
|
||||
|
||||
|
||||
setup(
|
||||
name='z3-solver',
|
||||
version=_z3_version(),
|
||||
|
|
|
@ -12,8 +12,6 @@ Z3 is used in many applications such as: software/hardware verification and test
|
|||
constraint solving, analysis of hybrid systems, security, biology (in silico analysis),
|
||||
and geometrical problems.
|
||||
|
||||
Several online tutorials for Z3Py are available at:
|
||||
http://rise4fun.com/Z3Py/tutorial/guide
|
||||
|
||||
Please send feedback, comments and/or corrections on the Issue tracker for
|
||||
https://github.com/Z3prover/z3.git. Your comments are very valuable.
|
||||
|
@ -103,9 +101,6 @@ def get_version():
|
|||
def get_full_version():
|
||||
return Z3_get_full_version()
|
||||
|
||||
# We use _z3_assert instead of the assert command because we want to
|
||||
# produce nice error messages in Z3Py at rise4fun.com
|
||||
|
||||
|
||||
def _z3_assert(cond, msg):
|
||||
if not cond:
|
||||
|
@ -1771,7 +1766,7 @@ def Xor(a, b, ctx=None):
|
|||
>>> Xor(p, q)
|
||||
Xor(p, q)
|
||||
>>> simplify(Xor(p, q))
|
||||
Not(p) == q
|
||||
Not(p == q)
|
||||
"""
|
||||
ctx = _get_ctx(_ctx_from_ast_arg_list([a, b], ctx))
|
||||
s = BoolSort(ctx)
|
||||
|
@ -2015,8 +2010,7 @@ class QuantifierRef(BoolRef):
|
|||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(self.is_lambda(), "quantifier should be a lambda expression")
|
||||
arg = self.sort().domain().cast(arg)
|
||||
return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx)
|
||||
return _array_select(self, arg)
|
||||
|
||||
def weight(self):
|
||||
"""Return the weight annotation of `self`.
|
||||
|
@ -2285,6 +2279,9 @@ class ArithSortRef(SortRef):
|
|||
"""
|
||||
return self.kind() == Z3_INT_SORT
|
||||
|
||||
def is_bool(self):
|
||||
return False
|
||||
|
||||
def subsort(self, other):
|
||||
"""Return `True` if `self` is a subsort of `other`."""
|
||||
return self.is_int() and is_arith_sort(other) and other.is_real()
|
||||
|
@ -4496,6 +4493,11 @@ class ArraySortRef(SortRef):
|
|||
"""
|
||||
return _to_sort_ref(Z3_get_array_sort_domain(self.ctx_ref(), self.ast), self.ctx)
|
||||
|
||||
def domain_n(self, i):
|
||||
"""Return the domain of the array sort `self`.
|
||||
"""
|
||||
return _to_sort_ref(Z3_get_array_sort_domain_n(self.ctx_ref(), self.ast, i), self.ctx)
|
||||
|
||||
def range(self):
|
||||
"""Return the range of the array sort `self`.
|
||||
|
||||
|
@ -4527,6 +4529,10 @@ class ArrayRef(ExprRef):
|
|||
"""
|
||||
return self.sort().domain()
|
||||
|
||||
def domain_n(self, i):
|
||||
"""Shorthand for self.sort().domain_n(i)`."""
|
||||
return self.sort().domain_n(i)
|
||||
|
||||
def range(self):
|
||||
"""Shorthand for `self.sort().range()`.
|
||||
|
||||
|
@ -4546,13 +4552,21 @@ class ArrayRef(ExprRef):
|
|||
>>> a[i].sexpr()
|
||||
'(select a i)'
|
||||
"""
|
||||
arg = self.domain().cast(arg)
|
||||
return _to_expr_ref(Z3_mk_select(self.ctx_ref(), self.as_ast(), arg.as_ast()), self.ctx)
|
||||
return _array_select(self, arg)
|
||||
|
||||
def default(self):
|
||||
return _to_expr_ref(Z3_mk_array_default(self.ctx_ref(), self.as_ast()), self.ctx)
|
||||
|
||||
|
||||
def _array_select(ar, arg):
|
||||
if isinstance(arg, tuple):
|
||||
args = [ar.domain_n(i).cast(arg[i]) for i in range(len(arg))]
|
||||
_args, sz = _to_ast_array(args)
|
||||
return _to_expr_ref(Z3_mk_select_n(ar.ctx_ref(), ar.as_ast(), sz, _args), ar.ctx)
|
||||
arg = ar.domain().cast(arg)
|
||||
return _to_expr_ref(Z3_mk_select(ar.ctx_ref(), ar.as_ast(), arg.as_ast()), ar.ctx)
|
||||
|
||||
|
||||
def is_array_sort(a):
|
||||
return Z3_get_sort_kind(a.ctx.ref(), Z3_get_sort(a.ctx.ref(), a.ast)) == Z3_ARRAY_SORT
|
||||
|
||||
|
@ -4679,7 +4693,7 @@ def ArraySort(*sig):
|
|||
return ArraySortRef(Z3_mk_array_sort_n(ctx.ref(), arity, dom, r.ast), ctx)
|
||||
|
||||
|
||||
def Array(name, dom, rng):
|
||||
def Array(name, *sorts):
|
||||
"""Return an array constant named `name` with the given domain and range sorts.
|
||||
|
||||
>>> a = Array('a', IntSort(), IntSort())
|
||||
|
@ -4688,12 +4702,12 @@ def Array(name, dom, rng):
|
|||
>>> a[0]
|
||||
a[0]
|
||||
"""
|
||||
s = ArraySort(dom, rng)
|
||||
s = ArraySort(sorts)
|
||||
ctx = s.ctx
|
||||
return ArrayRef(Z3_mk_const(ctx.ref(), to_symbol(name, ctx), s.ast), ctx)
|
||||
|
||||
|
||||
def Update(a, i, v):
|
||||
def Update(a, *args):
|
||||
"""Return a Z3 store array expression.
|
||||
|
||||
>>> a = Array('a', IntSort(), IntSort())
|
||||
|
@ -4709,10 +4723,20 @@ def Update(a, i, v):
|
|||
"""
|
||||
if z3_debug():
|
||||
_z3_assert(is_array_sort(a), "First argument must be a Z3 array expression")
|
||||
i = a.sort().domain().cast(i)
|
||||
v = a.sort().range().cast(v)
|
||||
args = _get_args(args)
|
||||
ctx = a.ctx
|
||||
return _to_expr_ref(Z3_mk_store(ctx.ref(), a.as_ast(), i.as_ast(), v.as_ast()), ctx)
|
||||
if len(args) <= 1:
|
||||
raise Z3Exception("array update requires index and value arguments")
|
||||
if len(args) == 2:
|
||||
i = args[0]
|
||||
v = args[1]
|
||||
i = a.sort().domain().cast(i)
|
||||
v = a.sort().range().cast(v)
|
||||
return _to_expr_ref(Z3_mk_store(ctx.ref(), a.as_ast(), i.as_ast(), v.as_ast()), ctx)
|
||||
v = a.sort().range().cast(args[-1])
|
||||
idxs = [a.sort().domain_n(i).cast(args[i]) for i in range(len(args)-1)]
|
||||
_args, sz = _to_ast_array(idxs)
|
||||
return _to_expr_ref(Z3_mk_store_n(ctx.ref(), a.as_ast(), sz, _args, v.as_ast()), ctx)
|
||||
|
||||
|
||||
def Default(a):
|
||||
|
@ -4726,7 +4750,7 @@ def Default(a):
|
|||
return a.default()
|
||||
|
||||
|
||||
def Store(a, i, v):
|
||||
def Store(a, *args):
|
||||
"""Return a Z3 store array expression.
|
||||
|
||||
>>> a = Array('a', IntSort(), IntSort())
|
||||
|
@ -4740,10 +4764,10 @@ def Store(a, i, v):
|
|||
>>> prove(Implies(i != j, s[j] == a[j]))
|
||||
proved
|
||||
"""
|
||||
return Update(a, i, v)
|
||||
return Update(a, args)
|
||||
|
||||
|
||||
def Select(a, i):
|
||||
def Select(a, *args):
|
||||
"""Return a Z3 select array expression.
|
||||
|
||||
>>> a = Array('a', IntSort(), IntSort())
|
||||
|
@ -4753,9 +4777,10 @@ def Select(a, i):
|
|||
>>> eq(Select(a, i), a[i])
|
||||
True
|
||||
"""
|
||||
args = _get_args(args)
|
||||
if z3_debug():
|
||||
_z3_assert(is_array_sort(a), "First argument must be a Z3 array expression")
|
||||
return a[i]
|
||||
return a[args]
|
||||
|
||||
|
||||
def Map(f, *args):
|
||||
|
@ -6569,6 +6594,19 @@ class ModelRef(Z3PPObject):
|
|||
"""Update the interpretation of a constant"""
|
||||
if is_expr(x):
|
||||
x = x.decl()
|
||||
if is_func_decl(x) and x.arity() != 0 and isinstance(value, FuncInterp):
|
||||
fi1 = value.f
|
||||
fi2 = Z3_add_func_interp(x.ctx_ref(), self.model, x.ast, value.else_value().ast);
|
||||
fi2 = FuncInterp(fi2, x.ctx)
|
||||
for i in range(value.num_entries()):
|
||||
e = value.entry(i)
|
||||
n = Z3_func_entry_get_num_args(x.ctx_ref(), e.entry)
|
||||
v = AstVector()
|
||||
for j in range(n):
|
||||
v.push(entry.arg_value(j))
|
||||
val = Z3_func_entry_get_value(x.ctx_ref(), e.entry)
|
||||
Z3_func_interp_add_entry(x.ctx_ref(), fi2.f, v.vector, val)
|
||||
return
|
||||
if not is_func_decl(x) or x.arity() != 0:
|
||||
raise Z3Exception("Expecting 0-ary function or constant expression")
|
||||
value = _py2expr(value)
|
||||
|
@ -8856,7 +8894,7 @@ def _pb_args_coeffs(args, default_ctx=None):
|
|||
for i in range(len(coeffs)):
|
||||
_z3_check_cint_overflow(coeffs[i], "coefficient")
|
||||
_coeffs[i] = coeffs[i]
|
||||
return ctx, sz, _args, _coeffs
|
||||
return ctx, sz, _args, _coeffs, args
|
||||
|
||||
|
||||
def PbLe(args, k):
|
||||
|
@ -8866,7 +8904,7 @@ def PbLe(args, k):
|
|||
>>> f = PbLe(((a,1),(b,3),(c,2)), 3)
|
||||
"""
|
||||
_z3_check_cint_overflow(k, "k")
|
||||
ctx, sz, _args, _coeffs = _pb_args_coeffs(args)
|
||||
ctx, sz, _args, _coeffs, args = _pb_args_coeffs(args)
|
||||
return BoolRef(Z3_mk_pble(ctx.ref(), sz, _args, _coeffs, k), ctx)
|
||||
|
||||
|
||||
|
@ -8877,7 +8915,7 @@ def PbGe(args, k):
|
|||
>>> f = PbGe(((a,1),(b,3),(c,2)), 3)
|
||||
"""
|
||||
_z3_check_cint_overflow(k, "k")
|
||||
ctx, sz, _args, _coeffs = _pb_args_coeffs(args)
|
||||
ctx, sz, _args, _coeffs, args = _pb_args_coeffs(args)
|
||||
return BoolRef(Z3_mk_pbge(ctx.ref(), sz, _args, _coeffs, k), ctx)
|
||||
|
||||
|
||||
|
@ -8888,7 +8926,7 @@ def PbEq(args, k, ctx=None):
|
|||
>>> f = PbEq(((a,1),(b,3),(c,2)), 3)
|
||||
"""
|
||||
_z3_check_cint_overflow(k, "k")
|
||||
ctx, sz, _args, _coeffs = _pb_args_coeffs(args)
|
||||
ctx, sz, _args, _coeffs, args = _pb_args_coeffs(args)
|
||||
return BoolRef(Z3_mk_pbeq(ctx.ref(), sz, _args, _coeffs, k), ctx)
|
||||
|
||||
|
||||
|
@ -8982,7 +9020,7 @@ def prove(claim, show=False, **keywords):
|
|||
|
||||
|
||||
def _solve_html(*args, **keywords):
|
||||
"""Version of function `solve` used in RiSE4Fun."""
|
||||
"""Version of function `solve` that renders HTML output."""
|
||||
show = keywords.pop("show", False)
|
||||
s = Solver()
|
||||
s.set(**keywords)
|
||||
|
@ -9006,7 +9044,7 @@ def _solve_html(*args, **keywords):
|
|||
|
||||
|
||||
def _solve_using_html(s, *args, **keywords):
|
||||
"""Version of function `solve_using` used in RiSE4Fun."""
|
||||
"""Version of function `solve_using` that renders HTML."""
|
||||
show = keywords.pop("show", False)
|
||||
if z3_debug():
|
||||
_z3_assert(isinstance(s, Solver), "Solver object expected")
|
||||
|
@ -9031,7 +9069,7 @@ def _solve_using_html(s, *args, **keywords):
|
|||
|
||||
|
||||
def _prove_html(claim, show=False, **keywords):
|
||||
"""Version of function `prove` used in RiSE4Fun."""
|
||||
"""Version of function `prove` that renders HTML."""
|
||||
if z3_debug():
|
||||
_z3_assert(is_bool(claim), "Z3 Boolean expression expected")
|
||||
s = Solver()
|
||||
|
@ -11215,12 +11253,16 @@ def ensure_prop_closures():
|
|||
_prop_closures = PropClosures()
|
||||
|
||||
|
||||
def user_prop_push(ctx):
|
||||
_prop_closures.get(ctx).push()
|
||||
def user_prop_push(ctx, cb):
|
||||
prop = _prop_closures.get(ctx)
|
||||
prop.cb = cb
|
||||
prop.push()
|
||||
|
||||
|
||||
def user_prop_pop(ctx, num_scopes):
|
||||
_prop_closures.get(ctx).pop(num_scopes)
|
||||
def user_prop_pop(ctx, cb, num_scopes):
|
||||
prop = _prop_closures.get(ctx)
|
||||
prop.cb = cb
|
||||
pop(num_scopes)
|
||||
|
||||
|
||||
def user_prop_fresh(id, ctx):
|
||||
|
@ -11230,31 +11272,38 @@ def user_prop_fresh(id, ctx):
|
|||
_prop_closures.set(new_prop.id, new_prop)
|
||||
return ctypes.c_void_p(new_prop.id)
|
||||
|
||||
def to_Ast(ptr,):
|
||||
ast = Ast(ptr)
|
||||
super(ctypes.c_void_p, ast).__init__(ptr)
|
||||
return ast
|
||||
|
||||
def user_prop_fixed(ctx, cb, id, value):
|
||||
prop = _prop_closures.get(ctx)
|
||||
prop.cb = cb
|
||||
prop.fixed(id, _to_expr_ref(ctypes.c_void_p(value), prop.ctx()))
|
||||
id = _to_expr_ref(to_Ast(id), prop.ctx())
|
||||
value = _to_expr_ref(to_Ast(value), prop.ctx())
|
||||
prop.fixed(id, value)
|
||||
prop.cb = None
|
||||
|
||||
|
||||
def user_prop_final(ctx, cb):
|
||||
prop = _prop_closures.get(ctx)
|
||||
prop.cb = cb
|
||||
prop.final()
|
||||
prop.cb = None
|
||||
|
||||
|
||||
def user_prop_eq(ctx, cb, x, y):
|
||||
prop = _prop_closures.get(ctx)
|
||||
prop.cb = cb
|
||||
x = _to_expr_ref(to_Ast(x), prop.ctx())
|
||||
y = _to_expr_ref(to_Ast(y), prop.ctx())
|
||||
prop.eq(x, y)
|
||||
prop.cb = None
|
||||
|
||||
|
||||
def user_prop_diseq(ctx, cb, x, y):
|
||||
prop = _prop_closures.get(ctx)
|
||||
prop.cb = cb
|
||||
x = _to_expr_ref(to_Ast(x), prop.ctx())
|
||||
y = _to_expr_ref(to_Ast(y), prop.ctx())
|
||||
prop.diseq(x, y)
|
||||
prop.cb = None
|
||||
|
||||
|
@ -11352,24 +11401,18 @@ class UserPropagateBase:
|
|||
def add(self, e):
|
||||
assert self.solver
|
||||
assert not self._ctx
|
||||
return Z3_solver_propagate_register(self.ctx_ref(), self.solver.solver, e.ast)
|
||||
Z3_solver_propagate_register(self.ctx_ref(), self.solver.solver, e.ast)
|
||||
|
||||
#
|
||||
# Propagation can only be invoked as during a fixed or final callback.
|
||||
#
|
||||
def propagate(self, e, ids, eqs=[]):
|
||||
num_fixed = len(ids)
|
||||
_ids = (ctypes.c_uint * num_fixed)()
|
||||
for i in range(num_fixed):
|
||||
_ids[i] = ids[i]
|
||||
_ids, num_fixed = _to_ast_array(ids)
|
||||
num_eqs = len(eqs)
|
||||
_lhs = (ctypes.c_uint * num_eqs)()
|
||||
_rhs = (ctypes.c_uint * num_eqs)()
|
||||
for i in range(num_eqs):
|
||||
_lhs[i] = eqs[i][0]
|
||||
_rhs[i] = eqs[i][1]
|
||||
_lhs, _num_lhs = _to_ast_array([x for x, y in eqs])
|
||||
_rhs, _num_rhs = _to_ast_array([y for x, y in eqs])
|
||||
Z3_solver_propagate_consequence(e.ctx.ref(), ctypes.c_void_p(
|
||||
self.cb), num_fixed, _ids, num_eqs, _lhs, _rhs, e.ast)
|
||||
|
||||
def conflict(self, ids):
|
||||
self.propagate(BoolVal(False, self.ctx()), ids, eqs=[])
|
||||
def conflict(self, deps):
|
||||
self.propagate(BoolVal(False, self.ctx()), deps, eqs=[])
|
||||
|
|
|
@ -996,6 +996,8 @@ typedef enum
|
|||
information is exposed. Tools may use the string representation of the
|
||||
function declaration to obtain more information.
|
||||
|
||||
- Z3_OP_RECURSIVE: function declared as recursive
|
||||
|
||||
- Z3_OP_UNINTERPRETED: kind used for uninterpreted symbols.
|
||||
*/
|
||||
typedef enum {
|
||||
|
@ -1220,13 +1222,17 @@ typedef enum {
|
|||
Z3_OP_RE_CONCAT,
|
||||
Z3_OP_RE_UNION,
|
||||
Z3_OP_RE_RANGE,
|
||||
Z3_OP_RE_DIFF,
|
||||
Z3_OP_RE_INTERSECT,
|
||||
Z3_OP_RE_LOOP,
|
||||
Z3_OP_RE_POWER,
|
||||
Z3_OP_RE_INTERSECT,
|
||||
Z3_OP_RE_DIFF,
|
||||
Z3_OP_RE_COMPLEMENT,
|
||||
Z3_OP_RE_EMPTY_SET,
|
||||
Z3_OP_RE_FULL_SET,
|
||||
Z3_OP_RE_COMPLEMENT,
|
||||
Z3_OP_RE_FULL_CHAR_SET,
|
||||
Z3_OP_RE_OF_PRED,
|
||||
Z3_OP_RE_REVERSE,
|
||||
Z3_OP_RE_DERIVATIVE,
|
||||
|
||||
// char
|
||||
Z3_OP_CHAR_CONST,
|
||||
|
@ -1316,6 +1322,7 @@ typedef enum {
|
|||
Z3_OP_FPA_BV2RM,
|
||||
|
||||
Z3_OP_INTERNAL,
|
||||
Z3_OP_RECURSIVE,
|
||||
|
||||
Z3_OP_UNINTERPRETED
|
||||
} Z3_decl_kind;
|
||||
|
@ -1430,13 +1437,14 @@ Z3_DECLARE_CLOSURE(Z3_error_handler, void, (Z3_context c, Z3_error_code e));
|
|||
/**
|
||||
\brief callback functions for user propagator.
|
||||
*/
|
||||
Z3_DECLARE_CLOSURE(Z3_push_eh, void, (void* ctx));
|
||||
Z3_DECLARE_CLOSURE(Z3_pop_eh, void, (void* ctx, unsigned num_scopes));
|
||||
Z3_DECLARE_CLOSURE(Z3_push_eh, void, (void* ctx, Z3_solver_callback cb));
|
||||
Z3_DECLARE_CLOSURE(Z3_pop_eh, void, (void* ctx, Z3_solver_callback cb, unsigned num_scopes));
|
||||
Z3_DECLARE_CLOSURE(Z3_fresh_eh, void*, (void* ctx, Z3_context new_context));
|
||||
Z3_DECLARE_CLOSURE(Z3_fixed_eh, void, (void* ctx, Z3_solver_callback cb, unsigned id, Z3_ast value));
|
||||
Z3_DECLARE_CLOSURE(Z3_eq_eh, void, (void* ctx, Z3_solver_callback cb, unsigned x, unsigned y));
|
||||
Z3_DECLARE_CLOSURE(Z3_fixed_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast t, Z3_ast value));
|
||||
Z3_DECLARE_CLOSURE(Z3_eq_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast s, Z3_ast t));
|
||||
Z3_DECLARE_CLOSURE(Z3_final_eh, void, (void* ctx, Z3_solver_callback cb));
|
||||
Z3_DECLARE_CLOSURE(Z3_created_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast e, unsigned id));
|
||||
Z3_DECLARE_CLOSURE(Z3_created_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast t));
|
||||
Z3_DECLARE_CLOSURE(Z3_decide_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast*, unsigned*, Z3_lbool*));
|
||||
|
||||
|
||||
/**
|
||||
|
@ -3817,6 +3825,13 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_re_loop(Z3_context c, Z3_ast r, unsigned lo, unsigned hi);
|
||||
|
||||
/**
|
||||
\brief Create a power regular expression.
|
||||
|
||||
def_API('Z3_mk_re_power', AST, (_in(CONTEXT), _in(AST), _in(UINT)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_re_power(Z3_context c, Z3_ast, unsigned n);
|
||||
|
||||
/**
|
||||
\brief Create the intersection of the regular languages.
|
||||
|
||||
|
@ -4358,11 +4373,27 @@ extern "C" {
|
|||
|
||||
\sa Z3_mk_array_sort
|
||||
\sa Z3_get_sort_kind
|
||||
\sa Z3_get_array_sort_domain_n
|
||||
|
||||
def_API('Z3_get_array_sort_domain', SORT, (_in(CONTEXT), _in(SORT)))
|
||||
*/
|
||||
Z3_sort Z3_API Z3_get_array_sort_domain(Z3_context c, Z3_sort t);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return the i'th domain sort of an n-dimensional array.
|
||||
|
||||
\pre Z3_get_sort_kind(c, t) == Z3_ARRAY_SORT
|
||||
|
||||
\sa Z3_mk_array_sort
|
||||
\sa Z3_get_sort_kind
|
||||
\sa Z3_get_array_sort_domain
|
||||
|
||||
def_API('Z3_get_array_sort_domain_n', SORT, (_in(CONTEXT), _in(SORT), _in(UINT)))
|
||||
|
||||
*/
|
||||
Z3_sort Z3_API Z3_get_array_sort_domain_n(Z3_context c, Z3_sort t, unsigned idx);
|
||||
|
||||
/**
|
||||
\brief Return the range of the given array sort.
|
||||
|
||||
|
@ -6672,6 +6703,13 @@ extern "C" {
|
|||
|
||||
/**
|
||||
\brief register a user-properator with the solver.
|
||||
|
||||
\param c - context.
|
||||
\param s - solver object.
|
||||
\param user_context - a context used to maintain state for callbacks.
|
||||
\param push_eh - a callback invoked when scopes are pushed
|
||||
\param pop_eh - a callback invoked when scopes are poped
|
||||
\param fresh_eh - a solver may spawn new solvers internally. This callback is used to produce a fresh user_context to be associated with fresh solvers.
|
||||
*/
|
||||
|
||||
void Z3_API Z3_solver_propagate_init(
|
||||
|
@ -6694,11 +6732,15 @@ extern "C" {
|
|||
/**
|
||||
\brief register a callback on final check.
|
||||
This provides freedom to the propagator to delay actions or implement a branch-and bound solver.
|
||||
The final check is invoked when all decision variables have been assigned by the solver.
|
||||
|
||||
The final_eh callback takes as argument the original user_context that was used
|
||||
when calling \c Z3_solver_propagate_init, and it takes a callback context for propagations.
|
||||
If may use the callback context to invoke the \c Z3_solver_propagate_consequence function.
|
||||
If the callback context gets used, the solver continues.
|
||||
The \c final_eh callback takes as argument the original user_context that was used
|
||||
when calling \c Z3_solver_propagate_init, and it takes a callback context with the
|
||||
opaque type \c Z3_solver_callback.
|
||||
The callback context is passed as argument to invoke the \c Z3_solver_propagate_consequence function.
|
||||
The callback context can only be accessed (for propagation and for dynamically registering expressions) within a callback.
|
||||
If the callback context gets used for propagation or conflicts, those propagations take effect and
|
||||
may trigger new decision variables to be set.
|
||||
*/
|
||||
void Z3_API Z3_solver_propagate_final(Z3_context c, Z3_solver s, Z3_final_eh final_eh);
|
||||
|
||||
|
@ -6717,6 +6759,14 @@ extern "C" {
|
|||
* The registered function appears at the top level and is created using \ref Z3_propagate_solver_declare.
|
||||
*/
|
||||
void Z3_API Z3_solver_propagate_created(Z3_context c, Z3_solver s, Z3_created_eh created_eh);
|
||||
|
||||
/**
|
||||
* \brief register a callback when a the solver decides to split on a registered expression
|
||||
* The callback may set passed expression to another registered expression which will be selected instead.
|
||||
* In case the expression is a bitvector the bit to split on is determined by the bit argument and the
|
||||
* truth-value to try first is given by is_pos
|
||||
*/
|
||||
void Z3_API Z3_solver_propagate_decide(Z3_context c, Z3_solver s, Z3_decide_eh decide_eh);
|
||||
|
||||
/**
|
||||
Create uninterpreted function declaration for the user propagator.
|
||||
|
@ -6734,10 +6784,10 @@ extern "C" {
|
|||
\brief register an expression to propagate on with the solver.
|
||||
Only expressions of type Bool and type Bit-Vector can be registered for propagation.
|
||||
|
||||
def_API('Z3_solver_propagate_register', UINT, (_in(CONTEXT), _in(SOLVER), _in(AST)))
|
||||
def_API('Z3_solver_propagate_register', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST)))
|
||||
*/
|
||||
|
||||
unsigned Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e);
|
||||
void Z3_API Z3_solver_propagate_register(Z3_context c, Z3_solver s, Z3_ast e);
|
||||
|
||||
/**
|
||||
\brief register an expression to propagate on with the solver.
|
||||
|
@ -6745,9 +6795,9 @@ extern "C" {
|
|||
Unlike \ref Z3_solver_propagate_register, this function takes a solver callback context
|
||||
as argument. It can be invoked during a callback to register new expressions.
|
||||
|
||||
def_API('Z3_solver_propagate_register_cb', UINT, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(AST)))
|
||||
def_API('Z3_solver_propagate_register_cb', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(AST)))
|
||||
*/
|
||||
unsigned Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback cb, Z3_ast e);
|
||||
void Z3_API Z3_solver_propagate_register_cb(Z3_context c, Z3_solver_callback cb, Z3_ast e);
|
||||
|
||||
/**
|
||||
\brief propagate a consequence based on fixed values.
|
||||
|
@ -6755,10 +6805,10 @@ extern "C" {
|
|||
The callback adds a propagation consequence based on the fixed values of the
|
||||
\c ids.
|
||||
|
||||
def_API('Z3_solver_propagate_consequence', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, UINT), _in(UINT), _in_array(4, UINT), _in_array(4, UINT), _in(AST)))
|
||||
def_API('Z3_solver_propagate_consequence', VOID, (_in(CONTEXT), _in(SOLVER_CALLBACK), _in(UINT), _in_array(2, AST), _in(UINT), _in_array(4, AST), _in_array(4, AST), _in(AST)))
|
||||
*/
|
||||
|
||||
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback, unsigned num_fixed, unsigned const* fixed_ids, unsigned num_eqs, unsigned const* eq_lhs, unsigned const* eq_rhs, Z3_ast conseq);
|
||||
void Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
|
||||
|
||||
/**
|
||||
\brief Check whether the assertions in a given solver are consistent or not.
|
||||
|
|
|
@ -82,7 +82,7 @@ extern "C" {
|
|||
\param c - context
|
||||
\param o - optimization context
|
||||
\param a - formula
|
||||
\param weight - a positive weight, penalty for violating soft constraint
|
||||
\param weight - a penalty for violating soft constraint. Negative weights convert into rewards.
|
||||
\param id - optional identifier to group soft constraints
|
||||
|
||||
\sa Z3_optimize_assert
|
||||
|
|
|
@ -27,6 +27,7 @@ Revision History:
|
|||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/ast_translation.h"
|
||||
#include "util/z3_version.h"
|
||||
|
||||
|
@ -233,8 +234,7 @@ std::ostream& operator<<(std::ostream& out, sort_size const & ss) {
|
|||
// -----------------------------------
|
||||
std::ostream & operator<<(std::ostream & out, sort_info const & info) {
|
||||
operator<<(out, static_cast<decl_info const&>(info));
|
||||
out << " :size " << info.get_num_elements();
|
||||
return out;
|
||||
return out << " :size " << info.get_num_elements();
|
||||
}
|
||||
|
||||
// -----------------------------------
|
||||
|
@ -1758,13 +1758,13 @@ ast * ast_manager::register_node_core(ast * n) {
|
|||
switch (n->get_kind()) {
|
||||
case AST_SORT:
|
||||
if (to_sort(n)->m_info != nullptr) {
|
||||
to_sort(n)->m_info = alloc(sort_info, *(to_sort(n)->get_info()));
|
||||
to_sort(n)->m_info = alloc(sort_info, std::move(*(to_sort(n)->get_info())));
|
||||
to_sort(n)->m_info->init_eh(*this);
|
||||
}
|
||||
break;
|
||||
case AST_FUNC_DECL:
|
||||
if (to_func_decl(n)->m_info != nullptr) {
|
||||
to_func_decl(n)->m_info = alloc(func_decl_info, *(to_func_decl(n)->get_info()));
|
||||
to_func_decl(n)->m_info = alloc(func_decl_info, std::move(*(to_func_decl(n)->get_info())));
|
||||
to_func_decl(n)->m_info->init_eh(*this);
|
||||
}
|
||||
inc_array_ref(to_func_decl(n)->get_arity(), to_func_decl(n)->get_domain());
|
||||
|
@ -1992,7 +1992,7 @@ sort * ast_manager::substitute(sort* s, unsigned n, sort * const * src, sort * c
|
|||
return s;
|
||||
}
|
||||
decl_info dinfo(s->get_family_id(), s->get_decl_kind(), ps.size(), ps.data(), s->private_parameters());
|
||||
sort_info sinfo(dinfo, s->get_num_elements());
|
||||
sort_info sinfo(std::move(dinfo), s->get_num_elements());
|
||||
return mk_sort(s->get_name(), &sinfo);
|
||||
}
|
||||
|
||||
|
@ -2131,12 +2131,17 @@ bool ast_manager::coercion_needed(func_decl * decl, unsigned num_args, expr * co
|
|||
expr* ast_manager::coerce_to(expr* e, sort* s) {
|
||||
sort* se = e->get_sort();
|
||||
if (s != se && s->get_family_id() == arith_family_id && se->get_family_id() == arith_family_id) {
|
||||
if (s->get_decl_kind() == REAL_SORT) {
|
||||
if (s->get_decl_kind() == REAL_SORT)
|
||||
return mk_app(arith_family_id, OP_TO_REAL, e);
|
||||
}
|
||||
else {
|
||||
return mk_app(arith_family_id, OP_TO_INT, e);
|
||||
}
|
||||
else
|
||||
return mk_app(arith_family_id, OP_TO_INT, e);
|
||||
}
|
||||
if (s != se && s->get_family_id() == arith_family_id && is_bool(e)) {
|
||||
arith_util au(*this);
|
||||
if (s->get_decl_kind() == REAL_SORT)
|
||||
return mk_ite(e, au.mk_real(1), au.mk_real(0));
|
||||
else
|
||||
return mk_ite(e, au.mk_int(1), au.mk_int(0));
|
||||
}
|
||||
else {
|
||||
return e;
|
||||
|
@ -2231,7 +2236,7 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar
|
|||
std::ostringstream buffer;
|
||||
buffer << "Wrong number of arguments (" << num_args
|
||||
<< ") passed to function " << mk_pp(decl, *this);
|
||||
throw ast_exception(buffer.str());
|
||||
throw ast_exception(std::move(buffer).str());
|
||||
}
|
||||
app * r = nullptr;
|
||||
if (num_args == 1 && decl->is_chainable() && decl->get_arity() == 2) {
|
||||
|
|
|
@ -367,8 +367,8 @@ public:
|
|||
decl_info(family_id, k, num_parameters, parameters, private_parameters), m_num_elements(num_elements) {
|
||||
}
|
||||
|
||||
sort_info(decl_info const& di, sort_size const& num_elements) :
|
||||
decl_info(di), m_num_elements(num_elements) {}
|
||||
sort_info(decl_info && di, sort_size const& num_elements) :
|
||||
decl_info(std::move(di)), m_num_elements(num_elements) {}
|
||||
|
||||
bool is_infinite() const { return m_num_elements.is_infinite(); }
|
||||
bool is_very_big() const { return m_num_elements.is_very_big(); }
|
||||
|
|
|
@ -47,18 +47,14 @@ format * smt2_pp_environment::pp_fdecl_name(symbol const & s, unsigned & len, bo
|
|||
len = static_cast<unsigned>(str.length());
|
||||
return mk_string(m, str);
|
||||
}
|
||||
else if (s.is_numerical()) {
|
||||
std::string str = s.str();
|
||||
len = static_cast<unsigned>(str.length());
|
||||
return mk_string(m, str);
|
||||
}
|
||||
else if (!s.bare_str()) {
|
||||
else if (s.is_null()) {
|
||||
len = 4;
|
||||
return mk_string(m, "null");
|
||||
}
|
||||
else {
|
||||
len = static_cast<unsigned>(strlen(s.bare_str()));
|
||||
return mk_string(m, s.bare_str());
|
||||
std::string str = s.str();
|
||||
len = static_cast<unsigned>(str.length());
|
||||
return mk_string(m, str);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -170,12 +170,20 @@ void ast_translation::mk_func_decl(func_decl * f, frame & fr) {
|
|||
new_fi.set_injective(fi->is_injective());
|
||||
new_fi.set_skolem(fi->is_skolem());
|
||||
new_fi.set_idempotent(fi->is_idempotent());
|
||||
new_fi.set_lambda(fi->is_lambda());
|
||||
|
||||
new_f = m_to_manager.mk_func_decl(f->get_name(),
|
||||
f->get_arity(),
|
||||
new_domain,
|
||||
new_range,
|
||||
new_fi);
|
||||
|
||||
if (new_fi.is_lambda()) {
|
||||
quantifier* q = from().is_lambda_def(f);
|
||||
ast_translation tr(from(), to());
|
||||
quantifier* new_q = tr(q);
|
||||
to().add_lambda_def(new_f, new_q);
|
||||
}
|
||||
}
|
||||
TRACE("ast_translation",
|
||||
tout << f->get_name() << " "; if (fi) tout << *fi; tout << "\n";
|
||||
|
|
|
@ -886,8 +886,8 @@ app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
|
|||
}
|
||||
|
||||
sort * bv_util::mk_sort(unsigned bv_size) {
|
||||
parameter p[1] = { parameter(bv_size) };
|
||||
return m_manager.mk_sort(get_fid(), BV_SORT, 1, p);
|
||||
parameter p(bv_size);
|
||||
return m_manager.mk_sort(get_fid(), BV_SORT, 1, &p);
|
||||
}
|
||||
|
||||
unsigned bv_util::get_int2bv_size(parameter const& p) {
|
||||
|
|
|
@ -16,6 +16,7 @@ Author:
|
|||
|
||||
--*/
|
||||
#include "util/gparams.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/char_decl_plugin.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
@ -164,6 +165,14 @@ app* char_decl_plugin::mk_le(expr* a, expr* b) {
|
|||
unsigned v1 = 0, v2 = 0;
|
||||
if (a == b)
|
||||
return m_manager->mk_true();
|
||||
bv_util bv(*m_manager);
|
||||
if (bv.is_bv(a))
|
||||
return bv.mk_ule(a, b);
|
||||
arith_util arith(*m_manager);
|
||||
if (arith.is_int_real(a))
|
||||
return arith.mk_le(a, b);
|
||||
if (a->get_sort() != char_sort())
|
||||
throw default_exception("range comparison is only supported for bit-vectors, int, real and characters");
|
||||
bool c1 = is_const_char(a, v1);
|
||||
bool c2 = is_const_char(b, v2);
|
||||
if (c1 && c2)
|
||||
|
|
|
@ -69,8 +69,8 @@ namespace datatype {
|
|||
domain.push_back(a->instantiate(ps)->get_range());
|
||||
}
|
||||
sort_ref range = get_def().instantiate(ps);
|
||||
parameter pas[1] = { parameter(name()) };
|
||||
return func_decl_ref(m.mk_func_decl(u().get_family_id(), OP_DT_CONSTRUCTOR, 1, pas, domain.size(), domain.data(), range), m);
|
||||
parameter pas(name());
|
||||
return func_decl_ref(m.mk_func_decl(u().get_family_id(), OP_DT_CONSTRUCTOR, 1, &pas, domain.size(), domain.data(), range), m);
|
||||
}
|
||||
|
||||
func_decl_ref constructor::instantiate(sort* dt) const {
|
||||
|
@ -1052,8 +1052,8 @@ namespace datatype {
|
|||
func_decl * util::get_constructor_is(func_decl * con) {
|
||||
SASSERT(is_constructor(con));
|
||||
sort * datatype = con->get_range();
|
||||
parameter ps[1] = { parameter(con)};
|
||||
return m.mk_func_decl(fid(), OP_DT_IS, 1, ps, 1, &datatype);
|
||||
parameter ps(con);
|
||||
return m.mk_func_decl(fid(), OP_DT_IS, 1, &ps, 1, &datatype);
|
||||
}
|
||||
|
||||
func_decl * util::get_constructor_recognizer(func_decl * con) {
|
||||
|
|
|
@ -293,11 +293,12 @@ namespace euf {
|
|||
VERIFY(n->num_args() == 0 || !n->merge_enabled() || m_table.contains(n));
|
||||
}
|
||||
|
||||
void egraph::set_value(enode* n, lbool value) {
|
||||
void egraph::set_value(enode* n, lbool value, justification j) {
|
||||
if (n->value() == l_undef) {
|
||||
force_push();
|
||||
TRACE("euf", tout << bpp(n) << " := " << value << "\n";);
|
||||
n->set_value(value);
|
||||
n->m_lit_justification = j;
|
||||
m_updates.push_back(update_record(n, update_record::value_assignment()));
|
||||
}
|
||||
}
|
||||
|
@ -657,6 +658,7 @@ namespace euf {
|
|||
push_lca(n1->get_arg(1), n2->get_arg(0));
|
||||
return;
|
||||
}
|
||||
TRACE("euf_verbose", tout << bpp(n1) << " " << bpp(n2) << "\n");
|
||||
|
||||
for (unsigned i = 0; i < n1->num_args(); ++i)
|
||||
push_lca(n1->get_arg(i), n2->get_arg(i));
|
||||
|
@ -713,6 +715,15 @@ namespace euf {
|
|||
explain_todo(justifications);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j) {
|
||||
if (j.is_external())
|
||||
justifications.push_back(j.ext<T>());
|
||||
else if (j.is_congruence())
|
||||
push_congruence(a, b, j.is_commutative());
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void egraph::explain_eq(ptr_vector<T>& justifications, enode* a, enode* b) {
|
||||
SASSERT(a->get_root() == b->get_root());
|
||||
|
@ -746,11 +757,21 @@ namespace euf {
|
|||
void egraph::explain_todo(ptr_vector<T>& justifications) {
|
||||
for (unsigned i = 0; i < m_todo.size(); ++i) {
|
||||
enode* n = m_todo[i];
|
||||
if (n->m_target && !n->is_marked1()) {
|
||||
if (n->is_marked1())
|
||||
continue;
|
||||
if (n->m_target) {
|
||||
n->mark1();
|
||||
CTRACE("euf_verbose", m_display_justification, n->m_justification.display(tout << n->get_expr_id() << " = " << n->m_target->get_expr_id() << " ", m_display_justification) << "\n";);
|
||||
explain_eq(justifications, n, n->m_target, n->m_justification);
|
||||
}
|
||||
else if (!n->is_marked1() && n->value() != l_undef) {
|
||||
n->mark1();
|
||||
if (m.is_true(n->get_expr()) || m.is_false(n->get_expr()))
|
||||
continue;
|
||||
justification j = n->m_lit_justification;
|
||||
SASSERT(j.is_external());
|
||||
justifications.push_back(j.ext<T>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -226,12 +226,8 @@ namespace euf {
|
|||
void erase_from_table(enode* p);
|
||||
|
||||
template <typename T>
|
||||
void explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j) {
|
||||
if (j.is_external())
|
||||
justifications.push_back(j.ext<T>());
|
||||
else if (j.is_congruence())
|
||||
push_congruence(a, b, j.is_commutative());
|
||||
}
|
||||
void explain_eq(ptr_vector<T>& justifications, enode* a, enode* b, justification const& j);
|
||||
|
||||
template <typename T>
|
||||
void explain_todo(ptr_vector<T>& justifications);
|
||||
|
||||
|
@ -295,7 +291,7 @@ namespace euf {
|
|||
void add_th_var(enode* n, theory_var v, theory_id id);
|
||||
void set_th_propagates_diseqs(theory_id id);
|
||||
void set_merge_enabled(enode* n, bool enable_merge);
|
||||
void set_value(enode* n, lbool value);
|
||||
void set_value(enode* n, lbool value, justification j);
|
||||
void set_bool_var(enode* n, unsigned v) { n->set_bool_var(v); }
|
||||
void set_relevant(enode* n);
|
||||
void set_default_relevant(bool b) { m_default_relevant = b; }
|
||||
|
|
|
@ -63,6 +63,7 @@ namespace euf {
|
|||
enode* m_cg = nullptr;
|
||||
th_var_list m_th_vars;
|
||||
justification m_justification;
|
||||
justification m_lit_justification;
|
||||
unsigned m_num_args = 0;
|
||||
signed char m_lbl_hash = -1; // It is different from -1, if enode is used in a pattern
|
||||
approx_set m_lbls;
|
||||
|
@ -133,6 +134,7 @@ namespace euf {
|
|||
void del_th_var(theory_id id) { m_th_vars.del_var(id); }
|
||||
void set_merge_enabled(bool m) { m_merge_enabled = m; }
|
||||
void set_value(lbool v) { m_value = v; }
|
||||
void set_justification(justification j) { m_justification = j; }
|
||||
void set_is_equality() { m_is_equality = true; }
|
||||
void set_bool_var(sat::bool_var v) { m_bool_var = v; }
|
||||
|
||||
|
|
|
@ -33,11 +33,9 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
unsigned arity, sort * const * domain, sort * range) {
|
||||
SASSERT(m_manager);
|
||||
ast_manager& m = *m_manager;
|
||||
for (unsigned i = 0; i < arity; ++i) {
|
||||
if (!m.is_bool(domain[i])) {
|
||||
m.raise_exception("invalid non-Boolean sort applied to 'at-most'");
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < arity; ++i)
|
||||
if (!m.is_bool(domain[i]))
|
||||
m.raise_exception("invalid non-Boolean sort applied to Pseudo-Boolean relation");
|
||||
symbol sym;
|
||||
switch(k) {
|
||||
case OP_AT_LEAST_K: sym = m_at_least_sym; break;
|
||||
|
@ -50,9 +48,8 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
switch(k) {
|
||||
case OP_AT_LEAST_K:
|
||||
case OP_AT_MOST_K: {
|
||||
if (num_parameters != 1 || !parameters[0].is_int() || parameters[0].get_int() < 0) {
|
||||
if (num_parameters != 1 || !parameters[0].is_int() || parameters[0].get_int() < 0)
|
||||
m.raise_exception("function expects one non-negative integer parameter");
|
||||
}
|
||||
func_decl_info info(m_family_id, k, 1, parameters);
|
||||
return m.mk_func_decl(sym, arity, domain, m.mk_bool_sort(), info);
|
||||
}
|
||||
|
@ -93,11 +90,11 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
|
||||
void pb_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
|
||||
if (logic == symbol::null || logic == "QF_FD" || logic == "ALL" || logic == "HORN") {
|
||||
op_names.push_back(builtin_name(m_at_most_sym.bare_str(), OP_AT_MOST_K));
|
||||
op_names.push_back(builtin_name(m_at_least_sym.bare_str(), OP_AT_LEAST_K));
|
||||
op_names.push_back(builtin_name(m_pble_sym.bare_str(), OP_PB_LE));
|
||||
op_names.push_back(builtin_name(m_pbge_sym.bare_str(), OP_PB_GE));
|
||||
op_names.push_back(builtin_name(m_pbeq_sym.bare_str(), OP_PB_EQ));
|
||||
op_names.push_back(builtin_name(m_at_most_sym.str(), OP_AT_MOST_K));
|
||||
op_names.push_back(builtin_name(m_at_least_sym.str(), OP_AT_LEAST_K));
|
||||
op_names.push_back(builtin_name(m_pble_sym.str(), OP_PB_LE));
|
||||
op_names.push_back(builtin_name(m_pbge_sym.str(), OP_PB_GE));
|
||||
op_names.push_back(builtin_name(m_pbeq_sym.str(), OP_PB_EQ));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -225,6 +225,11 @@ namespace recfun {
|
|||
m_vars.append(n_vars, vars);
|
||||
m_rhs = rhs;
|
||||
|
||||
if (!is_macro)
|
||||
for (expr* e : subterms::all(m_rhs))
|
||||
if (is_lambda(e))
|
||||
throw default_exception("recursive definitions with lambdas are not supported");
|
||||
|
||||
expr_ref_vector conditions(m);
|
||||
|
||||
// is the function a macro (unconditional body)?
|
||||
|
@ -233,6 +238,8 @@ namespace recfun {
|
|||
add_case(name, 0, conditions, rhs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// analyze control flow of `rhs`, accumulating guards and
|
||||
// rebuilding a `ite`-free RHS on the fly for each path in `rhs`.
|
||||
|
|
|
@ -9,6 +9,7 @@ z3_add_component(rewriter
|
|||
bv_elim.cpp
|
||||
bv_rewriter.cpp
|
||||
cached_var_subst.cpp
|
||||
char_rewriter.cpp
|
||||
datatype_rewriter.cpp
|
||||
der.cpp
|
||||
distribute_forall.cpp
|
||||
|
|
|
@ -37,6 +37,7 @@ void bv_rewriter::updt_local_params(params_ref const & _p) {
|
|||
m_extract_prop = p.bv_extract_prop();
|
||||
m_ite2id = p.bv_ite2id();
|
||||
m_le_extra = p.bv_le_extra();
|
||||
m_le2extract = p.bv_le2extract();
|
||||
set_sort_sums(p.bv_sort_ac());
|
||||
}
|
||||
|
||||
|
@ -196,11 +197,11 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons
|
|||
SASSERT(num_args == 1);
|
||||
return mk_bit2bool(args[0], f->get_parameter(0).get_int(), result);
|
||||
case OP_BSMUL_NO_OVFL:
|
||||
return mk_bvsmul_no_overflow(num_args, args, result);
|
||||
return mk_bvsmul_no_overflow(num_args, args, true, result);
|
||||
case OP_BSMUL_NO_UDFL:
|
||||
return mk_bvsmul_no_overflow(num_args, args, false, result);
|
||||
case OP_BUMUL_NO_OVFL:
|
||||
return mk_bvumul_no_overflow(num_args, args, result);
|
||||
case OP_BSMUL_NO_UDFL:
|
||||
return mk_bvsmul_no_underflow(num_args, args, result);
|
||||
default:
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
@ -577,7 +578,7 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref
|
|||
result = m().mk_eq(a, m_util.mk_numeral(numeral(0), bv_sz));
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else if (first_non_zero < bv_sz - 1) {
|
||||
else if (first_non_zero < bv_sz - 1 && m_le2extract) {
|
||||
result = m().mk_and(m().mk_eq(m_mk_extract(bv_sz - 1, first_non_zero + 1, a), m_util.mk_numeral(numeral(0), bv_sz - first_non_zero - 1)),
|
||||
m_util.mk_ule(m_mk_extract(first_non_zero, 0, a), m_mk_extract(first_non_zero, 0, b)));
|
||||
return BR_REWRITE3;
|
||||
|
@ -2802,30 +2803,51 @@ br_status bv_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & resu
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status bv_rewriter::mk_bvsmul_no_overflow(unsigned num, expr * const * args, expr_ref & result) {
|
||||
br_status bv_rewriter::mk_distinct(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
if (num_args <= 1) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
unsigned sz = get_bv_size(args[0]);
|
||||
// check if num_args > 2^sz
|
||||
if (sz >= 32)
|
||||
return BR_FAILED;
|
||||
if (num_args <= 1u << sz)
|
||||
return BR_FAILED;
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
br_status bv_rewriter::mk_bvsmul_no_overflow(unsigned num, expr * const * args, bool is_overflow, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
unsigned bv_sz;
|
||||
rational a0_val, a1_val;
|
||||
|
||||
bool is_num1 = is_numeral(args[0], a0_val, bv_sz);
|
||||
bool is_num2 = is_numeral(args[1], a1_val, bv_sz);
|
||||
if (is_num1 && (a0_val.is_zero() || a0_val.is_one())) {
|
||||
|
||||
if (is_num1 && (a0_val.is_zero() || (bv_sz != 1 && a0_val.is_one()))) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num2 && (a1_val.is_zero() || a1_val.is_one())) {
|
||||
if (is_num2 && (a1_val.is_zero() || (bv_sz != 1 && a1_val.is_one()))) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (!is_num1 || !is_num2)
|
||||
return BR_FAILED;
|
||||
|
||||
rational lim = rational::power_of_two(bv_sz);
|
||||
|
||||
bool sign0 = m_util.has_sign_bit(a0_val, bv_sz);
|
||||
bool sign1 = m_util.has_sign_bit(a1_val, bv_sz);
|
||||
if (sign0) a0_val = rational::power_of_two(bv_sz) - a0_val;
|
||||
if (sign1) a1_val = rational::power_of_two(bv_sz) - a1_val;
|
||||
rational lim = rational::power_of_two(bv_sz-1);
|
||||
rational r = a0_val * a1_val;
|
||||
bool sign1 = m_util.has_sign_bit(a0_val, bv_sz);
|
||||
bool sign2 = m_util.has_sign_bit(a1_val, bv_sz);
|
||||
result = m().mk_bool_val((sign1 != sign2) || r < lim);
|
||||
if (is_overflow)
|
||||
result = m().mk_bool_val(sign0 != sign1 || r < lim);
|
||||
else
|
||||
result = m().mk_bool_val(sign0 == sign1 || r <= lim);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
@ -2855,36 +2877,5 @@ br_status bv_rewriter::mk_bvumul_no_overflow(unsigned num, expr * const * args,
|
|||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status bv_rewriter::mk_bvsmul_no_underflow(unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
unsigned bv_sz;
|
||||
rational a0_val, a1_val;
|
||||
|
||||
bool is_num1 = is_numeral(args[0], a0_val, bv_sz);
|
||||
bool is_num2 = is_numeral(args[1], a1_val, bv_sz);
|
||||
if (is_num1 && (a0_val.is_zero() || a0_val.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
if (is_num2 && (a1_val.is_zero() || a1_val.is_one())) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
if (is_num1 && is_num2) {
|
||||
rational ul = rational::power_of_two(bv_sz);
|
||||
rational lim = rational::power_of_two(bv_sz-1);
|
||||
if (a0_val >= lim) a0_val -= ul;
|
||||
if (a1_val >= lim) a1_val -= ul;
|
||||
rational mr = a0_val * a1_val;
|
||||
rational neg_lim = -lim;
|
||||
TRACE("bv_rewriter_bvsmul_no_underflow", tout << "a0:" << a0_val << " a1:" << a1_val << " mr:" << mr << " neg_lim:" << neg_lim << std::endl;);
|
||||
result = m().mk_bool_val(mr >= neg_lim);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
template class poly_rewriter<bv_rewriter_core>;
|
||||
|
|
|
@ -62,6 +62,7 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
|
|||
bool m_extract_prop;
|
||||
bool m_bvnot_simpl;
|
||||
bool m_le_extra;
|
||||
bool m_le2extract;
|
||||
|
||||
bool is_zero_bit(expr * x, unsigned idx);
|
||||
|
||||
|
@ -134,9 +135,8 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
|
|||
br_status mk_blast_eq_value(expr * lhs, expr * rhs, expr_ref & result);
|
||||
br_status mk_eq_concat(expr * lhs, expr * rhs, expr_ref & result);
|
||||
br_status mk_mkbv(unsigned num, expr * const * args, expr_ref & result);
|
||||
br_status mk_bvsmul_no_overflow(unsigned num, expr * const * args, expr_ref & result);
|
||||
br_status mk_bvsmul_no_overflow(unsigned num, expr * const * args, bool is_overflow, expr_ref & result);
|
||||
br_status mk_bvumul_no_overflow(unsigned num, expr * const * args, expr_ref & result);
|
||||
br_status mk_bvsmul_no_underflow(unsigned num, expr * const * args, expr_ref & result);
|
||||
bool is_minus_one_times_t(expr * arg);
|
||||
void mk_t1_add_t2_eq_c(expr * t1, expr * t2, expr * c, expr_ref & result);
|
||||
|
||||
|
@ -180,7 +180,8 @@ public:
|
|||
|
||||
bool is_urem_any(expr * e, expr * & dividend, expr * & divisor);
|
||||
br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
|
||||
br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & resul);
|
||||
br_status mk_ite_core(expr * c, expr * t, expr * e, expr_ref & result);
|
||||
br_status mk_distinct(unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
bool hi_div0() const { return m_hi_div0; }
|
||||
|
||||
|
|
73
src/ast/rewriter/char_rewriter.cpp
Normal file
73
src/ast/rewriter/char_rewriter.cpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
char_rewriter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for character constraints
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2015-12-5
|
||||
|
||||
--*/
|
||||
|
||||
#include "util/debug.h"
|
||||
#include "ast/rewriter/char_rewriter.h"
|
||||
#include "ast/bv_decl_plugin.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
|
||||
|
||||
char_rewriter::char_rewriter(ast_manager& m):
|
||||
m(m) {
|
||||
m_char = static_cast<char_decl_plugin*>(m.get_plugin(m.mk_family_id("char")));
|
||||
}
|
||||
|
||||
family_id char_rewriter::get_fid() {
|
||||
return m_char->get_family_id();
|
||||
}
|
||||
|
||||
br_status char_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
SASSERT(f->get_family_id() == get_fid());
|
||||
br_status st = BR_FAILED;
|
||||
switch (f->get_decl_kind()) {
|
||||
case OP_CHAR_CONST:
|
||||
break;
|
||||
case OP_CHAR_LE:
|
||||
break;
|
||||
case OP_CHAR_TO_INT:
|
||||
st = mk_char_to_int(args[0], result);
|
||||
break;
|
||||
case OP_CHAR_TO_BV:
|
||||
break;
|
||||
case OP_CHAR_FROM_BV:
|
||||
st = mk_char_from_bv(args[0], result);
|
||||
break;
|
||||
case OP_CHAR_IS_DIGIT:
|
||||
break;
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
br_status char_rewriter::mk_char_from_bv(expr* e, expr_ref& result) {
|
||||
bv_util bv(m);
|
||||
rational n;
|
||||
if (bv.is_numeral(e, n) && n.is_unsigned() && n <= m_char->max_char()) {
|
||||
result = m_char->mk_char(n.get_unsigned());
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status char_rewriter::mk_char_to_int(expr* e, expr_ref& result) {
|
||||
unsigned n = 0;
|
||||
if (m_char->is_const_char(e, n)) {
|
||||
arith_util arith(m);
|
||||
result = arith.mk_int(n);
|
||||
return BR_DONE;
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
57
src/ast/rewriter/char_rewriter.h
Normal file
57
src/ast/rewriter/char_rewriter.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
char_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Basic rewriting rules for characters constraints.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2022-03-10
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "ast/char_decl_plugin.h"
|
||||
#include "ast/rewriter/rewriter_types.h"
|
||||
#include "util/params.h"
|
||||
#include "util/lbool.h"
|
||||
|
||||
|
||||
/**
|
||||
\brief Cheap rewrite rules for character constraints
|
||||
*/
|
||||
class char_rewriter {
|
||||
ast_manager& m;
|
||||
char_decl_plugin* m_char;
|
||||
|
||||
br_status mk_char_from_bv(expr* e, expr_ref& result);
|
||||
|
||||
br_status mk_char_to_int(expr* e, expr_ref& result);
|
||||
|
||||
public:
|
||||
|
||||
char_rewriter(ast_manager& m);
|
||||
|
||||
family_id get_fid();
|
||||
|
||||
br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);
|
||||
|
||||
expr_ref mk_app(func_decl* f, expr_ref_vector const& args) { return mk_app(f, args.size(), args.data()); }
|
||||
|
||||
expr_ref mk_app(func_decl* f, unsigned n, expr* const* args) {
|
||||
expr_ref result(m);
|
||||
if (f->get_family_id() != get_fid() ||
|
||||
BR_FAILED == mk_app_core(f, n, args, result))
|
||||
result = m.mk_app(f, n, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -23,7 +23,8 @@ Revision History:
|
|||
|
||||
expr_ref func_decl_replace::operator()(expr* e) {
|
||||
m_todo.push_back(e);
|
||||
|
||||
m_refs.push_back(e);
|
||||
|
||||
while (!m_todo.empty()) {
|
||||
expr* a = m_todo.back(), *b;
|
||||
if (m_cache.contains(a)) {
|
||||
|
|
|
@ -979,9 +979,8 @@ expr* poly_rewriter<Config>::merge_muls(expr* x, expr* y) {
|
|||
|
||||
template<typename Config>
|
||||
bool poly_rewriter<Config>::hoist_ite(expr_ref& e) {
|
||||
if (!m_hoist_ite) {
|
||||
if (!m_hoist_ite)
|
||||
return false;
|
||||
}
|
||||
obj_hashtable<expr> shared;
|
||||
ptr_buffer<expr> adds;
|
||||
expr_ref_vector bs(m()), pinned(m());
|
||||
|
|
|
@ -936,22 +936,13 @@ expr_ref seq_rewriter::mk_seq_last(expr* t) {
|
|||
}
|
||||
|
||||
/*
|
||||
* In general constructs substring(t,0,|t|-1) but if t = substring(s,0,k) then simplifies to substring(s,0,k-1)
|
||||
* This method assumes that |t| > 0, thus, if t = substring(s,0,k) then k > 0 so substring(s,0,k-1) is correct.
|
||||
* In general constructs substring(t,0,|t|-1)
|
||||
* Incorrect comment: "but if t = substring(s,0,k) then simplifies to substring(s,0,k-1).
|
||||
* This method assumes that |t| > 0, thus, if t = substring(s,0,k) then k > 0 so substring(s,0,k-1) is correct."
|
||||
* No: if k > |s| then substring(s,0,k) = substring(s,0,k-1)
|
||||
*/
|
||||
expr_ref seq_rewriter::mk_seq_butlast(expr* t) {
|
||||
expr_ref result(m());
|
||||
expr* s, * j, * k;
|
||||
rational v;
|
||||
if (str().is_extract(t, s, j, k) && m_autil.is_numeral(j, v) && v.is_zero()) {
|
||||
expr_ref_vector k_min_1(m());
|
||||
k_min_1.push_back(k);
|
||||
k_min_1.push_back(minus_one());
|
||||
result = str().mk_substr(s, j, m_autil.mk_add_simplify(k_min_1));
|
||||
}
|
||||
else
|
||||
result = str().mk_substr(t, zero(), m_autil.mk_sub(str().mk_length(t), one()));
|
||||
return result;
|
||||
return expr_ref(str().mk_substr(t, zero(), m_autil.mk_sub(str().mk_length(t), one())), m());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3128,8 +3119,8 @@ void seq_rewriter::mk_antimirov_deriv_rec(expr* e, expr* r, expr* path, expr_ref
|
|||
expr_ref range(m());
|
||||
expr_ref psi(m().mk_false(), m());
|
||||
if (str().is_unit_string(r1, c1) && str().is_unit_string(r2, c2)) {
|
||||
SASSERT(u().is_char(c1));
|
||||
SASSERT(u().is_char(c2));
|
||||
// SASSERT(u().is_char(c1));
|
||||
// SASSERT(u().is_char(c2));
|
||||
// case: c1 <= e <= c2
|
||||
range = simplify_path(e, m().mk_and(u().mk_le(c1, e), u().mk_le(e, c2)));
|
||||
psi = simplify_path(e, m().mk_and(path, range));
|
||||
|
@ -5531,44 +5522,37 @@ lbool seq_rewriter::eq_length(expr* x, expr* y) {
|
|||
maximal length (the sequence is bounded).
|
||||
*/
|
||||
|
||||
bool seq_rewriter::min_length(expr* e, unsigned& len) {
|
||||
bool seq_rewriter::min_length(unsigned sz, expr* const* ss, unsigned& len) {
|
||||
ptr_buffer<expr> es;
|
||||
for (unsigned i = 0; i < sz; ++i)
|
||||
es.push_back(ss[i]);
|
||||
zstring s;
|
||||
len = 0;
|
||||
if (str().is_unit(e)) {
|
||||
len = 1;
|
||||
return true;
|
||||
bool bounded = true;
|
||||
while (!es.empty()) {
|
||||
expr* e = es.back();
|
||||
es.pop_back();
|
||||
if (str().is_unit(e))
|
||||
len += 1;
|
||||
else if (str().is_empty(e))
|
||||
continue;
|
||||
else if (str().is_string(e, s))
|
||||
len += s.length();
|
||||
else if (str().is_concat(e))
|
||||
for (expr* arg : *to_app(e))
|
||||
es.push_back(arg);
|
||||
else
|
||||
bounded = false;
|
||||
}
|
||||
else if (str().is_empty(e)) {
|
||||
len = 0;
|
||||
return true;
|
||||
}
|
||||
else if (str().is_string(e, s)) {
|
||||
len = s.length();
|
||||
return true;
|
||||
}
|
||||
else if (str().is_concat(e)) {
|
||||
unsigned min_l = 0;
|
||||
bool bounded = true;
|
||||
for (expr* arg : *to_app(e)) {
|
||||
if (!min_length(arg, min_l))
|
||||
bounded = false;
|
||||
len += min_l;
|
||||
}
|
||||
return bounded;
|
||||
}
|
||||
return false;
|
||||
return bounded;
|
||||
}
|
||||
|
||||
bool seq_rewriter::min_length(expr* e, unsigned& len) {
|
||||
return min_length(1, &e, len);
|
||||
}
|
||||
|
||||
bool seq_rewriter::min_length(expr_ref_vector const& es, unsigned& len) {
|
||||
unsigned min_l = 0;
|
||||
bool bounded = true;
|
||||
len = 0;
|
||||
for (expr* arg : es) {
|
||||
if (!min_length(arg, min_l))
|
||||
bounded = false;
|
||||
len += min_l;
|
||||
}
|
||||
return bounded;
|
||||
return min_length(es.size(), es.data(), len);
|
||||
}
|
||||
|
||||
bool seq_rewriter::max_length(expr* e, rational& len) {
|
||||
|
|
|
@ -322,6 +322,7 @@ class seq_rewriter {
|
|||
bool reduce_eq_empty(expr* l, expr* r, expr_ref& result);
|
||||
bool min_length(expr_ref_vector const& es, unsigned& len);
|
||||
bool min_length(expr* e, unsigned& len);
|
||||
bool min_length(unsigned sz, expr* const* es, unsigned& len);
|
||||
bool max_length(expr* e, rational& len);
|
||||
lbool eq_length(expr* x, expr* y);
|
||||
expr* concat_non_empty(expr_ref_vector& es);
|
||||
|
|
|
@ -21,6 +21,7 @@ Notes:
|
|||
#include "ast/rewriter/bool_rewriter.h"
|
||||
#include "ast/rewriter/arith_rewriter.h"
|
||||
#include "ast/rewriter/bv_rewriter.h"
|
||||
#include "ast/rewriter/char_rewriter.h"
|
||||
#include "ast/rewriter/datatype_rewriter.h"
|
||||
#include "ast/rewriter/array_rewriter.h"
|
||||
#include "ast/rewriter/fpa_rewriter.h"
|
||||
|
@ -48,6 +49,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
dl_rewriter m_dl_rw;
|
||||
pb_rewriter m_pb_rw;
|
||||
seq_rewriter m_seq_rw;
|
||||
char_rewriter m_char_rw;
|
||||
recfun_rewriter m_rec_rw;
|
||||
arith_util m_a_util;
|
||||
bv_util m_bv_util;
|
||||
|
@ -58,7 +60,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
expr_substitution * m_subst = nullptr;
|
||||
unsigned long long m_max_memory; // in bytes
|
||||
bool m_new_subst = false;
|
||||
unsigned m_max_steps = UINT_MAX;
|
||||
unsigned m_max_steps = UINT_MAX;
|
||||
bool m_pull_cheap_ite = true;
|
||||
bool m_flat = true;
|
||||
bool m_cache_all = false;
|
||||
|
@ -178,7 +180,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
// theory dispatch for =
|
||||
SASSERT(num == 2);
|
||||
family_id s_fid = args[0]->get_sort()->get_family_id();
|
||||
if (s_fid == m_a_rw.get_fid())
|
||||
if (s_fid == m_a_rw.get_fid())
|
||||
st = m_a_rw.mk_eq_core(args[0], args[1], result);
|
||||
else if (s_fid == m_bv_rw.get_fid())
|
||||
st = m_bv_rw.mk_eq_core(args[0], args[1], result);
|
||||
|
@ -191,10 +193,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
else if (s_fid == m_seq_rw.get_fid())
|
||||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (k == OP_EQ) {
|
||||
SASSERT(num == 2);
|
||||
return st;
|
||||
st = apply_tamagotchi(args[0], args[1], result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
|
@ -208,16 +207,21 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
return st;
|
||||
}
|
||||
if ((k == OP_AND || k == OP_OR) && m_seq_rw.u().has_re()) {
|
||||
st = m_seq_rw.mk_bool_app(f, num, args, result);
|
||||
st = m_seq_rw.mk_bool_app(f, num, args, result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (k == OP_EQ && m_seq_rw.u().has_seq() && is_app(args[0]) &&
|
||||
if (k == OP_EQ && m_seq_rw.u().has_seq() && is_app(args[0]) &&
|
||||
to_app(args[0])->get_family_id() == m_seq_rw.get_fid()) {
|
||||
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
if (k == OP_DISTINCT && num > 0 && m_bv_rw.is_bv(args[0])) {
|
||||
st = m_bv_rw.mk_distinct(num, args, result);
|
||||
if (st != BR_FAILED)
|
||||
return st;
|
||||
}
|
||||
|
||||
return m_b_rw.mk_app_core(f, num, args, result);
|
||||
}
|
||||
|
@ -247,6 +251,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
return m_pb_rw.mk_app_core(f, num, args, result);
|
||||
if (fid == m_seq_rw.get_fid())
|
||||
return m_seq_rw.mk_app_core(f, num, args, result);
|
||||
if (fid == m_char_rw.get_fid())
|
||||
return m_char_rw.mk_app_core(f, num, args, result);
|
||||
if (fid == m_rec_rw.get_fid())
|
||||
return m_rec_rw.mk_app_core(f, num, args, result);
|
||||
return BR_FAILED;
|
||||
|
@ -295,6 +301,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
bool is_ite_value_tree(expr * t) {
|
||||
if (!m().is_ite(t))
|
||||
return false;
|
||||
if (t->get_ref_count() != 1)
|
||||
return false;
|
||||
ptr_buffer<app> todo;
|
||||
todo.push_back(to_app(t));
|
||||
while (!todo.empty()) {
|
||||
|
@ -303,12 +311,12 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
expr * arg1 = ite->get_arg(1);
|
||||
expr * arg2 = ite->get_arg(2);
|
||||
|
||||
if (m().is_ite(arg1) && arg1->get_ref_count() == 1) // do not apply on shared terms, since it may blowup
|
||||
if (m().is_ite(arg1) && arg1->get_ref_count() == 1) // do not apply on shared terms, since it may blow up
|
||||
todo.push_back(to_app(arg1));
|
||||
else if (!m().is_value(arg1))
|
||||
return false;
|
||||
|
||||
if (m().is_ite(arg2) && arg2->get_ref_count() == 1) // do not apply on shared terms, since it may blowup
|
||||
if (m().is_ite(arg2) && arg2->get_ref_count() == 1) // do not apply on shared terms, since it may blow up
|
||||
todo.push_back(to_app(arg2));
|
||||
else if (!m().is_value(arg2))
|
||||
return false;
|
||||
|
@ -319,7 +327,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
br_status pull_ite(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
if (num == 2 && m().is_bool(f->get_range()) && !m().is_bool(args[0])) {
|
||||
if (m().is_ite(args[0])) {
|
||||
if (m().is_value(args[1]))
|
||||
if (m().is_value(args[1]) && args[0]->get_ref_count() == 1)
|
||||
return pull_ite_core<false>(f, to_app(args[0]), to_app(args[1]), result);
|
||||
if (m().is_ite(args[1]) && to_app(args[0])->get_arg(0) == to_app(args[1])->get_arg(0)) {
|
||||
// (p (ite C A1 B1) (ite C A2 B2)) --> (ite (p A1 A2) (p B1 B2))
|
||||
|
@ -329,17 +337,17 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
return BR_REWRITE2;
|
||||
}
|
||||
}
|
||||
if (m().is_ite(args[1]) && m().is_value(args[0]))
|
||||
if (m().is_ite(args[1]) && m().is_value(args[0]) && args[1]->get_ref_count() == 1)
|
||||
return pull_ite_core<true>(f, to_app(args[1]), to_app(args[0]), result);
|
||||
}
|
||||
family_id fid = f->get_family_id();
|
||||
if (num == 2 && (fid == m().get_basic_family_id() || fid == m_a_rw.get_fid() || fid == m_bv_rw.get_fid())) {
|
||||
// (f v3 (ite c v1 v2)) --> (ite v (f v3 v1) (f v3 v2))
|
||||
if (m().is_value(args[0]) && is_ite_value_tree(args[1]))
|
||||
if (m().is_value(args[0]) && is_ite_value_tree(args[1]))
|
||||
return pull_ite_core<true>(f, to_app(args[1]), to_app(args[0]), result);
|
||||
|
||||
// (f (ite c v1 v2) v3) --> (ite v (f v1 v3) (f v2 v3))
|
||||
if (m().is_value(args[1]) && is_ite_value_tree(args[0]))
|
||||
if (m().is_value(args[1]) && is_ite_value_tree(args[0]))
|
||||
return pull_ite_core<false>(f, to_app(args[0]), to_app(args[1]), result);
|
||||
}
|
||||
return BR_FAILED;
|
||||
|
@ -800,6 +808,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
|||
m_dl_rw(m),
|
||||
m_pb_rw(m),
|
||||
m_seq_rw(m),
|
||||
m_char_rw(m),
|
||||
m_rec_rw(m),
|
||||
m_a_util(m),
|
||||
m_bv_util(m),
|
||||
|
|
|
@ -1053,6 +1053,12 @@ sort* seq_util::rex::to_seq(sort* re) {
|
|||
return to_sort(re->get_parameter(0).get_ast());
|
||||
}
|
||||
|
||||
app* seq_util::rex::mk_power(expr* r, unsigned n) {
|
||||
parameter param(n);
|
||||
return m.mk_app(m_fid, OP_RE_POWER, 1, ¶m, 1, &r);
|
||||
}
|
||||
|
||||
|
||||
app* seq_util::rex::mk_loop(expr* r, unsigned lo) {
|
||||
parameter param(lo);
|
||||
return m.mk_app(m_fid, OP_RE_LOOP, 1, ¶m, 1, &r);
|
||||
|
|
|
@ -502,6 +502,7 @@ public:
|
|||
app* mk_star(expr* r) { return m.mk_app(m_fid, OP_RE_STAR, r); }
|
||||
app* mk_plus(expr* r) { return m.mk_app(m_fid, OP_RE_PLUS, r); }
|
||||
app* mk_opt(expr* r) { return m.mk_app(m_fid, OP_RE_OPTION, r); }
|
||||
app* mk_power(expr* r, unsigned n);
|
||||
app* mk_loop(expr* r, unsigned lo);
|
||||
app* mk_loop(expr* r, unsigned lo, unsigned hi);
|
||||
expr* mk_loop_proper(expr* r, unsigned lo, unsigned hi);
|
||||
|
|
|
@ -61,11 +61,11 @@ func_decl * special_relations_decl_plugin::mk_func_decl(
|
|||
|
||||
void special_relations_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
|
||||
if (logic == symbol::null) {
|
||||
op_names.push_back(builtin_name(m_po.bare_str(), OP_SPECIAL_RELATION_PO));
|
||||
op_names.push_back(builtin_name(m_lo.bare_str(), OP_SPECIAL_RELATION_LO));
|
||||
op_names.push_back(builtin_name(m_plo.bare_str(), OP_SPECIAL_RELATION_PLO));
|
||||
op_names.push_back(builtin_name(m_to.bare_str(), OP_SPECIAL_RELATION_TO));
|
||||
op_names.push_back(builtin_name(m_tc.bare_str(), OP_SPECIAL_RELATION_TC));
|
||||
op_names.push_back(builtin_name(m_po.str(), OP_SPECIAL_RELATION_PO));
|
||||
op_names.push_back(builtin_name(m_lo.str(), OP_SPECIAL_RELATION_LO));
|
||||
op_names.push_back(builtin_name(m_plo.str(), OP_SPECIAL_RELATION_PLO));
|
||||
op_names.push_back(builtin_name(m_to.str(), OP_SPECIAL_RELATION_TO));
|
||||
op_names.push_back(builtin_name(m_tc.str(), OP_SPECIAL_RELATION_TC));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
cmd * c = ctx.find_cmd(s);
|
||||
if (c == nullptr) {
|
||||
std::string err_msg("unknown command '");
|
||||
err_msg = err_msg + s.bare_str() + "'";
|
||||
err_msg = err_msg + s.str() + "'";
|
||||
throw cmd_exception(std::move(err_msg));
|
||||
}
|
||||
m_cmds.push_back(s);
|
||||
|
@ -817,9 +817,9 @@ public:
|
|||
sort_ref range(ctx.m());
|
||||
array_sort_args.push_back(m_f->get_range());
|
||||
range = array_sort->instantiate(ctx.pm(), array_sort_args.size(), array_sort_args.data());
|
||||
parameter p[1] = { parameter(m_f) };
|
||||
parameter p(m_f);
|
||||
func_decl_ref new_map(ctx.m());
|
||||
new_map = ctx.m().mk_func_decl(get_array_fid(ctx), OP_ARRAY_MAP, 1, p, domain.size(), domain.data(), range.get());
|
||||
new_map = ctx.m().mk_func_decl(get_array_fid(ctx), OP_ARRAY_MAP, 1, &p, domain.size(), domain.data(), range.get());
|
||||
if (new_map == 0)
|
||||
throw cmd_exception("invalid array map operator");
|
||||
ctx.insert(m_name, new_map);
|
||||
|
|
|
@ -1636,6 +1636,7 @@ void cmd_context::pop(unsigned n) {
|
|||
restore_aux_pdecls(s.m_aux_pdecls_lim);
|
||||
restore_assertions(s.m_assertions_lim);
|
||||
restore_psort_inst(s.m_psort_inst_stack_lim);
|
||||
m_dt_eh.get()->reset();
|
||||
m_mcs.shrink(m_mcs.size() - n);
|
||||
m_scopes.shrink(new_lvl);
|
||||
if (!m_global_decls)
|
||||
|
@ -1815,6 +1816,9 @@ void cmd_context::display_model(model_ref& mdl) {
|
|||
}
|
||||
|
||||
void cmd_context::add_declared_functions(model& mdl) {
|
||||
model_params p;
|
||||
if (!p.user_functions())
|
||||
return;
|
||||
for (auto const& kv : m_func_decls) {
|
||||
func_decl* f = kv.m_value.first();
|
||||
if (f->get_family_id() == null_family_id && !mdl.has_interpretation(f)) {
|
||||
|
|
|
@ -267,6 +267,7 @@ protected:
|
|||
cmd_context & m_owner;
|
||||
datatype_util m_dt_util;
|
||||
public:
|
||||
void reset() { m_dt_util.reset(); }
|
||||
dt_eh(cmd_context & owner);
|
||||
~dt_eh() override;
|
||||
void operator()(sort * dt, pdecl* pd) override;
|
||||
|
|
|
@ -57,6 +57,8 @@ public:
|
|||
|
||||
void execute(cmd_context & ctx) override {
|
||||
model_ref md;
|
||||
if (ctx.ignore_check())
|
||||
return;
|
||||
if (!ctx.is_model_available(md))
|
||||
throw cmd_exception("model is not available");
|
||||
if (!m_target)
|
||||
|
|
|
@ -156,8 +156,8 @@ public:
|
|||
return false;
|
||||
return m_sort == static_cast<psort_sort const *>(other)->m_sort;
|
||||
}
|
||||
void display(std::ostream & out) const override {
|
||||
out << m_sort->get_name();
|
||||
std::ostream& display(std::ostream & out) const override {
|
||||
return out << m_sort->get_name();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -180,8 +180,8 @@ public:
|
|||
get_num_params() == other->get_num_params() &&
|
||||
m_idx == static_cast<psort_var const *>(other)->m_idx;
|
||||
}
|
||||
void display(std::ostream & out) const override {
|
||||
out << "s_" << m_idx;
|
||||
std::ostream& display(std::ostream & out) const override {
|
||||
return out << "s_" << m_idx;
|
||||
}
|
||||
unsigned idx() const { return m_idx; }
|
||||
};
|
||||
|
@ -254,7 +254,7 @@ public:
|
|||
}
|
||||
return true;
|
||||
}
|
||||
void display(std::ostream & out) const override {
|
||||
std::ostream& display(std::ostream & out) const override {
|
||||
if (m_args.empty()) {
|
||||
out << m_decl->get_name();
|
||||
}
|
||||
|
@ -267,6 +267,7 @@ public:
|
|||
}
|
||||
out << ")";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -342,12 +343,12 @@ void display_sort_args(std::ostream & out, unsigned num_params) {
|
|||
out << ") ";
|
||||
}
|
||||
|
||||
void psort_user_decl::display(std::ostream & out) const {
|
||||
std::ostream& psort_user_decl::display(std::ostream & out) const {
|
||||
out << "(declare-sort " << m_name;
|
||||
display_sort_args(out, m_num_params);
|
||||
if (m_def)
|
||||
m_def->display(out);
|
||||
out << ")";
|
||||
return out << ")";
|
||||
}
|
||||
|
||||
// -------------------
|
||||
|
@ -364,8 +365,8 @@ sort * psort_dt_decl::instantiate(pdecl_manager & m, unsigned n, sort * const *
|
|||
return m.instantiate_datatype(this, m_name, n, s);
|
||||
}
|
||||
|
||||
void psort_dt_decl::display(std::ostream & out) const {
|
||||
out << "(datatype-sort " << m_name << ")";
|
||||
std::ostream& psort_dt_decl::display(std::ostream & out) const {
|
||||
return out << "(datatype-sort " << m_name << ")";
|
||||
}
|
||||
|
||||
// -------------------
|
||||
|
@ -410,8 +411,8 @@ sort * psort_builtin_decl::instantiate(pdecl_manager & m, unsigned n, unsigned c
|
|||
}
|
||||
}
|
||||
|
||||
void psort_builtin_decl::display(std::ostream & out) const {
|
||||
out << "(declare-builtin-sort " << m_name << ")";
|
||||
std::ostream& psort_builtin_decl::display(std::ostream & out) const {
|
||||
return out << "(declare-builtin-sort " << m_name << ")";
|
||||
}
|
||||
|
||||
void ptype::display(std::ostream & out, pdatatype_decl const * const * dts) const {
|
||||
|
@ -615,7 +616,7 @@ sort * pdatatype_decl::instantiate(pdecl_manager & m, unsigned n, sort * const *
|
|||
}
|
||||
|
||||
|
||||
void pdatatype_decl::display(std::ostream & out) const {
|
||||
std::ostream& pdatatype_decl::display(std::ostream & out) const {
|
||||
out << "(declare-datatype " << m_name;
|
||||
display_sort_args(out, m_num_params);
|
||||
bool first = true;
|
||||
|
@ -631,7 +632,7 @@ void pdatatype_decl::display(std::ostream & out) const {
|
|||
}
|
||||
first = false;
|
||||
}
|
||||
out << ")";
|
||||
return out << ")";
|
||||
}
|
||||
|
||||
bool pdatatype_decl::commit(pdecl_manager& m) {
|
||||
|
@ -645,9 +646,11 @@ bool pdatatype_decl::commit(pdecl_manager& m) {
|
|||
datatype_decl * d_ptr = dts.m_buffer[0];
|
||||
sort_ref_vector sorts(m.m());
|
||||
bool is_ok = m.get_dt_plugin()->mk_datatypes(1, &d_ptr, m_num_params, ps.data(), sorts);
|
||||
m.notify_mk_datatype(m_name);
|
||||
if (is_ok && m_num_params == 0) {
|
||||
m.notify_new_dt(sorts.get(0), this);
|
||||
}
|
||||
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
|
@ -722,6 +725,7 @@ void pdecl_manager::notify_datatype(sort *r, psort_decl* p, unsigned n, sort* co
|
|||
|
||||
void pdecl_manager::push() {
|
||||
m_notified_lim.push_back(m_notified_trail.size());
|
||||
m_datatypes_lim.push_back(m_datatypes_trail.size());
|
||||
}
|
||||
|
||||
void pdecl_manager::pop(unsigned n) {
|
||||
|
@ -732,6 +736,16 @@ void pdecl_manager::pop(unsigned n) {
|
|||
}
|
||||
m_notified_trail.shrink(new_sz);
|
||||
m_notified_lim.shrink(m_notified_lim.size() - n);
|
||||
|
||||
new_sz = m_datatypes_lim[m_datatypes_lim.size() - n];
|
||||
if (new_sz != m_datatypes_trail.size()) {
|
||||
datatype_util util(m());
|
||||
for (unsigned i = m_datatypes_trail.size(); i-- > new_sz; )
|
||||
util.plugin().remove(m_datatypes_trail[i]);
|
||||
}
|
||||
m_datatypes_trail.shrink(new_sz);
|
||||
m_datatypes_lim.shrink(m_datatypes_lim.size() - n);
|
||||
|
||||
}
|
||||
|
||||
bool pdatatypes_decl::instantiate(pdecl_manager & m, sort * const * s) {
|
||||
|
@ -751,16 +765,24 @@ bool pdatatypes_decl::commit(pdecl_manager& m) {
|
|||
sort_ref_vector sorts(m.m());
|
||||
bool is_ok = m.get_dt_plugin()->mk_datatypes(m_datatypes.size(), dts.m_buffer.data(), 0, nullptr, sorts);
|
||||
if (is_ok) {
|
||||
for (pdatatype_decl* d : m_datatypes) {
|
||||
m.notify_mk_datatype(d->get_name());
|
||||
}
|
||||
for (unsigned i = 0; i < m_datatypes.size(); ++i) {
|
||||
pdatatype_decl* d = m_datatypes[i];
|
||||
if (d->get_num_params() == 0) {
|
||||
if (d->get_num_params() == 0)
|
||||
m.notify_new_dt(sorts.get(i), this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
void pdecl_manager::notify_mk_datatype(symbol const& name) {
|
||||
m_datatypes_trail.push_back(name);
|
||||
}
|
||||
|
||||
|
||||
struct pdecl_manager::sort_info {
|
||||
psort_decl * m_decl;
|
||||
|
||||
|
@ -985,16 +1007,19 @@ void pdecl_manager::del_decl_core(pdecl * p) {
|
|||
}
|
||||
|
||||
void pdecl_manager::del_decl(pdecl * p) {
|
||||
TRACE("pdecl_manager", tout << "del psort "; p->display(tout); tout << "\n";);
|
||||
TRACE("pdecl_manager", tout << "del psort "; p->display(tout); tout << "\n";);
|
||||
if (p->is_psort()) {
|
||||
psort * _p = static_cast<psort*>(p);
|
||||
if (_p->is_sort_wrapper()) {
|
||||
m_sort2psort.erase(static_cast<psort_sort*>(_p)->get_sort());
|
||||
sort* s = static_cast<psort_sort*>(_p)->get_sort();
|
||||
m_sort2psort.erase(s);
|
||||
}
|
||||
else {
|
||||
m_table.erase(_p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
del_decl_core(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
unsigned get_id() const { return m_id; }
|
||||
unsigned get_ref_count() const { return m_ref_count; }
|
||||
unsigned hash() const { return m_id; }
|
||||
virtual void display(std::ostream & out) const {}
|
||||
virtual std::ostream& display(std::ostream & out) const { return out;}
|
||||
virtual void reset_cache(pdecl_manager& m) {}
|
||||
};
|
||||
|
||||
|
@ -123,7 +123,7 @@ protected:
|
|||
~psort_user_decl() override {}
|
||||
public:
|
||||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
||||
void display(std::ostream & out) const override;
|
||||
std::ostream& display(std::ostream & out) const override;
|
||||
};
|
||||
|
||||
class psort_builtin_decl : public psort_decl {
|
||||
|
@ -137,7 +137,7 @@ protected:
|
|||
public:
|
||||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
||||
sort * instantiate(pdecl_manager & m, unsigned n, unsigned const * s) override;
|
||||
void display(std::ostream & out) const override;
|
||||
std::ostream& display(std::ostream & out) const override;
|
||||
};
|
||||
|
||||
class psort_dt_decl : public psort_decl {
|
||||
|
@ -148,7 +148,7 @@ protected:
|
|||
~psort_dt_decl() override {}
|
||||
public:
|
||||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
||||
void display(std::ostream & out) const override;
|
||||
std::ostream& display(std::ostream & out) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -198,7 +198,7 @@ class paccessor_decl : public pdecl {
|
|||
ptype const & get_type() const { return m_type; }
|
||||
~paccessor_decl() override {}
|
||||
public:
|
||||
void display(std::ostream & out) const override { pdecl::display(out); }
|
||||
std::ostream& display(std::ostream & out) const override { pdecl::display(out); return out; }
|
||||
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
|
||||
};
|
||||
|
||||
|
@ -219,7 +219,7 @@ class pconstructor_decl : public pdecl {
|
|||
constructor_decl * instantiate_decl(pdecl_manager & m, unsigned n, sort * const * s);
|
||||
~pconstructor_decl() override {}
|
||||
public:
|
||||
void display(std::ostream & out) const override { pdecl::display(out); }
|
||||
std::ostream& display(std::ostream & out) const override { pdecl::display(out); return out; }
|
||||
void display(std::ostream & out, pdatatype_decl const * const * dts) const;
|
||||
};
|
||||
|
||||
|
@ -237,7 +237,7 @@ class pdatatype_decl : public psort_decl {
|
|||
~pdatatype_decl() override {}
|
||||
public:
|
||||
sort * instantiate(pdecl_manager & m, unsigned n, sort * const * s) override;
|
||||
void display(std::ostream & out) const override;
|
||||
std::ostream& display(std::ostream & out) const override;
|
||||
bool has_missing_refs(symbol & missing) const;
|
||||
bool has_duplicate_accessors(symbol & repeated) const;
|
||||
bool commit(pdecl_manager& m);
|
||||
|
@ -289,6 +289,8 @@ class pdecl_manager {
|
|||
obj_hashtable<sort> m_notified;
|
||||
ptr_vector<sort> m_notified_trail;
|
||||
unsigned_vector m_notified_lim;
|
||||
svector<symbol> m_datatypes_trail;
|
||||
unsigned_vector m_datatypes_lim;
|
||||
|
||||
void init_list();
|
||||
void del_decl_core(pdecl * p);
|
||||
|
@ -319,6 +321,7 @@ public:
|
|||
sort * instantiate_datatype(psort_decl* p, symbol const& name, unsigned n, sort * const* s);
|
||||
sort * instantiate(psort * s, unsigned num, sort * const * args);
|
||||
void notify_datatype(sort *r, psort_decl* p, unsigned n, sort* const* s);
|
||||
void notify_mk_datatype(symbol const& name);
|
||||
void push();
|
||||
void pop(unsigned n);
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ class lar_solver : public column_namer {
|
|||
void insert_row_with_changed_bounds(unsigned rid);
|
||||
void detect_rows_with_changed_bounds_for_column(unsigned j);
|
||||
void detect_rows_with_changed_bounds();
|
||||
void set_value_for_nbasic_column(unsigned j, const impq & new_val);
|
||||
|
||||
void update_x_and_inf_costs_for_columns_with_changed_bounds();
|
||||
void update_x_and_inf_costs_for_columns_with_changed_bounds_tableau();
|
||||
void solve_with_core_solver();
|
||||
|
@ -355,6 +355,9 @@ public:
|
|||
bp.consume(a, witness);
|
||||
}
|
||||
}
|
||||
|
||||
void set_value_for_nbasic_column(unsigned j, const impq& new_val);
|
||||
|
||||
// lp_assert(implied_bound_is_correctly_explained(ib, explanation)); }
|
||||
constraint_index mk_var_bound(var_index j, lconstraint_kind kind, const mpq & right_side);
|
||||
void activate_check_on_equal(constraint_index, var_index&);
|
||||
|
|
|
@ -217,14 +217,14 @@ template <typename T, typename X> void lp_dual_simplex<T, X>::fill_costs_bounds_
|
|||
m_can_enter_basis[j] = true;
|
||||
this->set_scaled_cost(j);
|
||||
this->m_lower_bounds[j] = numeric_traits<T>::zero();
|
||||
this->m_upper_bounds[j] =numeric_traits<T>::one();
|
||||
this->m_upper_bounds[j] = numeric_traits<T>::one();
|
||||
break;
|
||||
}
|
||||
case column_type::free_column: {
|
||||
m_can_enter_basis[j] = true;
|
||||
this->set_scaled_cost(j);
|
||||
this->m_upper_bounds[j] = free_bound;
|
||||
this->m_lower_bounds[j] = -free_bound;
|
||||
this->m_upper_bounds[j] = free_bound;
|
||||
this->m_lower_bounds[j] = -free_bound;
|
||||
break;
|
||||
}
|
||||
case column_type::boxed:
|
||||
|
|
|
@ -2013,6 +2013,11 @@ namespace algebraic_numbers {
|
|||
}
|
||||
else {
|
||||
algebraic_cell * c = a.to_algebraic();
|
||||
if (c->m_i == 0) {
|
||||
// undefined
|
||||
c->m_i = upm().get_root_id(c->m_p_sz, c->m_p, lower(c)) + 1;
|
||||
}
|
||||
SASSERT(c->m_i > 0);
|
||||
return c->m_i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ expr * array_factory::mk_array_interp(sort * s, func_interp * & fi) {
|
|||
func_decl * f = mk_aux_decl_for_array_sort(m_manager, s);
|
||||
fi = alloc(func_interp, m_manager, get_array_arity(s));
|
||||
m_model.register_decl(f, fi);
|
||||
parameter p[1] = { parameter(f) };
|
||||
expr * val = m_manager.mk_app(get_family_id(), OP_AS_ARRAY, 1, p);
|
||||
parameter p(f);
|
||||
expr * val = m_manager.mk_app(get_family_id(), OP_AS_ARRAY, 1, &p);
|
||||
register_value(val);
|
||||
return val;
|
||||
}
|
||||
|
|
|
@ -48,10 +48,8 @@ expr * datatype_factory::get_some_value(sort * s) {
|
|||
*/
|
||||
expr * datatype_factory::get_last_fresh_value(sort * s) {
|
||||
expr * val = nullptr;
|
||||
if (m_last_fresh_value.find(s, val)) {
|
||||
TRACE("datatype", tout << "cached fresh value: " << mk_pp(val, m_manager) << "\n";);
|
||||
if (m_last_fresh_value.find(s, val))
|
||||
return val;
|
||||
}
|
||||
value_set * set = get_value_set(s);
|
||||
if (set->empty())
|
||||
val = get_some_value(s);
|
||||
|
@ -200,7 +198,7 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
if (m_util.is_recursive(s)) {
|
||||
while (true) {
|
||||
++num_iterations;
|
||||
TRACE("datatype", tout << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
|
||||
TRACE("datatype", tout << num_iterations << " " << mk_pp(get_last_fresh_value(s), m_manager) << "\n";);
|
||||
ptr_vector<func_decl> const & constructors = *m_util.get_datatype_constructors(s);
|
||||
for (func_decl * constructor : constructors) {
|
||||
expr_ref_vector args(m_manager);
|
||||
|
@ -219,7 +217,7 @@ expr * datatype_factory::get_fresh_value(sort * s) {
|
|||
expr * maybe_new_arg = nullptr;
|
||||
if (!m_util.is_datatype(s_arg))
|
||||
maybe_new_arg = m_model.get_fresh_value(s_arg);
|
||||
else if (num_iterations <= 1)
|
||||
else if (num_iterations <= 1 || m_util.is_recursive(s_arg))
|
||||
maybe_new_arg = get_almost_fresh_value(s_arg);
|
||||
else
|
||||
maybe_new_arg = get_fresh_value(s_arg);
|
||||
|
|
|
@ -5,6 +5,7 @@ def_module_params('model',
|
|||
('v2', BOOL, False, 'use Z3 version 2.x (x <= 16) pretty printer'),
|
||||
('compact', BOOL, True, 'try to compact function graph (i.e., function interpretations that are lookup tables)'),
|
||||
('inline_def', BOOL, False, 'inline local function definitions ignoring possible expansion'),
|
||||
('user_functions', BOOL, True, 'include user defined functions in model'),
|
||||
('completion', BOOL, False, 'enable/disable model completion'),
|
||||
))
|
||||
|
||||
|
|
|
@ -281,14 +281,19 @@ namespace datalog {
|
|||
return get_max_var(has_var);
|
||||
}
|
||||
|
||||
void del_rule(horn_subsume_model_converter* mc, rule& r, bool unreachable) {
|
||||
void del_rule(horn_subsume_model_converter* mc, rule& r, lbool unreachable) {
|
||||
if (mc) {
|
||||
ast_manager& m = mc->get_manager();
|
||||
expr_ref_vector body(m);
|
||||
if (unreachable) {
|
||||
TRACE("dl", tout << "unreachable: " << unreachable << " " << r.get_decl()->get_name() << "\n");
|
||||
switch (unreachable) {
|
||||
case l_true:
|
||||
body.push_back(m.mk_true());
|
||||
break;
|
||||
case l_false:
|
||||
body.push_back(m.mk_false());
|
||||
}
|
||||
else {
|
||||
break;
|
||||
default:
|
||||
for (unsigned i = 0; i < r.get_tail_size(); ++i) {
|
||||
if (r.is_neg_tail(i)) {
|
||||
body.push_back(m.mk_not(r.get_tail(i)));
|
||||
|
@ -297,11 +302,12 @@ namespace datalog {
|
|||
body.push_back(r.get_tail(i));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
TRACE("dl_dr",
|
||||
TRACE("dl",
|
||||
tout << mk_pp(r.get_head(), m) << " :- \n";
|
||||
for (unsigned i = 0; i < body.size(); ++i) {
|
||||
tout << mk_pp(body[i].get(), m) << "\n";
|
||||
tout << mk_pp(body.get(i), m) << "\n";
|
||||
});
|
||||
|
||||
mc->insert(r.get_head(), body.size(), body.data());
|
||||
|
|
|
@ -353,7 +353,7 @@ namespace datalog {
|
|||
unsigned get_max_rule_var(const rule& r);
|
||||
};
|
||||
|
||||
void del_rule(horn_subsume_model_converter* mc, rule& r, bool unreachable);
|
||||
void del_rule(horn_subsume_model_converter* mc, rule& r, lbool unreachable);
|
||||
|
||||
void resolve_rule(rule_manager& rm,
|
||||
replace_proof_converter* pc, rule const& r1, rule const& r2, unsigned idx,
|
||||
|
|
|
@ -210,19 +210,35 @@ bool rule_properties::check_accessor(app* n) {
|
|||
SASSERT(m_dt.is_datatype(s));
|
||||
if (m_dt.get_datatype_constructors(s)->size() <= 1)
|
||||
return true;
|
||||
|
||||
|
||||
func_decl* f = n->get_decl();
|
||||
func_decl * c = m_dt.get_accessor_constructor(f);
|
||||
func_decl* c = m_dt.get_accessor_constructor(f);
|
||||
unsigned ut_size = m_rule->get_uninterpreted_tail_size();
|
||||
unsigned t_size = m_rule->get_tail_size();
|
||||
ptr_vector<func_decl> ctors;
|
||||
|
||||
// add recognizer constructor to ctors
|
||||
auto add_recognizer = [&](expr* r) {
|
||||
if (!m_dt.is_recognizer(r))
|
||||
return;
|
||||
if (n->get_arg(0) != to_app(r)->get_arg(0))
|
||||
return;
|
||||
auto* c2 = m_dt.get_recognizer_constructor(to_app(r)->get_decl());
|
||||
if (c == c2)
|
||||
return;
|
||||
ctors.push_back(c2);
|
||||
};
|
||||
auto add_not_recognizer = [&](expr* r) {
|
||||
if (m.is_not(r, r))
|
||||
add_recognizer(r);
|
||||
};
|
||||
|
||||
// t is a recognizer for n
|
||||
auto is_recognizer_base = [&](expr* t) {
|
||||
return m_dt.is_recognizer(t) &&
|
||||
to_app(t)->get_arg(0) == n->get_arg(0) &&
|
||||
m_dt.get_recognizer_constructor(to_app(t)->get_decl()) == c;
|
||||
};
|
||||
|
||||
auto is_recognizer = [&](expr* t) {
|
||||
if (m.is_and(t))
|
||||
for (expr* arg : *to_app(t))
|
||||
|
@ -231,43 +247,78 @@ bool rule_properties::check_accessor(app* n) {
|
|||
return is_recognizer_base(t);
|
||||
};
|
||||
|
||||
|
||||
for (unsigned i = ut_size; i < t_size; ++i)
|
||||
if (is_recognizer(m_rule->get_tail(i)))
|
||||
for (unsigned i = ut_size; i < t_size; ++i) {
|
||||
auto* tail = m_rule->get_tail(i);
|
||||
if (is_recognizer(tail))
|
||||
return true;
|
||||
|
||||
add_not_recognizer(tail);
|
||||
}
|
||||
|
||||
// create parent use list for every sub-expression in the rule
|
||||
obj_map<expr, ptr_vector<expr>> use_list;
|
||||
for (unsigned i = ut_size; i < t_size; ++i) {
|
||||
app* t = m_rule->get_tail(i);
|
||||
use_list.insert_if_not_there(t, ptr_vector<expr>()).push_back(nullptr); // add marker for top-level expression.
|
||||
for (expr* sub : subterms::all(expr_ref(t, m)))
|
||||
for (expr* sub : subterms::all(expr_ref(t, m)))
|
||||
if (is_app(sub))
|
||||
for (expr* arg : *to_app(sub))
|
||||
use_list.insert_if_not_there(arg, ptr_vector<expr>()).push_back(sub);
|
||||
}
|
||||
|
||||
// walk parents of n to check that each path is guarded by a recognizer.
|
||||
ptr_vector<expr> todo;
|
||||
todo.push_back(n);
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
expr* e = todo[i];
|
||||
// walk parents of n depth first to check that each path is guarded by a recognizer.
|
||||
vector<std::tuple<expr *, unsigned int, bool>> todo;
|
||||
todo.push_back({n, ctors.size(), false});
|
||||
while(!todo.empty()) {
|
||||
auto [e, ctors_size, visited] = todo.back();
|
||||
if (visited) {
|
||||
todo.pop_back();
|
||||
while (ctors.size() > ctors_size) ctors.pop_back();
|
||||
continue;
|
||||
}
|
||||
std::get<2>(todo.back()) = true; // set visited
|
||||
|
||||
if (!use_list.contains(e))
|
||||
return false;
|
||||
for (expr* parent : use_list[e]) {
|
||||
if (!parent)
|
||||
return false; // top-level expressions are not guarded
|
||||
if (is_recognizer(parent))
|
||||
if (!parent) { // top-level expression
|
||||
// check if n is an unguarded "else" branch
|
||||
ptr_vector<func_decl> diff;
|
||||
for (auto* dtc : *m_dt.get_datatype_constructors(s))
|
||||
if (!ctors.contains(dtc))
|
||||
diff.push_back(dtc);
|
||||
// the only unguarded constructor for s is c:
|
||||
// all the others are guarded and we are in an "else" branch so the accessor is safe
|
||||
if (diff.size() == 1 && diff[0] == c)
|
||||
continue;
|
||||
return false; // the accessor is not safe
|
||||
}
|
||||
if (is_recognizer(parent))
|
||||
continue;
|
||||
if (m.is_ite(parent) && to_app(parent)->get_arg(1) == e && is_recognizer(to_app(parent)->get_arg(0)))
|
||||
continue;
|
||||
todo.push_back(parent);
|
||||
|
||||
expr *cnd, *thn, *els;
|
||||
if (m.is_ite(parent, cnd, thn, els)) {
|
||||
if (thn == e) {
|
||||
if (is_recognizer(cnd) && els != e)
|
||||
continue; // e is guarded
|
||||
}
|
||||
add_recognizer(cnd);
|
||||
}
|
||||
if (m.is_and(parent))
|
||||
for (expr* arg : *to_app(parent))
|
||||
add_not_recognizer(arg);
|
||||
if (m.is_or(parent))
|
||||
for (expr* arg : *to_app(parent)) {
|
||||
add_recognizer(arg);
|
||||
// if one branch is not(recognizer) then the accessor is safe
|
||||
if (m.is_not(arg, arg) && is_recognizer(arg))
|
||||
goto _continue;
|
||||
}
|
||||
todo.push_back({parent, ctors.size(), false});
|
||||
_continue:;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void rule_properties::operator()(app* n) {
|
||||
|
|
|
@ -777,6 +777,7 @@ protected:
|
|||
// Sym ::= String | NUM | Var
|
||||
//
|
||||
dtoken parse_infix(dtoken tok1, char const* td, app_ref& pred) {
|
||||
std::string td1_(td);
|
||||
symbol td1(td);
|
||||
expr_ref v1(m), v2(m);
|
||||
sort* s = nullptr;
|
||||
|
@ -793,12 +794,12 @@ protected:
|
|||
|
||||
if (tok1 == TK_ID) {
|
||||
expr* _v1 = nullptr;
|
||||
m_vars.find(td1.bare_str(), _v1);
|
||||
m_vars.find(td1_, _v1);
|
||||
v1 = _v1;
|
||||
}
|
||||
if (tok3 == TK_ID) {
|
||||
expr* _v2 = nullptr;
|
||||
m_vars.find(td2.bare_str(), _v2);
|
||||
m_vars.find(td, _v2);
|
||||
v2 = _v2;
|
||||
}
|
||||
if (!v1 && !v2) {
|
||||
|
@ -950,18 +951,19 @@ protected:
|
|||
break;
|
||||
}
|
||||
case TK_ID: {
|
||||
symbol data (m_lexer->get_token_data());
|
||||
if (is_var(data.bare_str())) {
|
||||
char const* d = m_lexer->get_token_data();
|
||||
symbol data (d);
|
||||
if (is_var(d)) {
|
||||
unsigned idx = 0;
|
||||
expr* v = nullptr;
|
||||
if (!m_vars.find(data.bare_str(), v)) {
|
||||
if (!m_vars.find(d, v)) {
|
||||
idx = m_num_vars++;
|
||||
v = m.mk_var(idx, s);
|
||||
m_vars.insert(data.bare_str(), v);
|
||||
m_vars.insert(d, v);
|
||||
}
|
||||
else if (s != v->get_sort()) {
|
||||
throw default_exception(default_exception::fmt(), "sort: %s expected, but got: %s\n",
|
||||
s->get_name().bare_str(), v->get_sort()->get_name().bare_str());
|
||||
s->get_name().str().c_str(), v->get_sort()->get_name().str().c_str());
|
||||
}
|
||||
args.push_back(v);
|
||||
}
|
||||
|
@ -1075,21 +1077,21 @@ protected:
|
|||
}
|
||||
|
||||
sort * register_finite_sort(symbol name, uint64_t domain_size, context::sort_kind k) {
|
||||
if(m_sort_dict.contains(name.bare_str())) {
|
||||
throw default_exception(default_exception::fmt(), "sort %s already declared", name.bare_str());
|
||||
if(m_sort_dict.contains(name.str().c_str())) {
|
||||
throw default_exception(default_exception::fmt(), "sort %s already declared", name.str().c_str());
|
||||
}
|
||||
sort * s = m_decl_util.mk_sort(name, domain_size);
|
||||
m_context.register_finite_sort(s, k);
|
||||
m_sort_dict.insert(name.bare_str(), s);
|
||||
m_sort_dict.insert(name.str(), s);
|
||||
return s;
|
||||
}
|
||||
|
||||
sort * register_int_sort(symbol name) {
|
||||
if(m_sort_dict.contains(name.bare_str())) {
|
||||
throw default_exception(default_exception::fmt(), "sort %s already declared", name.bare_str());
|
||||
if(m_sort_dict.contains(name.str().c_str())) {
|
||||
throw default_exception(default_exception::fmt(), "sort %s already declared", name.str().c_str());
|
||||
}
|
||||
sort * s = m_arith.mk_int();
|
||||
m_sort_dict.insert(name.bare_str(), s);
|
||||
m_sort_dict.insert(name.str(), s);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -1105,8 +1107,8 @@ protected:
|
|||
app * res;
|
||||
if(m_arith.is_int(s)) {
|
||||
uint64_t val;
|
||||
if (!string_to_uint64(name.bare_str(), val)) {
|
||||
throw default_exception(default_exception::fmt(), "Invalid integer: \"%s\"", name.bare_str());
|
||||
if (!string_to_uint64(name.str().c_str(), val)) {
|
||||
throw default_exception(default_exception::fmt(), "Invalid integer: \"%s\"", name.str().c_str());
|
||||
}
|
||||
res = m_arith.mk_numeral(rational(val, rational::ui64()), s);
|
||||
}
|
||||
|
@ -1288,7 +1290,7 @@ private:
|
|||
uint64_set & sort_content = *e->get_data().m_value;
|
||||
if(!sort_content.contains(num)) {
|
||||
warning_msg("symbol number %I64u on line %d in file %s does not belong to sort %s",
|
||||
num, m_current_line, m_current_file.c_str(), s->get_name().bare_str());
|
||||
num, m_current_line, m_current_file.c_str(), s->get_name().str().c_str());
|
||||
return false;
|
||||
}
|
||||
if(!m_use_map_names) {
|
||||
|
@ -1366,7 +1368,7 @@ private:
|
|||
func_decl * pred = m_context.try_get_predicate_decl(predicate_name);
|
||||
if(!pred) {
|
||||
throw default_exception(default_exception::fmt(), "tuple file %s for undeclared predicate %s",
|
||||
m_current_file.c_str(), predicate_name.bare_str());
|
||||
m_current_file.c_str(), predicate_name.str().c_str());
|
||||
}
|
||||
unsigned pred_arity = pred->get_arity();
|
||||
sort * const * arg_sorts = pred->get_domain();
|
||||
|
@ -1531,9 +1533,9 @@ private:
|
|||
|
||||
if(m_use_map_names) {
|
||||
auto const & value = m_number_names.insert_if_not_there(num, el_name);
|
||||
if (value!=el_name) {
|
||||
if (value != el_name) {
|
||||
warning_msg("mismatch of number names on line %d in file %s. old: \"%s\" new: \"%s\"",
|
||||
m_current_line, fname.c_str(), value.bare_str(), el_name.bare_str());
|
||||
m_current_line, fname.c_str(), value.str().c_str(), el_name.str().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ class horn_tactic : public tactic {
|
|||
verify(q, g, result, mc, pc);
|
||||
}
|
||||
g->set(pc.get());
|
||||
g->set(mc.get());
|
||||
g->add(mc.get());
|
||||
}
|
||||
|
||||
void verify(expr* q,
|
||||
|
@ -282,12 +282,11 @@ class horn_tactic : public tactic {
|
|||
}
|
||||
case l_false: {
|
||||
// goal is sat
|
||||
mc = concat(g->mc(), mc.get());
|
||||
g->reset();
|
||||
if (produce_models) {
|
||||
model_ref md = m_ctx.get_model();
|
||||
model_converter_ref mc2 = model2model_converter(md.get());
|
||||
mc = concat(mc.get(), mc2.get());
|
||||
mc = mc2.get();
|
||||
TRACE("dl", mc->display(tout << *md << "\n"););
|
||||
}
|
||||
break;
|
||||
|
@ -345,6 +344,7 @@ class horn_tactic : public tactic {
|
|||
g->assert_expr(fml);
|
||||
}
|
||||
g->set_prec(goal::UNDER_OVER);
|
||||
mc = g->mc();
|
||||
}
|
||||
|
||||
void check_parameters() {
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
symbol finite_product_relation_plugin::get_name(relation_plugin & inner_plugin) {
|
||||
std::string str = std::string("fpr_")+inner_plugin.get_name().bare_str();
|
||||
std::string str = std::string("fpr_")+inner_plugin.get_name().str();
|
||||
return symbol(str.c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -213,10 +213,10 @@ namespace datalog {
|
|||
return true;
|
||||
}
|
||||
void make_annotations(execution_context & ctx) override {
|
||||
ctx.set_register_annotation(m_reg, m_pred->get_name().bare_str());
|
||||
ctx.set_register_annotation(m_reg, m_pred->get_name().str().c_str());
|
||||
}
|
||||
std::ostream& display_head_impl(execution_context const& ctx, std::ostream & out) const override {
|
||||
const char * rel_name = m_pred->get_name().bare_str();
|
||||
auto rel_name = m_pred->get_name();
|
||||
if (m_store) {
|
||||
return out << "store " << m_reg << " into " << rel_name;
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported join operation on relations of kinds %s and %s",
|
||||
r1.get_plugin().get_name().bare_str(), r2.get_plugin().get_name().bare_str());
|
||||
r1.get_plugin().get_name().str().c_str(), r2.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(r1, r2, fn);
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported filter_equal operation on a relation of kind %s",
|
||||
r.get_plugin().get_name().bare_str());
|
||||
r.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(r, fn);
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported filter_identical operation on a relation of kind %s",
|
||||
r.get_plugin().get_name().bare_str());
|
||||
r.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(r, fn);
|
||||
}
|
||||
|
@ -537,7 +537,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported filter_interpreted operation on a relation of kind %s",
|
||||
r.get_plugin().get_name().bare_str());
|
||||
r.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(r, fn);
|
||||
}
|
||||
|
@ -594,7 +594,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported filter_interpreted_and_project operation on a relation of kind %s",
|
||||
reg.get_plugin().get_name().bare_str());
|
||||
reg.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(reg, fn);
|
||||
}
|
||||
|
@ -837,7 +837,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported join-project operation on relations of kinds %s and %s",
|
||||
r1.get_plugin().get_name().bare_str(), r2.get_plugin().get_name().bare_str());
|
||||
r1.get_plugin().get_name().str().c_str(), r2.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(r1, r2, fn);
|
||||
}
|
||||
|
@ -910,7 +910,7 @@ namespace datalog {
|
|||
if (!fn) {
|
||||
throw default_exception(default_exception::fmt(),
|
||||
"trying to perform unsupported select_equal_and_project operation on a relation of kind %s",
|
||||
r.get_plugin().get_name().bare_str());
|
||||
r.get_plugin().get_name().str().c_str());
|
||||
}
|
||||
store_fn(r, fn);
|
||||
}
|
||||
|
@ -1076,7 +1076,7 @@ namespace datalog {
|
|||
return true;
|
||||
}
|
||||
std::ostream& display_head_impl(execution_context const& ctx, std::ostream & out) const override {
|
||||
return out << "mark_saturated " << m_pred->get_name().bare_str();
|
||||
return out << "mark_saturated " << m_pred->get_name();
|
||||
}
|
||||
void make_annotations(execution_context & ctx) override {
|
||||
}
|
||||
|
|
|
@ -370,7 +370,7 @@ namespace datalog {
|
|||
rule * one_parent = inf.m_rules.back();
|
||||
|
||||
func_decl* parent_head = one_parent->get_decl();
|
||||
const char * one_parent_name = parent_head->get_name().bare_str();
|
||||
std::string one_parent_name = parent_head->get_name().str();
|
||||
std::string parent_name;
|
||||
if (inf.m_rules.size() > 1) {
|
||||
parent_name = one_parent_name + std::string("_and_") + to_string(inf.m_rules.size()-1);
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace datalog {
|
|||
// -----------------------------------
|
||||
|
||||
symbol table_relation_plugin::create_plugin_name(const table_plugin &p) {
|
||||
std::string name = std::string("tr_") + p.get_name().bare_str();
|
||||
std::string name = std::string("tr_") + p.get_name().str();
|
||||
return symbol(name.c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace datalog {
|
|||
//IF_VERBOSE(3, m_context.display_smt2(0,0,verbose_stream()););
|
||||
|
||||
if (m_context.print_aig().is_non_empty_string()) {
|
||||
const char *filename = m_context.print_aig().bare_str();
|
||||
std::string filename = m_context.print_aig().str();
|
||||
aig_exporter aig(m_context.get_rules(), get_context(), &m_table_facts);
|
||||
std::ofstream strm(filename, std::ios_base::binary);
|
||||
aig(strm);
|
||||
|
|
|
@ -126,7 +126,7 @@ public:
|
|||
void move_to_front(expr* e) override { m_solver.move_to_front(e); }
|
||||
expr_ref_vector cube(expr_ref_vector&, unsigned) override { return expr_ref_vector(m); }
|
||||
void get_levels(ptr_vector<expr> const& vars, unsigned_vector& depth) override { m_solver.get_levels(vars, depth); }
|
||||
expr_ref_vector get_trail() override { return m_solver.get_trail(); }
|
||||
expr_ref_vector get_trail(unsigned max_level) override { return m_solver.get_trail(max_level); }
|
||||
|
||||
void push() override;
|
||||
void pop(unsigned n) override;
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace datalog {
|
|||
}
|
||||
|
||||
rule_set * mk_coi_filter::top_down(rule_set const & source) {
|
||||
func_decl_set pruned_preds;
|
||||
func_decl_set pruned_preds, seen;
|
||||
dataflow_engine<reachability_info> engine(source.get_manager(), source);
|
||||
engine.run_top_down();
|
||||
scoped_ptr<rule_set> res = alloc(rule_set, m_context);
|
||||
|
@ -126,37 +126,51 @@ namespace datalog {
|
|||
|
||||
for (rule * r : source) {
|
||||
func_decl * pred = r->get_decl();
|
||||
if (engine.get_fact(pred).is_reachable()) {
|
||||
res->add_rule(r);
|
||||
}
|
||||
bool should_keep = false;
|
||||
if (seen.contains(pred))
|
||||
continue;
|
||||
seen.insert(pred);
|
||||
if (engine.get_fact(pred).is_reachable())
|
||||
should_keep = true;
|
||||
else if (m_context.get_model_converter()) {
|
||||
pruned_preds.insert(pred);
|
||||
for (rule* pr : source.get_predicate_rules(pred))
|
||||
for (unsigned i = 0; i < pr->get_uninterpreted_tail_size(); ++i)
|
||||
if (pr->get_tail(i)->get_decl() != pred)
|
||||
// don't try to eliminate across predicates
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if (should_keep)
|
||||
for (rule* pr : source.get_predicate_rules(pred))
|
||||
res->add_rule(pr);
|
||||
else
|
||||
pruned_preds.insert(pred);
|
||||
}
|
||||
|
||||
if (res->get_num_rules() == source.get_num_rules()) {
|
||||
TRACE("dl", tout << "No transformation\n";);
|
||||
res = nullptr;
|
||||
}
|
||||
if (res && m_context.get_model_converter()) {
|
||||
generic_model_converter* mc0 = alloc(generic_model_converter, m, "dl_coi");
|
||||
for (func_decl* f : pruned_preds) {
|
||||
if (res && m_context.get_model_converter() && !pruned_preds.empty()) {
|
||||
auto* mc0 = alloc(generic_model_converter, m, "dl_coi");
|
||||
horn_subsume_model_converter hmc(m);
|
||||
|
||||
for (func_decl* f : pruned_preds) {
|
||||
const rule_vector& rules = source.get_predicate_rules(f);
|
||||
expr_ref_vector fmls(m);
|
||||
for (rule * r : rules) {
|
||||
app* head = r->get_head();
|
||||
expr_ref_vector conj(m);
|
||||
for (unsigned j = 0; j < head->get_num_args(); ++j) {
|
||||
expr* arg = head->get_arg(j);
|
||||
if (!is_var(arg)) {
|
||||
conj.push_back(m.mk_eq(m.mk_var(j, arg->get_sort()), arg));
|
||||
}
|
||||
}
|
||||
fmls.push_back(mk_and(conj));
|
||||
for (rule* r : rules) {
|
||||
expr_ref_vector constraints(m);
|
||||
expr_ref body_res(m);
|
||||
func_decl_ref pred(m);
|
||||
for (unsigned i = r->get_uninterpreted_tail_size(); i < r->get_tail_size(); ++i)
|
||||
constraints.push_back(r->get_tail(i));
|
||||
expr_ref body = mk_and(constraints);
|
||||
VERIFY(hmc.mk_horn(r->get_head(), body, pred, body_res));
|
||||
fmls.push_back(body_res);
|
||||
}
|
||||
expr_ref fml(m);
|
||||
fml = m.mk_or(fmls.size(), fmls.data());
|
||||
mc0->add(f, fml);
|
||||
mc0->add(f, mk_or(fmls));
|
||||
}
|
||||
m_context.add_model_converter(mc0);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,11 @@ Subsumption transformation (remove rule):
|
|||
P(x) := P(x) or (exists y . Q(y) & phi(x,y))
|
||||
|
||||
|
||||
For plan_inlining:
|
||||
TODO: order of rule inlining would affect model converter?
|
||||
so shouldn't model converter process inlined rules in a specific (topopologial) order?
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
|
@ -377,18 +382,15 @@ namespace datalog {
|
|||
return something_forbidden;
|
||||
}
|
||||
|
||||
void mk_rule_inliner::plan_inlining(rule_set const & orig)
|
||||
{
|
||||
void mk_rule_inliner::plan_inlining(rule_set const & orig) {
|
||||
count_pred_occurrences(orig);
|
||||
|
||||
scoped_ptr<rule_set> candidate_inlined_set = create_allowed_rule_set(orig);
|
||||
while (forbid_preds_from_cycles(*candidate_inlined_set)) {
|
||||
while (forbid_preds_from_cycles(*candidate_inlined_set))
|
||||
candidate_inlined_set = create_allowed_rule_set(orig);
|
||||
}
|
||||
|
||||
if (forbid_multiple_multipliers(orig, *candidate_inlined_set)) {
|
||||
if (forbid_multiple_multipliers(orig, *candidate_inlined_set))
|
||||
candidate_inlined_set = create_allowed_rule_set(orig);
|
||||
}
|
||||
|
||||
TRACE("dl", tout<<"rules to be inlined:\n" << (*candidate_inlined_set); );
|
||||
|
||||
|
@ -402,16 +404,13 @@ namespace datalog {
|
|||
for (rule_stratifier::item_set * stratum : comps) {
|
||||
SASSERT(stratum->size() == 1);
|
||||
func_decl * pred = *stratum->begin();
|
||||
for (rule * r : candidate_inlined_set->get_predicate_rules(pred)) {
|
||||
for (rule * r : candidate_inlined_set->get_predicate_rules(pred))
|
||||
transform_rule(orig, r, m_inlined_rules);
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("dl", tout << "inlined rules after mutual inlining:\n" << m_inlined_rules; );
|
||||
for (rule * r : m_inlined_rules)
|
||||
datalog::del_rule(m_mc, *r, l_undef);
|
||||
|
||||
for (rule * r : m_inlined_rules) {
|
||||
datalog::del_rule(m_mc, *r, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool mk_rule_inliner::transform_rule(rule_set const& orig, rule * r0, rule_set& tgt) {
|
||||
|
@ -437,20 +436,19 @@ namespace datalog {
|
|||
tgt.add_rule(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
modified = true;
|
||||
|
||||
func_decl * pred = r->get_decl(i);
|
||||
const rule_vector& pred_rules = m_inlined_rules.get_predicate_rules(pred);
|
||||
for (rule * inl_rule : pred_rules) {
|
||||
rule_ref inl_result(m_rm);
|
||||
if (try_to_inline_rule(*r.get(), *inl_rule, i, inl_result)) {
|
||||
if (try_to_inline_rule(*r.get(), *inl_rule, i, inl_result))
|
||||
todo.push_back(inl_result);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modified) {
|
||||
datalog::del_rule(m_mc, *r0, true);
|
||||
}
|
||||
if (modified)
|
||||
datalog::del_rule(m_mc, *r0, l_undef);
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
@ -473,7 +471,7 @@ namespace datalog {
|
|||
if (something_done && m_mc) {
|
||||
for (rule* r : orig) {
|
||||
if (inlining_allowed(orig, r->get_decl())) {
|
||||
datalog::del_rule(m_mc, *r, true);
|
||||
datalog::del_rule(m_mc, *r, l_undef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -558,7 +556,7 @@ namespace datalog {
|
|||
// nothing unifies with the tail atom, therefore the rule is unsatisfiable
|
||||
// (we can say this because relation pred doesn't have any ground facts either)
|
||||
res = nullptr;
|
||||
datalog::del_rule(m_mc, *r, false);
|
||||
datalog::del_rule(m_mc, *r, l_false);
|
||||
return true;
|
||||
}
|
||||
if (!is_oriented_rewriter(inlining_candidate, strat)) {
|
||||
|
@ -568,7 +566,7 @@ namespace datalog {
|
|||
goto process_next_tail;
|
||||
}
|
||||
if (!try_to_inline_rule(*r, *inlining_candidate, ti, res)) {
|
||||
datalog::del_rule(m_mc, *r, false);
|
||||
datalog::del_rule(m_mc, *r, l_false);
|
||||
res = nullptr;
|
||||
}
|
||||
return true;
|
||||
|
@ -768,7 +766,7 @@ namespace datalog {
|
|||
break;
|
||||
}
|
||||
|
||||
rule* r2 = acc[j].get();
|
||||
rule* r2 = acc.get(j);
|
||||
|
||||
// check that the head of r2 only unifies with this single body position.
|
||||
TRACE("dl", output_predicate(m_context, r2->get_head(), tout << "unify head: "); tout << "\n";);
|
||||
|
@ -801,7 +799,7 @@ namespace datalog {
|
|||
if (num_tail_unifiers == 1) {
|
||||
TRACE("dl", tout << "setting invalid: " << j << "\n";);
|
||||
valid.set(j, false);
|
||||
datalog::del_rule(m_mc, *r2, true);
|
||||
datalog::del_rule(m_mc, *r2, l_undef);
|
||||
del_rule(r2, j);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ z3_add_component(opt
|
|||
opt_lns.cpp
|
||||
opt_pareto.cpp
|
||||
opt_parse.cpp
|
||||
opt_preprocess.cpp
|
||||
optsmt.cpp
|
||||
opt_solver.cpp
|
||||
pb_sls.cpp
|
||||
|
|
|
@ -26,15 +26,15 @@ Author:
|
|||
|
||||
namespace opt {
|
||||
|
||||
bool is_maxlex(weights_t & _ws) {
|
||||
vector<rational> ws(_ws);
|
||||
std::sort(ws.begin(), ws.end());
|
||||
bool is_maxlex(vector<soft> const & _ws) {
|
||||
vector<soft> ws(_ws);
|
||||
std::sort(ws.begin(), ws.end(), [&](soft const& s1, soft const& s2) { return s1.weight < s2.weight; });
|
||||
ws.reverse();
|
||||
rational sum(0);
|
||||
for (rational const& w : ws) {
|
||||
for (auto const& [e, w, t] : ws) {
|
||||
sum += w;
|
||||
}
|
||||
for (rational const& w : ws) {
|
||||
for (auto const& [e, w, t] : ws) {
|
||||
if (sum > w + w) return false;
|
||||
sum -= w;
|
||||
}
|
||||
|
@ -185,8 +185,8 @@ namespace opt {
|
|||
|
||||
public:
|
||||
|
||||
maxlex(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& s):
|
||||
maxsmt_solver_base(c, ws, s),
|
||||
maxlex(maxsat_context& c, unsigned id, vector<soft>& s):
|
||||
maxsmt_solver_base(c, s, id),
|
||||
m(c.get_manager()),
|
||||
m_c(c) {
|
||||
// ensure that soft constraints are sorted with largest soft constraints first.
|
||||
|
@ -210,8 +210,8 @@ namespace opt {
|
|||
}
|
||||
};
|
||||
|
||||
maxsmt_solver_base* mk_maxlex(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& soft) {
|
||||
return alloc(maxlex, c, id, ws, soft);
|
||||
maxsmt_solver_base* mk_maxlex(maxsat_context& c, unsigned id, vector<soft>& soft) {
|
||||
return alloc(maxlex, c, id, soft);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ Notes:
|
|||
|
||||
namespace opt {
|
||||
|
||||
bool is_maxlex(weights_t & ws);
|
||||
bool is_maxlex(vector<soft> const & ws);
|
||||
|
||||
maxsmt_solver_base* mk_maxlex(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& soft);
|
||||
maxsmt_solver_base* mk_maxlex(maxsat_context& c, unsigned id, vector<soft>& soft);
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -72,7 +72,9 @@ class maxres : public maxsmt_solver_base {
|
|||
public:
|
||||
enum strategy_t {
|
||||
s_primal,
|
||||
s_primal_dual
|
||||
s_primal_dual,
|
||||
s_primal_binary,
|
||||
s_primal_binary_delay
|
||||
};
|
||||
private:
|
||||
struct stats {
|
||||
|
@ -95,7 +97,6 @@ private:
|
|||
expr_ref_vector const& soft() override { return i.m_asms; }
|
||||
};
|
||||
|
||||
unsigned m_index;
|
||||
stats m_stats;
|
||||
expr_ref_vector m_B;
|
||||
expr_ref_vector m_asms;
|
||||
|
@ -129,11 +130,10 @@ private:
|
|||
typedef ptr_vector<expr> exprs;
|
||||
|
||||
public:
|
||||
maxres(maxsat_context& c, unsigned index,
|
||||
weights_t& ws, expr_ref_vector const& soft,
|
||||
maxres(maxsat_context& c, unsigned index,
|
||||
vector<soft>& soft,
|
||||
strategy_t st):
|
||||
maxsmt_solver_base(c, ws, soft),
|
||||
m_index(index),
|
||||
maxsmt_solver_base(c, soft, index),
|
||||
m_B(m), m_asms(m), m_defs(m),
|
||||
m_new_core(m),
|
||||
m_mus(c.get_solver()),
|
||||
|
@ -159,6 +159,12 @@ public:
|
|||
case s_primal_dual:
|
||||
m_trace_id = "pd-maxres";
|
||||
break;
|
||||
case s_primal_binary:
|
||||
m_trace_id = "maxres-bin";
|
||||
break;
|
||||
case s_primal_binary_delay:
|
||||
m_trace_id = "maxres-bin-delay";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,6 +365,8 @@ public:
|
|||
m_defs.reset();
|
||||
switch(m_st) {
|
||||
case s_primal:
|
||||
case s_primal_binary:
|
||||
case s_primal_binary_delay:
|
||||
return mus_solver();
|
||||
case s_primal_dual:
|
||||
return primal_dual_solver();
|
||||
|
@ -534,8 +542,18 @@ public:
|
|||
expr_ref fml(m);
|
||||
SASSERT(!core.empty());
|
||||
TRACE("opt", display_vec(tout << "minimized core: ", core););
|
||||
IF_VERBOSE(10, display_vec(verbose_stream() << "core: ", core););
|
||||
max_resolve(core, w);
|
||||
IF_VERBOSE(10, display_vec(verbose_stream() << "core: ", core););
|
||||
switch (m_st) {
|
||||
case strategy_t::s_primal_binary:
|
||||
bin_max_resolve(core, w);
|
||||
break;
|
||||
case strategy_t::s_primal_binary_delay:
|
||||
bin_delay_max_resolve(core, w);
|
||||
break;
|
||||
default:
|
||||
max_resolve(core, w);
|
||||
break;
|
||||
}
|
||||
fml = mk_not(m, mk_and(m, core.size(), core.data()));
|
||||
add(fml);
|
||||
// save small cores such that lex-combinations of maxres can reuse these cores.
|
||||
|
@ -651,6 +669,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void max_resolve(exprs const& core, rational const& w) {
|
||||
SASSERT(!core.empty());
|
||||
expr_ref fml(m), asum(m);
|
||||
|
@ -701,6 +720,107 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void bin_max_resolve(exprs const& _core, rational const& w) {
|
||||
expr_ref_vector core(m, _core.size(), _core.data());
|
||||
expr_ref fml(m), cls(m);
|
||||
for (unsigned i = 0; i + 1 < core.size(); i += 2) {
|
||||
expr* a = core.get(i);
|
||||
expr* b = core.get(i + 1);
|
||||
expr* u = mk_fresh_bool("u");
|
||||
expr* v = mk_fresh_bool("v");
|
||||
// u = a or b
|
||||
// v = a and b
|
||||
cls = m.mk_or(a, b);
|
||||
fml = m.mk_implies(u, cls);
|
||||
add(fml);
|
||||
update_model(u, cls);
|
||||
m_defs.push_back(fml);
|
||||
cls = m.mk_and(a, b);
|
||||
fml = m.mk_implies(v, cls);
|
||||
add(fml);
|
||||
update_model(v, cls);
|
||||
m_defs.push_back(fml);
|
||||
new_assumption(u, w);
|
||||
core.push_back(v);
|
||||
}
|
||||
s().assert_expr(m.mk_not(core.back()));
|
||||
}
|
||||
|
||||
|
||||
struct unfold_record {
|
||||
ptr_vector<expr> ws;
|
||||
rational weight;
|
||||
};
|
||||
|
||||
obj_map<expr, unfold_record> m_unfold;
|
||||
rational m_unfold_upper;
|
||||
|
||||
void bin_delay_max_resolve(exprs const& _core, rational const& weight) {
|
||||
expr_ref_vector core(m, _core.size(), _core.data()), partial(m);
|
||||
expr_ref fml(m), cls(m);
|
||||
for (expr* c : core) {
|
||||
unfold_record r;
|
||||
if (!m_unfold.find(c, r))
|
||||
continue;
|
||||
IF_VERBOSE(2, verbose_stream() << "to unfold " << mk_pp(c, m) << "\n");
|
||||
for (expr* f : r.ws) {
|
||||
IF_VERBOSE(2, verbose_stream() << "unfold " << mk_pp(f, m) << "\n");
|
||||
new_assumption(f, r.weight);
|
||||
}
|
||||
m_unfold_upper -= r.weight * rational(r.ws.size() - 1);
|
||||
m_unfold.remove(c);
|
||||
}
|
||||
|
||||
for (expr* _ : core)
|
||||
partial.push_back(nullptr);
|
||||
|
||||
std::cout << "Core size " << core.size() << "\n";
|
||||
|
||||
if (core.size() > 2)
|
||||
m_unfold_upper += rational(core.size()-2)*weight;
|
||||
|
||||
expr* w = nullptr;
|
||||
for (unsigned i = 0; i + 1 < core.size(); i += 2) {
|
||||
expr* a = core.get(i);
|
||||
expr* b = core.get(i + 1);
|
||||
expr* u = mk_fresh_bool("u");
|
||||
expr* v = mk_fresh_bool("v");
|
||||
// u = a or b
|
||||
// v = a and b
|
||||
cls = m.mk_or(a, b);
|
||||
fml = m.mk_implies(u, cls);
|
||||
add(fml);
|
||||
update_model(u, cls);
|
||||
m_defs.push_back(fml);
|
||||
cls = m.mk_and(a, b);
|
||||
fml = m.mk_implies(v, cls);
|
||||
add(fml);
|
||||
update_model(v, cls);
|
||||
m_defs.push_back(fml);
|
||||
core.push_back(v);
|
||||
|
||||
// w = u and w1 and w2
|
||||
unfold_record r;
|
||||
r.ws.push_back(u);
|
||||
if (partial.get(i))
|
||||
r.ws.push_back(partial.get(i));
|
||||
if (partial.get(i + 1))
|
||||
r.ws.push_back(partial.get(i + 1));
|
||||
m_trail.append(r.ws.size(), r.ws.data());
|
||||
w = mk_fresh_bool("w");
|
||||
cls = m.mk_and(r.ws);
|
||||
fml = m.mk_implies(w, cls);
|
||||
partial.push_back(w);
|
||||
add(fml);
|
||||
update_model(w, cls);
|
||||
m_defs.push_back(fml);
|
||||
m_unfold.insert(w, r);
|
||||
}
|
||||
new_assumption(w, weight);
|
||||
s().assert_expr(m.mk_not(core.back()));
|
||||
}
|
||||
|
||||
// cs is a correction set (a complement of a (maximal) satisfying assignment).
|
||||
void cs_max_resolve(exprs const& cs, rational const& w) {
|
||||
if (cs.empty()) return;
|
||||
|
@ -780,7 +900,7 @@ public:
|
|||
}
|
||||
|
||||
rational cost(model& mdl) {
|
||||
rational upper(0);
|
||||
rational upper = m_unfold_upper;
|
||||
for (soft& s : m_soft)
|
||||
if (!mdl.is_true(s.s))
|
||||
upper += s.weight;
|
||||
|
@ -791,11 +911,10 @@ public:
|
|||
improve_model(mdl);
|
||||
mdl->set_model_completion(true);
|
||||
unsigned correction_set_size = 0;
|
||||
for (expr* a : m_asms) {
|
||||
if (mdl->is_false(a)) {
|
||||
for (expr* a : m_asms)
|
||||
if (mdl->is_false(a))
|
||||
++correction_set_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_csmodel.get() || correction_set_size < m_correction_set_size) {
|
||||
m_csmodel = mdl;
|
||||
m_correction_set_size = correction_set_size;
|
||||
|
@ -810,22 +929,22 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if (!m_c.verify_model(m_index, mdl.get(), upper)) {
|
||||
if (!m_c.verify_model(m_index, mdl.get(), upper))
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned num_assertions = s().get_num_assertions();
|
||||
m_model = mdl;
|
||||
m_c.model_updated(mdl.get());
|
||||
|
||||
TRACE("opt", tout << "updated upper: " << upper << "\n";);
|
||||
|
||||
for (soft& s : m_soft) {
|
||||
for (soft& s : m_soft)
|
||||
s.set_value(m_model->is_true(s.s));
|
||||
}
|
||||
|
||||
verify_assignment();
|
||||
|
||||
m_upper = upper;
|
||||
if (num_assertions == s().get_num_assertions())
|
||||
m_upper = upper;
|
||||
|
||||
trace();
|
||||
|
||||
|
@ -876,23 +995,18 @@ public:
|
|||
}
|
||||
|
||||
lbool init_local() {
|
||||
m_lower.reset();
|
||||
m_trail.reset();
|
||||
lbool is_sat = l_true;
|
||||
obj_map<expr, rational> new_soft;
|
||||
is_sat = find_mutexes(new_soft);
|
||||
if (is_sat != l_true) {
|
||||
return is_sat;
|
||||
}
|
||||
for (auto const& kv : new_soft) {
|
||||
add_soft(kv.m_key, kv.m_value);
|
||||
}
|
||||
for (auto const& [e, w, t] : m_soft)
|
||||
add_soft(e, w);
|
||||
m_max_upper = m_upper;
|
||||
m_found_feasible_optimum = false;
|
||||
m_last_index = 0;
|
||||
add_upper_bound_block();
|
||||
m_csmodel = nullptr;
|
||||
m_correction_set_size = 0;
|
||||
m_unfold.reset();
|
||||
m_unfold_upper = 0;
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
@ -954,12 +1068,22 @@ public:
|
|||
};
|
||||
|
||||
opt::maxsmt_solver_base* opt::mk_maxres(
|
||||
maxsat_context& c, unsigned id, weights_t& ws, expr_ref_vector const& soft) {
|
||||
return alloc(maxres, c, id, ws, soft, maxres::s_primal);
|
||||
maxsat_context& c, unsigned id, vector<soft>& soft) {
|
||||
return alloc(maxres, c, id, soft, maxres::s_primal);
|
||||
}
|
||||
|
||||
opt::maxsmt_solver_base* opt::mk_maxres_binary(
|
||||
maxsat_context& c, unsigned id, vector<soft>& soft) {
|
||||
return alloc(maxres, c, id, soft, maxres::s_primal_binary);
|
||||
}
|
||||
|
||||
opt::maxsmt_solver_base* opt::mk_maxres_binary_delay(
|
||||
maxsat_context& c, unsigned id, vector<soft>& soft) {
|
||||
return alloc(maxres, c, id, soft, maxres::s_primal_binary_delay);
|
||||
}
|
||||
|
||||
opt::maxsmt_solver_base* opt::mk_primal_dual_maxres(
|
||||
maxsat_context& c, unsigned id, weights_t& ws, expr_ref_vector const& soft) {
|
||||
return alloc(maxres, c, id, ws, soft, maxres::s_primal_dual);
|
||||
maxsat_context& c, unsigned id, vector<soft>& soft) {
|
||||
return alloc(maxres, c, id, soft, maxres::s_primal_dual);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,13 @@ Notes:
|
|||
|
||||
namespace opt {
|
||||
|
||||
maxsmt_solver_base* mk_maxres(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& soft);
|
||||
maxsmt_solver_base* mk_maxres(maxsat_context& c, unsigned id, vector<soft>& soft);
|
||||
|
||||
maxsmt_solver_base* mk_primal_dual_maxres(maxsat_context& c, unsigned id, weights_t & ws, expr_ref_vector const& soft);
|
||||
maxsmt_solver_base* mk_maxres_binary(maxsat_context& c, unsigned id, vector<soft>& soft);
|
||||
|
||||
maxsmt_solver_base* mk_maxres_binary_delay(maxsat_context& c, unsigned id, vector<soft>& soft);
|
||||
|
||||
maxsmt_solver_base* mk_primal_dual_maxres(maxsat_context& c, unsigned id, vector<soft>& soft);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -28,29 +28,34 @@ Notes:
|
|||
#include "opt/wmax.h"
|
||||
#include "opt/opt_params.hpp"
|
||||
#include "opt/opt_context.h"
|
||||
#include "opt/opt_preprocess.h"
|
||||
#include "smt/theory_wmaxsat.h"
|
||||
#include "smt/theory_pb.h"
|
||||
|
||||
|
||||
namespace opt {
|
||||
|
||||
maxsmt_solver_base::maxsmt_solver_base(
|
||||
maxsat_context& c, vector<rational> const& ws, expr_ref_vector const& softs):
|
||||
maxsmt_solver_base::maxsmt_solver_base(maxsat_context& c, vector<soft>& s, unsigned index):
|
||||
m(c.get_manager()),
|
||||
m_c(c),
|
||||
m_index(index),
|
||||
m_soft(s),
|
||||
m_assertions(m),
|
||||
m_trail(m) {
|
||||
c.get_base_model(m_model);
|
||||
SASSERT(m_model);
|
||||
updt_params(c.params());
|
||||
for (unsigned i = 0; i < ws.size(); ++i) {
|
||||
m_soft.push_back(soft(expr_ref(softs.get(i), m), ws[i], false));
|
||||
}
|
||||
}
|
||||
|
||||
void maxsmt_solver_base::updt_params(params_ref& p) {
|
||||
m_params.copy(p);
|
||||
}
|
||||
}
|
||||
|
||||
void maxsmt_solver_base::reset_upper() {
|
||||
m_upper = m_lower;
|
||||
for (soft& s : m_soft)
|
||||
m_upper += s.weight;
|
||||
}
|
||||
|
||||
solver& maxsmt_solver_base::s() {
|
||||
return m_c.get_solver();
|
||||
|
@ -82,14 +87,24 @@ namespace opt {
|
|||
m_upper.reset();
|
||||
for (soft& s : m_soft) {
|
||||
s.set_value(m.is_true(s.s));
|
||||
if (!s.is_true()) m_upper += s.weight;
|
||||
if (!s.is_true())
|
||||
m_upper += s.weight;
|
||||
}
|
||||
|
||||
// return true;
|
||||
|
||||
preprocess pp(s());
|
||||
rational lower(0);
|
||||
bool r = pp(m_soft, lower);
|
||||
|
||||
m_c.add_offset(m_index, lower);
|
||||
m_upper -= lower;
|
||||
|
||||
TRACE("opt",
|
||||
tout << "upper: " << m_upper << " assignments: ";
|
||||
tout << "lower " << lower << " upper: " << m_upper << " assignments: ";
|
||||
for (soft& s : m_soft) tout << (s.is_true()?"T":"F");
|
||||
tout << "\n";);
|
||||
return true;
|
||||
return r;
|
||||
}
|
||||
|
||||
void maxsmt_solver_base::set_mus(bool f) {
|
||||
|
@ -153,80 +168,15 @@ namespace opt {
|
|||
|
||||
void maxsmt_solver_base::trace_bounds(char const * solver) {
|
||||
IF_VERBOSE(1,
|
||||
rational l = m_adjust_value(m_lower);
|
||||
rational u = m_adjust_value(m_upper);
|
||||
rational l = m_c.adjust(m_index, m_lower);
|
||||
rational u = m_c.adjust(m_index, m_upper);
|
||||
if (l > u) std::swap(l, u);
|
||||
verbose_stream() << "(opt." << solver << " [" << l << ":" << u << "])\n";);
|
||||
}
|
||||
|
||||
lbool maxsmt_solver_base::find_mutexes(obj_map<expr, rational>& new_soft) {
|
||||
m_lower.reset();
|
||||
expr_ref_vector fmls(m);
|
||||
for (soft& s : m_soft) {
|
||||
new_soft.insert(s.s, s.weight);
|
||||
fmls.push_back(s.s);
|
||||
}
|
||||
vector<expr_ref_vector> mutexes;
|
||||
lbool is_sat = s().find_mutexes(fmls, mutexes);
|
||||
if (is_sat != l_true) {
|
||||
return is_sat;
|
||||
}
|
||||
for (auto& mux : mutexes) {
|
||||
process_mutex(mux, new_soft);
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
struct maxsmt_compare_soft {
|
||||
obj_map<expr, rational> const& m_soft;
|
||||
maxsmt_compare_soft(obj_map<expr, rational> const& soft): m_soft(soft) {}
|
||||
bool operator()(expr* a, expr* b) const {
|
||||
return m_soft.find(a) > m_soft.find(b);
|
||||
}
|
||||
};
|
||||
|
||||
void maxsmt_solver_base::process_mutex(expr_ref_vector& mutex, obj_map<expr, rational>& new_soft) {
|
||||
TRACE("opt",
|
||||
for (expr* e : mutex) {
|
||||
tout << mk_pp(e, m) << " |-> " << new_soft.find(e) << "\n";
|
||||
});
|
||||
if (mutex.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
maxsmt_compare_soft cmp(new_soft);
|
||||
ptr_vector<expr> _mutex(mutex.size(), mutex.data());
|
||||
std::sort(_mutex.begin(), _mutex.end(), cmp);
|
||||
mutex.reset();
|
||||
mutex.append(_mutex.size(), _mutex.data());
|
||||
|
||||
rational weight(0), sum1(0), sum2(0);
|
||||
vector<rational> weights;
|
||||
for (expr* e : mutex) {
|
||||
rational w = new_soft.find(e);
|
||||
weights.push_back(w);
|
||||
sum1 += w;
|
||||
new_soft.remove(e);
|
||||
}
|
||||
for (unsigned i = mutex.size(); i-- > 0; ) {
|
||||
expr_ref soft(m.mk_or(i+1, mutex.data()), m);
|
||||
m_trail.push_back(soft);
|
||||
rational w = weights[i];
|
||||
weight = w - weight;
|
||||
m_lower += weight*rational(i);
|
||||
IF_VERBOSE(1, verbose_stream() << "(opt.maxsat mutex size: " << i + 1 << " weight: " << weight << ")\n";);
|
||||
sum2 += weight*rational(i+1);
|
||||
new_soft.insert(soft, weight);
|
||||
for (; i > 0 && weights[i-1] == w; --i) {}
|
||||
weight = w;
|
||||
}
|
||||
SASSERT(sum1 == sum2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
maxsmt::maxsmt(maxsat_context& c, unsigned index):
|
||||
m(c.get_manager()), m_c(c), m_index(index),
|
||||
m_soft_constraints(m), m_answer(m) {}
|
||||
m(c.get_manager()), m_c(c), m_index(index), m_answer(m) {}
|
||||
|
||||
lbool maxsmt::operator()() {
|
||||
lbool is_sat = l_undef;
|
||||
|
@ -235,30 +185,35 @@ namespace opt {
|
|||
symbol const& maxsat_engine = m_c.maxsat_engine();
|
||||
IF_VERBOSE(1, verbose_stream() << "(maxsmt)\n";);
|
||||
TRACE("opt_verbose", s().display(tout << "maxsmt\n") << "\n";);
|
||||
if (optp.maxlex_enable() && is_maxlex(m_weights)) {
|
||||
m_msolver = mk_maxlex(m_c, m_index, m_weights, m_soft_constraints);
|
||||
if (optp.maxlex_enable() && is_maxlex(m_soft)) {
|
||||
m_msolver = mk_maxlex(m_c, m_index, m_soft);
|
||||
}
|
||||
else if (m_soft_constraints.empty() || maxsat_engine == symbol("maxres") || maxsat_engine == symbol::null) {
|
||||
m_msolver = mk_maxres(m_c, m_index, m_weights, m_soft_constraints);
|
||||
else if (m_soft.empty() || maxsat_engine == symbol("maxres") || maxsat_engine == symbol::null) {
|
||||
m_msolver = mk_maxres(m_c, m_index, m_soft);
|
||||
}
|
||||
else if (maxsat_engine == symbol("maxres-bin")) {
|
||||
m_msolver = mk_maxres_binary(m_c, m_index, m_soft);
|
||||
}
|
||||
else if (maxsat_engine == symbol("maxres-bin-delay")) {
|
||||
m_msolver = mk_maxres_binary_delay(m_c, m_index, m_soft);
|
||||
}
|
||||
else if (maxsat_engine == symbol("pd-maxres")) {
|
||||
m_msolver = mk_primal_dual_maxres(m_c, m_index, m_weights, m_soft_constraints);
|
||||
m_msolver = mk_primal_dual_maxres(m_c, m_index, m_soft);
|
||||
}
|
||||
else if (maxsat_engine == symbol("wmax")) {
|
||||
m_msolver = mk_wmax(m_c, m_weights, m_soft_constraints);
|
||||
m_msolver = mk_wmax(m_c, m_soft, m_index);
|
||||
}
|
||||
else if (maxsat_engine == symbol("sortmax")) {
|
||||
m_msolver = mk_sortmax(m_c, m_weights, m_soft_constraints);
|
||||
m_msolver = mk_sortmax(m_c, m_soft, m_index);
|
||||
}
|
||||
else {
|
||||
auto str = maxsat_engine.str();
|
||||
warning_msg("solver %s is not recognized, using default 'maxres'", str.c_str());
|
||||
m_msolver = mk_maxres(m_c, m_index, m_weights, m_soft_constraints);
|
||||
m_msolver = mk_maxres(m_c, m_index, m_soft);
|
||||
}
|
||||
|
||||
if (m_msolver) {
|
||||
m_msolver->updt_params(m_params);
|
||||
m_msolver->set_adjust_value(m_adjust_value);
|
||||
is_sat = l_undef;
|
||||
try {
|
||||
is_sat = (*m_msolver)();
|
||||
|
@ -282,14 +237,13 @@ namespace opt {
|
|||
return is_sat;
|
||||
}
|
||||
|
||||
void maxsmt::set_adjust_value(adjust_value& adj) {
|
||||
m_adjust_value = adj;
|
||||
void maxsmt::reset_upper() {
|
||||
if (m_msolver) {
|
||||
m_msolver->set_adjust_value(m_adjust_value);
|
||||
m_msolver->reset_upper();
|
||||
m_upper = m_msolver->get_upper();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void maxsmt::verify_assignment() {
|
||||
// TBD: have to use a different solver
|
||||
// because we don't push local scope any longer.
|
||||
|
@ -311,7 +265,7 @@ namespace opt {
|
|||
rational q = m_msolver->get_lower();
|
||||
if (q > r) r = q;
|
||||
}
|
||||
return m_adjust_value(r);
|
||||
return m_c.adjust(m_index, r);
|
||||
}
|
||||
|
||||
rational maxsmt::get_upper() const {
|
||||
|
@ -320,7 +274,7 @@ namespace opt {
|
|||
rational q = m_msolver->get_upper();
|
||||
if (q < r) r = q;
|
||||
}
|
||||
return m_adjust_value(r);
|
||||
return m_c.adjust(m_index, r);
|
||||
}
|
||||
|
||||
void maxsmt::update_lower(rational const& r) {
|
||||
|
@ -348,39 +302,32 @@ namespace opt {
|
|||
SASSERT(w.is_pos());
|
||||
unsigned index = 0;
|
||||
if (m_soft_constraint_index.find(f, index)) {
|
||||
m_weights[index] += w;
|
||||
m_soft[index].weight += w;
|
||||
}
|
||||
else {
|
||||
m_soft_constraint_index.insert(f, m_weights.size());
|
||||
m_soft_constraints.push_back(f);
|
||||
m_weights.push_back(w);
|
||||
m_soft_constraint_index.insert(f, m_soft.size());
|
||||
m_soft.push_back(soft(expr_ref(f, m), w, false));
|
||||
}
|
||||
m_upper += w;
|
||||
}
|
||||
|
||||
struct cmp_first {
|
||||
bool operator()(std::pair<unsigned, rational> const& x, std::pair<unsigned, rational> const& y) const {
|
||||
return x.first < y.first;
|
||||
return x.second < y.second;
|
||||
}
|
||||
};
|
||||
|
||||
void maxsmt::display_answer(std::ostream& out) const {
|
||||
vector<std::pair<unsigned, rational>> sorted_weights;
|
||||
unsigned n = m_weights.size();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
sorted_weights.push_back(std::make_pair(i, m_weights[i]));
|
||||
}
|
||||
std::sort(sorted_weights.begin(), sorted_weights.end(), cmp_first());
|
||||
sorted_weights.reverse();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
unsigned idx = sorted_weights[i].first;
|
||||
expr* e = m_soft_constraints[idx];
|
||||
|
||||
unsigned idx = 0;
|
||||
for (auto const & [_e, w, t] : m_soft) {
|
||||
expr* e = _e.get();
|
||||
bool is_not = m.is_not(e, e);
|
||||
out << m_weights[idx] << ": " << mk_pp(e, m)
|
||||
out << w << ": " << mk_pp(e, m)
|
||||
<< ((is_not != get_assignment(idx))?" |-> true ":" |-> false ")
|
||||
<< "\n";
|
||||
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -420,6 +367,7 @@ namespace opt {
|
|||
model_ref m_model;
|
||||
ref<generic_model_converter> m_fm;
|
||||
symbol m_maxsat_engine;
|
||||
vector<rational> m_offsets;
|
||||
public:
|
||||
solver_maxsat_context(params_ref& p, solver* s, model * m):
|
||||
m_params(p),
|
||||
|
@ -444,6 +392,14 @@ namespace opt {
|
|||
bool verify_model(unsigned id, model* mdl, rational const& v) override { return true; };
|
||||
void set_model(model_ref& _m) override { m_model = _m; }
|
||||
void model_updated(model* mdl) override { } // no-op
|
||||
rational adjust(unsigned id, rational const& r) override {
|
||||
m_offsets.reserve(id+1);
|
||||
return r + m_offsets[id];
|
||||
}
|
||||
void add_offset(unsigned id, rational const& r) override {
|
||||
m_offsets.reserve(id+1);
|
||||
m_offsets[id] += r;
|
||||
}
|
||||
};
|
||||
|
||||
lbool maxsmt_wrapper::operator()(vector<std::pair<expr*,rational>>& soft) {
|
||||
|
|
|
@ -34,8 +34,6 @@ namespace opt {
|
|||
class maxsat_context;
|
||||
|
||||
class maxsmt_solver {
|
||||
protected:
|
||||
adjust_value m_adjust_value;
|
||||
public:
|
||||
virtual ~maxsmt_solver() {}
|
||||
virtual lbool operator()() = 0;
|
||||
|
@ -45,28 +43,30 @@ namespace opt {
|
|||
virtual void collect_statistics(statistics& st) const = 0;
|
||||
virtual void get_model(model_ref& mdl, svector<symbol>& labels) = 0;
|
||||
virtual void updt_params(params_ref& p) = 0;
|
||||
void set_adjust_value(adjust_value& adj) { m_adjust_value = adj; }
|
||||
|
||||
};
|
||||
|
||||
// ---------------------------------------------
|
||||
// base class with common utilities used
|
||||
// by maxsmt solvers
|
||||
//
|
||||
//
|
||||
|
||||
struct soft {
|
||||
expr_ref s;
|
||||
rational weight;
|
||||
lbool value;
|
||||
void set_value(bool t) { value = t?l_true:l_undef; }
|
||||
void set_value(lbool t) { value = t; }
|
||||
bool is_true() const { return value == l_true; }
|
||||
soft(expr_ref const& s, rational const& w, bool t): s(s), weight(w), value(t?l_true:l_undef) {}
|
||||
};
|
||||
|
||||
class maxsmt_solver_base : public maxsmt_solver {
|
||||
protected:
|
||||
struct soft {
|
||||
expr_ref s;
|
||||
rational weight;
|
||||
lbool value;
|
||||
void set_value(bool t) { value = t?l_true:l_undef; }
|
||||
void set_value(lbool t) { value = t; }
|
||||
bool is_true() const { return value == l_true; }
|
||||
soft(expr_ref const& s, rational const& w, bool t): s(s), weight(w), value(t?l_true:l_undef) {}
|
||||
};
|
||||
ast_manager& m;
|
||||
maxsat_context& m_c;
|
||||
vector<soft> m_soft;
|
||||
maxsat_context& m_c;
|
||||
unsigned m_index;
|
||||
vector<soft>& m_soft;
|
||||
expr_ref_vector m_assertions;
|
||||
expr_ref_vector m_trail;
|
||||
rational m_lower;
|
||||
|
@ -76,8 +76,8 @@ namespace opt {
|
|||
params_ref m_params; // config
|
||||
|
||||
public:
|
||||
maxsmt_solver_base(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft);
|
||||
|
||||
maxsmt_solver_base(maxsat_context& c, vector<soft>& soft, unsigned index);
|
||||
|
||||
~maxsmt_solver_base() override {}
|
||||
rational get_lower() const override { return m_lower; }
|
||||
rational get_upper() const override { return m_upper; }
|
||||
|
@ -102,16 +102,13 @@ namespace opt {
|
|||
smt::theory_wmaxsat& operator()();
|
||||
};
|
||||
|
||||
lbool find_mutexes(obj_map<expr, rational>& new_soft);
|
||||
void reset_upper();
|
||||
|
||||
|
||||
protected:
|
||||
void enable_sls(bool force);
|
||||
void trace_bounds(char const* solver);
|
||||
|
||||
void process_mutex(expr_ref_vector& mutex, obj_map<expr, rational>& new_soft);
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -124,13 +121,11 @@ namespace opt {
|
|||
maxsat_context& m_c;
|
||||
unsigned m_index;
|
||||
scoped_ptr<maxsmt_solver_base> m_msolver;
|
||||
expr_ref_vector m_soft_constraints;
|
||||
vector<soft> m_soft;
|
||||
obj_map<expr, unsigned> m_soft_constraint_index;
|
||||
expr_ref_vector m_answer;
|
||||
vector<rational> m_weights;
|
||||
rational m_lower;
|
||||
rational m_upper;
|
||||
adjust_value m_adjust_value;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
params_ref m_params;
|
||||
|
@ -139,10 +134,9 @@ namespace opt {
|
|||
lbool operator()();
|
||||
void updt_params(params_ref& p);
|
||||
void add(expr* f, rational const& w);
|
||||
void set_adjust_value(adjust_value& adj);
|
||||
unsigned size() const { return m_soft_constraints.size(); }
|
||||
expr* operator[](unsigned idx) const { return m_soft_constraints[idx]; }
|
||||
rational weight(unsigned idx) const { return m_weights[idx]; }
|
||||
unsigned size() const { return m_soft.size(); }
|
||||
expr* operator[](unsigned idx) const { return m_soft[idx].s; }
|
||||
rational weight(unsigned idx) const { return m_soft[idx].weight; }
|
||||
void commit_assignment();
|
||||
rational get_lower() const;
|
||||
rational get_upper() const;
|
||||
|
@ -153,6 +147,7 @@ namespace opt {
|
|||
void display_answer(std::ostream& out) const;
|
||||
void collect_statistics(statistics& st) const;
|
||||
void model_updated(model* mdl);
|
||||
void reset_upper();
|
||||
private:
|
||||
bool is_maxsat_problem(weights_t& ws) const;
|
||||
void verify_assignment();
|
||||
|
|
|
@ -185,17 +185,36 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::set_hard_constraints(expr_ref_vector const& fmls) {
|
||||
if (m_scoped_state.set(fmls)) {
|
||||
if (m_calling_on_model) {
|
||||
for (expr* f : fmls)
|
||||
add_hard_constraint(f);
|
||||
return;
|
||||
}
|
||||
if (m_scoped_state.set(fmls))
|
||||
clear_state();
|
||||
}
|
||||
|
||||
void context::add_hard_constraint(expr* f) {
|
||||
if (m_calling_on_model) {
|
||||
get_solver().assert_expr(f);
|
||||
for (auto const& [k, v] : m_maxsmts)
|
||||
v->reset_upper();
|
||||
for (unsigned i = 0; i < num_objectives(); ++i) {
|
||||
auto const& o = m_scoped_state.m_objectives[i];
|
||||
if (o.m_type != O_MAXSMT)
|
||||
m_optsmt.update_upper(o.m_index, inf_eps::infinity());
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_scoped_state.add(f);
|
||||
clear_state();
|
||||
}
|
||||
}
|
||||
|
||||
void context::add_hard_constraint(expr* f) {
|
||||
m_scoped_state.add(f);
|
||||
clear_state();
|
||||
}
|
||||
|
||||
|
||||
void context::add_hard_constraint(expr* f, expr* t) {
|
||||
if (m_calling_on_model)
|
||||
throw default_exception("adding soft constraints is not supported during callbacks");
|
||||
m_scoped_state.m_asms.push_back(t);
|
||||
m_scoped_state.add(m.mk_implies(t, f));
|
||||
clear_state();
|
||||
|
@ -301,7 +320,7 @@ namespace opt {
|
|||
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n");
|
||||
|
||||
lbool is_sat = s.check_sat(asms.size(),asms.data());
|
||||
lbool is_sat = s.check_sat(asms.size(), asms.data());
|
||||
|
||||
TRACE("opt", s.display(tout << "initial search result: " << is_sat << "\n"););
|
||||
if (is_sat != l_false) {
|
||||
|
@ -379,7 +398,7 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::set_model(model_ref& m) {
|
||||
m_model = m;
|
||||
m_model = m;
|
||||
opt_params optp(m_params);
|
||||
if (optp.dump_models() && m) {
|
||||
model_ref md = m->copy();
|
||||
|
@ -389,6 +408,7 @@ namespace opt {
|
|||
model_ref md = m->copy();
|
||||
if (!m_model_fixed.contains(md.get()))
|
||||
fix_model(md);
|
||||
flet<bool> _calling(m_calling_on_model, true);
|
||||
m_on_model_eh(m_on_model_ctx, md);
|
||||
m_model_fixed.pop_back();
|
||||
}
|
||||
|
@ -910,7 +930,8 @@ namespace opt {
|
|||
bool context::is_maxsat(expr* fml, expr_ref_vector& terms,
|
||||
vector<rational>& weights, rational& offset,
|
||||
bool& neg, symbol& id, expr_ref& orig_term, unsigned& index) {
|
||||
if (!is_app(fml)) return false;
|
||||
if (!is_app(fml))
|
||||
return false;
|
||||
neg = false;
|
||||
orig_term = nullptr;
|
||||
index = 0;
|
||||
|
@ -1085,8 +1106,7 @@ namespace opt {
|
|||
obj.m_weights.append(weights);
|
||||
obj.m_adjust_value.set_offset(offset);
|
||||
obj.m_adjust_value.set_negate(neg);
|
||||
m_maxsmts.find(id)->set_adjust_value(obj.m_adjust_value);
|
||||
TRACE("opt", tout << "maxsat: " << id << " offset:" << offset << "\n";
|
||||
TRACE("opt", tout << "maxsat: " << neg << " " << id << " offset: " << offset << "\n";
|
||||
tout << terms << "\n";);
|
||||
}
|
||||
else if (is_maximize(fml, tr, orig_term, index)) {
|
||||
|
@ -1138,7 +1158,14 @@ namespace opt {
|
|||
#endif
|
||||
}
|
||||
|
||||
rational context::adjust(unsigned id, rational const& v) {
|
||||
return m_objectives[id].m_adjust_value(v);
|
||||
}
|
||||
|
||||
void context::add_offset(unsigned id, rational const& o) {
|
||||
m_objectives[id].m_adjust_value.add_offset(o);
|
||||
}
|
||||
|
||||
bool context::verify_model(unsigned index, model* md, rational const& _v) {
|
||||
rational r;
|
||||
app_ref term = m_objectives[index].m_term;
|
||||
|
@ -1321,24 +1348,21 @@ namespace opt {
|
|||
break;
|
||||
}
|
||||
case O_MAXSMT: {
|
||||
bool ok = true;
|
||||
for (unsigned j = 0; ok && j < obj.m_terms.size(); ++j) {
|
||||
for (unsigned j = 0; j < obj.m_terms.size(); ++j) {
|
||||
val = (*m_model)(obj.m_terms[j]);
|
||||
TRACE("opt", tout << mk_pp(obj.m_terms[j], m) << " " << val << "\n";);
|
||||
if (!m.is_true(val)) {
|
||||
if (!m.is_true(val))
|
||||
r += obj.m_weights[j];
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
maxsmt& ms = *m_maxsmts.find(obj.m_id);
|
||||
if (is_lower) {
|
||||
ms.update_upper(r);
|
||||
TRACE("opt", tout << "update upper from " << r << " to " << ms.get_upper() << "\n";);
|
||||
}
|
||||
else {
|
||||
ms.update_lower(r);
|
||||
TRACE("opt", tout << "update lower from " << r << " to " << ms.get_lower() << "\n";);
|
||||
}
|
||||
|
||||
maxsmt& ms = *m_maxsmts.find(obj.m_id);
|
||||
if (is_lower) {
|
||||
ms.update_upper(r);
|
||||
TRACE("opt", tout << "update upper from " << r << " to " << ms.get_upper() << "\n";);
|
||||
}
|
||||
else {
|
||||
ms.update_lower(r);
|
||||
TRACE("opt", tout << "update lower from " << r << " to " << ms.get_lower() << "\n";);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@ namespace opt {
|
|||
virtual smt::context& smt_context() = 0; // access SMT context for SMT based MaxSMT solver (wmax requires SMT core)
|
||||
virtual unsigned num_objectives() = 0;
|
||||
virtual bool verify_model(unsigned id, model* mdl, rational const& v) = 0;
|
||||
virtual rational adjust(unsigned id, rational const& v) = 0;
|
||||
virtual void add_offset(unsigned id, rational const& o) = 0;
|
||||
virtual void set_model(model_ref& _m) = 0;
|
||||
virtual void model_updated(model* mdl) = 0;
|
||||
};
|
||||
|
@ -93,7 +95,7 @@ namespace opt {
|
|||
app_ref m_term; // for maximize, minimize term
|
||||
expr_ref_vector m_terms; // for maxsmt
|
||||
vector<rational> m_weights; // for maxsmt
|
||||
adjust_value m_adjust_value;
|
||||
adjust_value m_adjust_value;
|
||||
symbol m_id; // for maxsmt
|
||||
unsigned m_index; // for maximize/minimize index
|
||||
|
||||
|
@ -165,6 +167,7 @@ namespace opt {
|
|||
ast_manager& m;
|
||||
on_model_t m_on_model_ctx;
|
||||
std::function<void(on_model_t&, model_ref&)> m_on_model_eh;
|
||||
bool m_calling_on_model = false;
|
||||
arith_util m_arith;
|
||||
bv_util m_bv;
|
||||
expr_ref_vector m_hard_constraints;
|
||||
|
@ -268,11 +271,14 @@ namespace opt {
|
|||
|
||||
void model_updated(model* mdl) override;
|
||||
|
||||
rational adjust(unsigned id, rational const& v) override;
|
||||
|
||||
void add_offset(unsigned id, rational const& o) override;
|
||||
|
||||
void register_on_model(on_model_t& ctx, std::function<void(on_model_t&, model_ref&)>& on_model) {
|
||||
m_on_model_ctx = ctx;
|
||||
m_on_model_eh = on_model;
|
||||
}
|
||||
|
||||
|
||||
void collect_timer_stats(statistics& st) const {
|
||||
if (m_time != 0)
|
||||
|
|
32
src/opt/opt_mux.h
Normal file
32
src/opt/opt_mux.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*++
|
||||
Copyright (c) 2021 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_mux.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Find mutexes - at most 1 constraints and modify soft constraints and bounds.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2022-04-11
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opt/maxsmt.h"
|
||||
|
||||
namespace opt {
|
||||
|
||||
class mux {
|
||||
ast_manager& m;
|
||||
solver& s;
|
||||
|
||||
public:
|
||||
mux(solver& s);
|
||||
lbool operator()(vector<soft>& soft, rational& bound);
|
||||
};
|
||||
};
|
|
@ -2,7 +2,7 @@ def_module_params('opt',
|
|||
description='optimization parameters',
|
||||
export=True,
|
||||
params=(('optsmt_engine', SYMBOL, 'basic', "select optimization engine: 'basic', 'symba'"),
|
||||
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres'"),
|
||||
('maxsat_engine', SYMBOL, 'maxres', "select engine for maxsat: 'core_maxsat', 'wmax', 'maxres', 'pd-maxres', 'maxres-bin', 'maxres-bin-delay'"),
|
||||
('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', 'box'"),
|
||||
('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'),
|
||||
('dump_models', BOOL, False, 'display intermediary models to stdout'),
|
||||
|
|
195
src/opt/opt_preprocess.cpp
Normal file
195
src/opt/opt_preprocess.cpp
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*++
|
||||
Copyright (c) 2021 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_preprocess.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Pre-processing for MaxSMT
|
||||
|
||||
Find mutexes - at most 1 constraints and modify soft constraints and bounds.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2022-04-11
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opt/opt_preprocess.h"
|
||||
#include "util/max_cliques.h"
|
||||
|
||||
namespace opt {
|
||||
|
||||
expr_ref_vector preprocess::propagate(expr* f, lbool& is_sat) {
|
||||
expr_ref_vector asms(m);
|
||||
asms.push_back(f);
|
||||
is_sat = s.check_sat(asms);
|
||||
return s.get_trail(1);
|
||||
}
|
||||
|
||||
bool preprocess::prop_mutexes(vector<soft>& softs, rational& lower) {
|
||||
expr_ref_vector fmls(m);
|
||||
obj_map<expr, rational> new_soft = soft2map(softs, fmls);
|
||||
|
||||
params_ref p;
|
||||
p.set_uint("max_conflicts", 1);
|
||||
s.updt_params(p);
|
||||
|
||||
obj_hashtable<expr> pfmls, nfmls;
|
||||
for (expr* f : fmls)
|
||||
if (m.is_not(f, f))
|
||||
nfmls.insert(f);
|
||||
else
|
||||
pfmls.insert(f);
|
||||
|
||||
u_map<expr*> ids;
|
||||
unsigned_vector ps;
|
||||
for (expr* f : fmls) {
|
||||
ids.insert(f->get_id(), f);
|
||||
ps.push_back(f->get_id());
|
||||
}
|
||||
|
||||
u_map<uint_set> conns;
|
||||
|
||||
for (expr* f : fmls) {
|
||||
lbool is_sat;
|
||||
expr_ref_vector trail = propagate(f, is_sat);
|
||||
if (is_sat == l_false) {
|
||||
rational w = new_soft[f];
|
||||
lower += w;
|
||||
s.assert_expr(m.mk_not(f));
|
||||
new_soft.remove(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
expr_ref_vector mux(m);
|
||||
for (expr* g : trail) {
|
||||
if (m.is_not(g, g)) {
|
||||
if (pfmls.contains(g))
|
||||
mux.push_back(g);
|
||||
}
|
||||
else if (nfmls.contains(g))
|
||||
mux.push_back(m.mk_not(g));
|
||||
}
|
||||
uint_set reach;
|
||||
for (expr* g : mux)
|
||||
reach.insert(g->get_id());
|
||||
conns.insert(f->get_id(), reach);
|
||||
}
|
||||
|
||||
p.set_uint("max_conflicts", UINT_MAX);
|
||||
s.updt_params(p);
|
||||
|
||||
struct neg_literal {
|
||||
unsigned negate(unsigned id) {
|
||||
throw default_exception("unexpected call");
|
||||
}
|
||||
};
|
||||
max_cliques<neg_literal> mc;
|
||||
vector<unsigned_vector> mutexes;
|
||||
mc.cliques(ps, conns, mutexes);
|
||||
|
||||
for (auto& mux : mutexes) {
|
||||
expr_ref_vector _mux(m);
|
||||
for (auto p : mux)
|
||||
_mux.push_back(ids[p]);
|
||||
process_mutex(_mux, new_soft, lower);
|
||||
}
|
||||
|
||||
softs.reset();
|
||||
for (auto const& [k, v] : new_soft)
|
||||
softs.push_back(soft(expr_ref(k, m), v, false));
|
||||
m_trail.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
obj_map<expr, rational> preprocess::soft2map(vector<soft> const& softs, expr_ref_vector& fmls) {
|
||||
obj_map<expr, rational> new_soft;
|
||||
for (soft const& sf : softs) {
|
||||
m_trail.push_back(sf.s);
|
||||
if (new_soft.contains(sf.s))
|
||||
new_soft[sf.s] += sf.weight;
|
||||
else
|
||||
new_soft.insert(sf.s, sf.weight);
|
||||
fmls.push_back(sf.s);
|
||||
}
|
||||
return new_soft;
|
||||
}
|
||||
|
||||
bool preprocess::find_mutexes(vector<soft>& softs, rational& lower) {
|
||||
expr_ref_vector fmls(m);
|
||||
obj_map<expr, rational> new_soft = soft2map(softs, fmls);
|
||||
vector<expr_ref_vector> mutexes;
|
||||
lbool is_sat = s.find_mutexes(fmls, mutexes);
|
||||
if (is_sat == l_false)
|
||||
return true;
|
||||
if (is_sat == l_undef)
|
||||
return false;
|
||||
for (auto& mux : mutexes)
|
||||
process_mutex(mux, new_soft, lower);
|
||||
softs.reset();
|
||||
for (auto const& [k, v] : new_soft)
|
||||
softs.push_back(soft(expr_ref(k, m), v, false));
|
||||
m_trail.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
struct maxsmt_compare_soft {
|
||||
obj_map<expr, rational> const& m_soft;
|
||||
maxsmt_compare_soft(obj_map<expr, rational> const& soft): m_soft(soft) {}
|
||||
bool operator()(expr* a, expr* b) const {
|
||||
return m_soft.find(a) > m_soft.find(b);
|
||||
}
|
||||
};
|
||||
|
||||
void preprocess::process_mutex(expr_ref_vector& mutex, obj_map<expr, rational>& new_soft, rational& lower) {
|
||||
TRACE("opt",
|
||||
for (expr* e : mutex) {
|
||||
tout << mk_pp(e, m) << " |-> " << new_soft.find(e) << "\n";
|
||||
});
|
||||
if (mutex.size() <= 1)
|
||||
return;
|
||||
|
||||
maxsmt_compare_soft cmp(new_soft);
|
||||
ptr_vector<expr> _mutex(mutex.size(), mutex.data());
|
||||
std::sort(_mutex.begin(), _mutex.end(), cmp);
|
||||
mutex.reset();
|
||||
mutex.append(_mutex.size(), _mutex.data());
|
||||
|
||||
rational weight(0), sum1(0), sum2(0);
|
||||
vector<rational> weights;
|
||||
for (expr* e : mutex) {
|
||||
rational w = new_soft.find(e);
|
||||
weights.push_back(w);
|
||||
sum1 += w;
|
||||
new_soft.remove(e);
|
||||
}
|
||||
for (unsigned i = mutex.size(); i-- > 0; ) {
|
||||
expr_ref soft(m.mk_or(i+1, mutex.data()), m);
|
||||
m_trail.push_back(soft);
|
||||
rational w = weights[i];
|
||||
weight = w - weight;
|
||||
lower += weight*rational(i);
|
||||
IF_VERBOSE(1, verbose_stream() << "(opt.maxsat mutex size: " << i + 1 << " weight: " << weight << ")\n";);
|
||||
sum2 += weight*rational(i+1);
|
||||
new_soft.insert(soft, weight);
|
||||
for (; i > 0 && weights[i-1] == w; --i) {}
|
||||
weight = w;
|
||||
}
|
||||
SASSERT(sum1 == sum2);
|
||||
}
|
||||
|
||||
preprocess::preprocess(solver& s): m(s.get_manager()), s(s), m_trail(m) {}
|
||||
|
||||
bool preprocess::operator()(vector<soft>& soft, rational& lower) {
|
||||
if (!find_mutexes(soft, lower))
|
||||
return false;
|
||||
if (false && !prop_mutexes(soft, lower))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
41
src/opt/opt_preprocess.h
Normal file
41
src/opt/opt_preprocess.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*++
|
||||
Copyright (c) 2021 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
opt_preprocess.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Pre-processing for MaxSMT
|
||||
|
||||
Find mutexes - at most 1 constraints and modify soft constraints and bounds.
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2022-04-11
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opt/maxsmt.h"
|
||||
|
||||
namespace opt {
|
||||
|
||||
class preprocess {
|
||||
ast_manager& m;
|
||||
solver& s;
|
||||
expr_ref_vector m_trail;
|
||||
|
||||
expr_ref_vector propagate(expr* f, lbool& is_sat);
|
||||
obj_map<expr, rational> soft2map(vector<soft> const& softs, expr_ref_vector& fmls);
|
||||
bool find_mutexes(vector<soft>& softs, rational& lower);
|
||||
bool prop_mutexes(vector<soft>& softs, rational& lower);
|
||||
void process_mutex(expr_ref_vector& mutex, obj_map<expr, rational>& new_soft, rational& lower);
|
||||
|
||||
public:
|
||||
preprocess(solver& s);
|
||||
bool operator()(vector<soft>& soft, rational& lower);
|
||||
};
|
||||
};
|
|
@ -48,6 +48,7 @@ namespace opt {
|
|||
void set_offset(rational const& o) { m_offset = o; }
|
||||
void set_negate(bool neg) { m_negate = neg; }
|
||||
rational const& get_offset() const { return m_offset; }
|
||||
void add_offset(rational const& o) { if (m_negate) m_offset -= o; else m_offset += o; }
|
||||
bool get_negate() { return m_negate; }
|
||||
inf_eps operator()(inf_eps const& r) const {
|
||||
inf_eps result = r;
|
||||
|
@ -107,7 +108,7 @@ namespace opt {
|
|||
lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) override;
|
||||
lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) override;
|
||||
void get_levels(ptr_vector<expr> const& vars, unsigned_vector& depth) override;
|
||||
expr_ref_vector get_trail() override { return m_context.get_trail(); }
|
||||
expr_ref_vector get_trail(unsigned max_level) override { return m_context.get_trail(max_level); }
|
||||
expr_ref_vector cube(expr_ref_vector&, unsigned) override { return expr_ref_vector(m); }
|
||||
void set_phase(expr* e) override { m_context.set_phase(e); }
|
||||
phase* get_phase() override { return m_context.get_phase(); }
|
||||
|
|
|
@ -36,34 +36,27 @@ namespace opt {
|
|||
expr_ref_vector m_trail;
|
||||
func_decl_ref_vector m_fresh;
|
||||
ref<generic_model_converter> m_filter;
|
||||
sortmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft):
|
||||
maxsmt_solver_base(c, ws, soft), m_sort(*this), m_trail(m), m_fresh(m) {}
|
||||
sortmax(maxsat_context& c, vector<soft>& s, unsigned index):
|
||||
maxsmt_solver_base(c, s, index), m_sort(*this), m_trail(m), m_fresh(m) {}
|
||||
|
||||
~sortmax() override {}
|
||||
|
||||
lbool operator()() override {
|
||||
obj_map<expr, rational> soft;
|
||||
if (!init()) {
|
||||
return l_false;
|
||||
}
|
||||
lbool is_sat = find_mutexes(soft);
|
||||
if (is_sat != l_true) {
|
||||
return is_sat;
|
||||
}
|
||||
if (!init())
|
||||
return l_undef;
|
||||
|
||||
lbool is_sat = l_true;
|
||||
m_filter = alloc(generic_model_converter, m, "sortmax");
|
||||
rational offset = m_lower;
|
||||
m_upper = offset;
|
||||
expr_ref_vector in(m);
|
||||
expr_ref tmp(m);
|
||||
ptr_vector<expr> out;
|
||||
obj_map<expr, rational>::iterator it = soft.begin(), end = soft.end();
|
||||
for (; it != end; ++it) {
|
||||
if (!it->m_value.is_unsigned()) {
|
||||
for (auto const & [e, w, t] : m_soft) {
|
||||
if (!w.is_unsigned()) {
|
||||
throw default_exception("sortmax can only handle unsigned weights. Use a different heuristic.");
|
||||
}
|
||||
unsigned n = it->m_value.get_unsigned();
|
||||
unsigned n = w.get_unsigned();
|
||||
while (n > 0) {
|
||||
in.push_back(it->m_key);
|
||||
in.push_back(e);
|
||||
--n;
|
||||
}
|
||||
}
|
||||
|
@ -71,19 +64,15 @@ namespace opt {
|
|||
|
||||
// initialize sorting network outputs using the initial assignment.
|
||||
unsigned first = 0;
|
||||
it = soft.begin();
|
||||
for (; it != end; ++it) {
|
||||
if (m_model->is_true(it->m_key)) {
|
||||
unsigned n = it->m_value.get_unsigned();
|
||||
for (auto const & [e, w, t] : m_soft) {
|
||||
if (t == l_true) {
|
||||
unsigned n = w.get_unsigned();
|
||||
while (n > 0) {
|
||||
s().assert_expr(out[first]);
|
||||
++first;
|
||||
--n;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_upper += it->m_value;
|
||||
}
|
||||
}
|
||||
while (l_true == is_sat && first < out.size() && m_lower < m_upper) {
|
||||
trace_bounds("sortmax");
|
||||
|
@ -149,8 +138,8 @@ namespace opt {
|
|||
};
|
||||
|
||||
|
||||
maxsmt_solver_base* mk_sortmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft) {
|
||||
return alloc(sortmax, c, ws, soft);
|
||||
maxsmt_solver_base* mk_sortmax(maxsat_context& c, vector<soft>& s, unsigned index) {
|
||||
return alloc(sortmax, c, s, index);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ namespace opt {
|
|||
}
|
||||
|
||||
public:
|
||||
wmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft):
|
||||
maxsmt_solver_base(c, ws, soft),
|
||||
wmax(maxsat_context& c, vector<soft>& s, unsigned index):
|
||||
maxsmt_solver_base(c, s, index),
|
||||
m_trail(m),
|
||||
m_defs(m) {}
|
||||
|
||||
|
@ -54,22 +54,18 @@ namespace opt {
|
|||
lbool operator()() override {
|
||||
TRACE("opt", tout << "weighted maxsat\n";);
|
||||
scoped_ensure_theory wth(*this);
|
||||
obj_map<expr, rational> soft;
|
||||
reset();
|
||||
lbool is_sat = find_mutexes(soft);
|
||||
if (is_sat != l_true) {
|
||||
return is_sat;
|
||||
}
|
||||
m_upper = m_lower;
|
||||
if (init())
|
||||
return l_undef;
|
||||
|
||||
lbool is_sat = l_true;
|
||||
|
||||
expr_ref_vector asms(m);
|
||||
vector<expr_ref_vector> cores;
|
||||
|
||||
for (auto const& kv : soft) {
|
||||
assert_weighted(wth(), kv.m_key, kv.m_value);
|
||||
if (!is_true(kv.m_key)) {
|
||||
m_upper += kv.m_value;
|
||||
}
|
||||
}
|
||||
for (auto const& [k, w, t] : m_soft)
|
||||
assert_weighted(wth(), k, w);
|
||||
|
||||
wth().init_min_cost(m_upper - m_lower);
|
||||
trace_bounds("wmax");
|
||||
|
||||
|
@ -308,8 +304,8 @@ namespace opt {
|
|||
|
||||
};
|
||||
|
||||
maxsmt_solver_base* mk_wmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft) {
|
||||
return alloc(wmax, c, ws, soft);
|
||||
maxsmt_solver_base* mk_wmax(maxsat_context& c, vector<soft> & s, unsigned index) {
|
||||
return alloc(wmax, c, s, index);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue