mirror of
https://github.com/Z3Prover/z3
synced 2025-06-20 21:03:39 +00:00
support checking pseudo-inverses
This commit is contained in:
parent
07d1f86575
commit
233baf170c
2 changed files with 70 additions and 2 deletions
|
@ -44,7 +44,7 @@ namespace polysat {
|
||||||
|
|
||||||
ast* store(ast* a) { storage.push_back(ast_ref{a, m}); return a; }
|
ast* store(ast* a) { storage.push_back(ast_ref{a, m}); return a; }
|
||||||
expr* store(expr* e) { storage.push_back(ast_ref{e, m}); return e; }
|
expr* store(expr* e) { storage.push_back(ast_ref{e, m}); return e; }
|
||||||
|
app* store(app* a) { storage.push_back(ast_ref{a, m}); return a; }
|
||||||
};
|
};
|
||||||
|
|
||||||
polysat_ast::polysat_ast(solver& s)
|
polysat_ast::polysat_ast(solver& s)
|
||||||
|
@ -57,6 +57,12 @@ namespace polysat {
|
||||||
ast_manager& polysat_ast::m() const { return d->m; }
|
ast_manager& polysat_ast::m() const { return d->m; }
|
||||||
bv_util& polysat_ast::bv() const { return *d->bv; }
|
bv_util& polysat_ast::bv() const { return *d->bv; }
|
||||||
|
|
||||||
|
expr* polysat_ast::mk_fresh_bool_const(char const* prefix) {
|
||||||
|
app* b = d->store(m().mk_fresh_const(prefix, m().mk_bool_sort()));
|
||||||
|
d->decls.push_back(b->get_decl());
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
expr* polysat_ast::mk_val(rational const& val, unsigned bit_width) {
|
expr* polysat_ast::mk_val(rational const& val, unsigned bit_width) {
|
||||||
return d->store(bv().mk_numeral(val, bit_width));
|
return d->store(bv().mk_numeral(val, bit_width));
|
||||||
}
|
}
|
||||||
|
@ -67,7 +73,7 @@ namespace polysat {
|
||||||
unsigned bit_width = s.size(x);
|
unsigned bit_width = s.size(x);
|
||||||
std::string name = "v";
|
std::string name = "v";
|
||||||
name += std::to_string(x);
|
name += std::to_string(x);
|
||||||
auto decl = m().mk_const_decl(name, bv().mk_sort(bit_width));
|
func_decl* decl = m().mk_const_decl(name, bv().mk_sort(bit_width));
|
||||||
d->decls.push_back(decl);
|
d->decls.push_back(decl);
|
||||||
node = d->store(m().mk_const(decl));
|
node = d->store(m().mk_const(decl));
|
||||||
d->var_expr.insert(x, node);
|
d->var_expr.insert(x, node);
|
||||||
|
@ -108,6 +114,51 @@ namespace polysat {
|
||||||
return d->store(bv().mk_bv_add(args));
|
return d->store(bv().mk_bv_add(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr* polysat_ast::mk_parity(pdd const& p) {
|
||||||
|
unsigned const N = p.power_of_2();
|
||||||
|
if (p.is_val())
|
||||||
|
return mk_val(rational(p.val().parity(N)), N);
|
||||||
|
app* parity = d->store(m().mk_fresh_const("parity", bv().mk_sort(N)));
|
||||||
|
d->decls.push_back(parity->get_decl());
|
||||||
|
expr* parity_1 = d->store(bv().mk_bv_add(parity, mk_val(rational(1), N)));
|
||||||
|
expr* v = mk_poly(p);
|
||||||
|
// if v = 0
|
||||||
|
// then parity = N
|
||||||
|
// else v = (v >> parity) << parity
|
||||||
|
// && v != (v >> parity+1) << parity+1
|
||||||
|
// TODO: what about: v[k:] = 0 && v[k+1:] != 0 ==> parity = k for each k?
|
||||||
|
// TODO: add helper axiom like parity <= N ?
|
||||||
|
expr* definition =
|
||||||
|
m().mk_ite(
|
||||||
|
m().mk_eq(v, mk_val(rational(0), N)),
|
||||||
|
m().mk_eq(parity, mk_val(rational(N), N)),
|
||||||
|
m().mk_and(
|
||||||
|
m().mk_eq(v, bv().mk_bv_shl(bv().mk_bv_lshr(v, parity), parity)),
|
||||||
|
m().mk_not(m().mk_eq(v, bv().mk_bv_shl(bv().mk_bv_lshr(v, parity_1), parity_1)))
|
||||||
|
));
|
||||||
|
add(definition);
|
||||||
|
return parity;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr* polysat_ast::mk_inv(pdd const& p, pdd const& p_inv) {
|
||||||
|
unsigned const N = p.power_of_2();
|
||||||
|
// p_inv == smallest_pseudo_inverse(p)
|
||||||
|
expr* v = mk_poly(p);
|
||||||
|
expr* v_inv = mk_poly(p_inv);
|
||||||
|
expr* parity = mk_parity(p);
|
||||||
|
expr* one = mk_val(rational(1), N);
|
||||||
|
// 2^parity = v * v_inv
|
||||||
|
expr* definition1 = m().mk_eq(bv().mk_bv_shl(one, parity), bv().mk_bv_mul(v, v_inv));
|
||||||
|
// v_inv <= 2^(N - parity) - 1
|
||||||
|
expr* v_inv_max = bv().mk_bv_sub(bv().mk_bv_shl(one, bv().mk_bv_sub(mk_val(rational(N), N), parity)), one);
|
||||||
|
expr* definition2 = bv().mk_ule(v_inv, v_inv_max);
|
||||||
|
// conditional on b
|
||||||
|
expr* b = mk_fresh_bool_const("parity_enable");
|
||||||
|
add(m().mk_iff(b, definition1));
|
||||||
|
add(m().mk_iff(b, definition2));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
expr* polysat_ast::mk_not(expr* e) {
|
expr* polysat_ast::mk_not(expr* e) {
|
||||||
return d->store(m().mk_not(e));
|
return d->store(m().mk_not(e));
|
||||||
}
|
}
|
||||||
|
@ -142,6 +193,15 @@ namespace polysat {
|
||||||
return mk_ule(c->to_ule().lhs(), c->to_ule().rhs(), c.sign());
|
return mk_ule(c->to_ule().lhs(), c->to_ule().rhs(), c.sign());
|
||||||
if (c->is_umul_ovfl())
|
if (c->is_umul_ovfl())
|
||||||
return mk_umul_ovfl(c->to_umul_ovfl().p(), c->to_umul_ovfl().q(), c.sign());
|
return mk_umul_ovfl(c->to_umul_ovfl().p(), c->to_umul_ovfl().q(), c.sign());
|
||||||
|
if (c->is_op()) {
|
||||||
|
op_constraint& op = c->to_op();
|
||||||
|
switch (op.get_op()) {
|
||||||
|
case op_constraint::code::inv_op:
|
||||||
|
return mk_inv(op.p(), op.r());
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
verbose_stream() << "polysat_ast not yet supported: " << c << "\n";
|
verbose_stream() << "polysat_ast not yet supported: " << c << "\n";
|
||||||
m_ok = false;
|
m_ok = false;
|
||||||
// NOT_IMPLEMENTED_YET();
|
// NOT_IMPLEMENTED_YET();
|
||||||
|
|
|
@ -33,6 +33,11 @@ namespace polysat {
|
||||||
ast_manager& m() const;
|
ast_manager& m() const;
|
||||||
bv_util& bv() const;
|
bv_util& bv() const;
|
||||||
|
|
||||||
|
expr* mk_fresh_bool_const(char const* prefix);
|
||||||
|
|
||||||
|
// expression for "parity of p"
|
||||||
|
expr* mk_parity(pdd const& p);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
polysat_ast(solver&);
|
polysat_ast(solver&);
|
||||||
~polysat_ast();
|
~polysat_ast();
|
||||||
|
@ -59,6 +64,9 @@ namespace polysat {
|
||||||
// ovfl*(p, q)
|
// ovfl*(p, q)
|
||||||
expr* mk_umul_ovfl(pdd const& p, pdd const& q, bool sign);
|
expr* mk_umul_ovfl(pdd const& p, pdd const& q, bool sign);
|
||||||
|
|
||||||
|
// p_inv = pseudo-inverse(p)
|
||||||
|
expr* mk_inv(pdd const& p, pdd const& p_inv);
|
||||||
|
|
||||||
expr* mk_not(expr* e);
|
expr* mk_not(expr* e);
|
||||||
|
|
||||||
expr* mk_lit(sat::literal lit);
|
expr* mk_lit(sat::literal lit);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue