mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 13:28:47 +00:00
add rewrite for hoisting multipliers over modular inverses
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
c727e2d048
commit
98c7069f75
|
@ -700,9 +700,32 @@ br_status arith_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result
|
||||||
else if (m_arith_lhs || is_arith_term(arg1) || is_arith_term(arg2)) {
|
else if (m_arith_lhs || is_arith_term(arg1) || is_arith_term(arg2)) {
|
||||||
st = mk_le_ge_eq_core(arg1, arg2, EQ, result);
|
st = mk_le_ge_eq_core(arg1, arg2, EQ, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (st == BR_FAILED && mk_eq_mod(arg1, arg2, result))
|
||||||
|
st = BR_REWRITE2;
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool arith_rewriter::mk_eq_mod(expr* arg1, expr* arg2, expr_ref& result) {
|
||||||
|
expr* x = nullptr, *y = nullptr, *z = nullptr, *u = nullptr;
|
||||||
|
rational p, k, l;
|
||||||
|
// match k*u mod p = l, where k, p, l are integers
|
||||||
|
if (m_util.is_mod(arg1, x, y) && m_util.is_numeral(y, p) &&
|
||||||
|
m_util.is_mul(x, z, u) && m_util.is_numeral(z, k) &&
|
||||||
|
m_util.is_numeral(arg2, l) && 0 <= l && l < p) {
|
||||||
|
// a*p + k*b = g
|
||||||
|
rational a, b;
|
||||||
|
rational g = gcd(p, k, a, b);
|
||||||
|
if (g == 1) {
|
||||||
|
expr_ref nb(m_util.mk_numeral(b, true), m());
|
||||||
|
result = m().mk_eq(m_util.mk_mod(u, y),
|
||||||
|
m_util.mk_mod(m_util.mk_mul(nb, arg2), y));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
expr_ref arith_rewriter::neg_monomial(expr* e) const {
|
expr_ref arith_rewriter::neg_monomial(expr* e) const {
|
||||||
expr_ref_vector args(m());
|
expr_ref_vector args(m());
|
||||||
rational a1;
|
rational a1;
|
||||||
|
|
|
@ -104,7 +104,9 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> {
|
||||||
bool divides(expr* d, expr* n, expr_ref& result);
|
bool divides(expr* d, expr* n, expr_ref& result);
|
||||||
expr_ref remove_divisor(expr* arg, expr* num, expr* den);
|
expr_ref remove_divisor(expr* arg, expr* num, expr* den);
|
||||||
void flat_mul(expr* e, ptr_buffer<expr>& args);
|
void flat_mul(expr* e, ptr_buffer<expr>& args);
|
||||||
void remove_divisor(expr* d, ptr_buffer<expr>& args);
|
void remove_divisor(expr* d, ptr_buffer<expr>& args);
|
||||||
|
|
||||||
|
bool mk_eq_mod(expr* arg1, expr* arg2, expr_ref& result);
|
||||||
public:
|
public:
|
||||||
arith_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
arith_rewriter(ast_manager & m, params_ref const & p = params_ref()):
|
||||||
poly_rewriter<arith_rewriter_core>(m, p) {
|
poly_rewriter<arith_rewriter_core>(m, p) {
|
||||||
|
|
Loading…
Reference in a new issue