3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-28 08:58:44 +00:00

generalize factoring

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2024-08-23 16:23:37 -07:00
parent 69dd247cfc
commit 0b8177c7d6
3 changed files with 68 additions and 46 deletions

View file

@ -515,28 +515,38 @@ br_status arith_rewriter::reduce_power(expr * arg1, expr * arg2, op_kind kind, e
} }
} }
bool arith_rewriter::is_factor(expr* s, expr* t) { bool arith_rewriter::is_mul_factor(expr* s, expr* t) {
if (m_util.is_mul(t)) if (m_util.is_mul(t))
return any_of(*to_app(t), [&](expr* m) { return m == s; }); return any_of(*to_app(t), [&](expr* m) { return is_mul_factor(s, m); });
if (m_util.is_add(t))
return all_of(*to_app(t), [&](expr* f) { return is_factor(s, f); });
return s == t; return s == t;
} }
bool arith_rewriter::is_add_factor(expr* s, expr* t) {
if (m_util.is_add(t))
return all_of(*to_app(t), [&](expr* f) { return is_add_factor(s, f); });
return is_mul_factor(s, t);
}
expr_ref arith_rewriter::remove_factor(expr* s, expr* t) { expr_ref arith_rewriter::remove_factor(expr* s, expr* t) {
if (m_util.is_mul(t)) { if (m_util.is_mul(t)) {
ptr_buffer<expr> r; ptr_buffer<expr> r;
r.append(to_app(t)->get_num_args(), to_app(t)->get_args()); r.push_back(t);
for (unsigned i = 0; i < r.size(); ++i) { for (unsigned i = 0; i < r.size(); ++i) {
expr* arg = r[i]; expr* arg = r[i];
if (m_util.is_mul(arg)) {
r.append(to_app(arg)->get_num_args(), to_app(arg)->get_args());
r[i] = r.back();
r.pop_back();
--i;
continue;
}
if (s == arg) { if (s == arg) {
r[i] = r.back(); r[i] = r.back();
r.pop_back(); r.pop_back();
break; break;
} }
} }
SASSERT(to_app(t)->get_num_args() == r.size() + 1);
switch (r.size()) { switch (r.size()) {
case 0: case 0:
return expr_ref(m_util.mk_numeral(rational(1), m_util.is_int(t)), m); return expr_ref(m_util.mk_numeral(rational(1), m_util.is_int(t)), m);
@ -546,49 +556,60 @@ expr_ref arith_rewriter::remove_factor(expr* s, expr* t) {
return expr_ref(m_util.mk_mul(r.size(), r.data()), m); return expr_ref(m_util.mk_mul(r.size(), r.data()), m);
} }
} }
if (m_util.is_add(t)) { expr_ref_vector sum(m);
expr_ref_vector sum(m); sum.push_back(t);
for (expr* arg : *to_app(t)) for (unsigned i = 0; i < sum.size(); ++i) {
sum.push_back(remove_factor(s, arg)); expr* arg = sum.get(i);
return expr_ref(m_util.mk_add(sum.size(), sum.data()), m); if (m_util.is_add(arg)) {
sum.append(to_app(arg)->get_num_args(), to_app(arg)->get_args());
sum[i] = sum.back();
sum.pop_back();
--i;
continue;
}
sum[i] = remove_factor(s, arg);
} }
SASSERT(s == t); if (sum.size() == 1)
return expr_ref(m_util.mk_numeral(rational(1), m_util.is_int(t)), m); return expr_ref(sum.get(0), m);
else
return expr_ref(m_util.mk_add(sum.size(), sum.data()), m);
} }
br_status arith_rewriter::factor_le_ge_eq(expr * arg1, expr * arg2, op_kind kind, expr_ref & result) { void arith_rewriter::get_nl_muls(expr* t, ptr_buffer<expr>& muls) {
auto is_nl_mul = [&](expr* t) { if (m_util.is_mul(t)) {
if (!m_util.is_mul(t))
return false;
if (to_app(t)->get_num_args() <= 1)
return false;
unsigned num_vars = 0;
for (expr* arg : *to_app(t)) for (expr* arg : *to_app(t))
if (!m_util.is_numeral(arg)) get_nl_muls(arg, muls);
++num_vars; }
return num_vars > 1; else if (!m_util.is_numeral(t))
}; muls.push_back(t);
auto find_nl_factor = [&](expr* s) -> expr* { }
if (is_nl_mul(s)) {
for (expr* arg : *to_app(s)) expr* arith_rewriter::find_nl_factor(expr* t) {
if (!m_util.is_numeral(arg) && is_factor(arg, s)) ptr_buffer<expr> sum, muls;
return arg; sum.push_back(t);
for (unsigned i = 0; i < sum.size(); ++i) {
expr* arg = sum[i];
if (m_util.is_add(arg))
sum.append(to_app(arg)->get_num_args(), to_app(arg)->get_args());
else if (m_util.is_mul(arg)) {
muls.reset();
get_nl_muls(arg, muls);
if (muls.size() <= 1)
continue;
for (auto m : muls) {
if (is_add_factor(m, t))
return m;
}
return nullptr; return nullptr;
} }
if (m_util.is_add(s)) { }
for (expr* arg : *to_app(s)) { return nullptr;
if (is_nl_mul(arg)) { }
for (expr* arg1 : *to_app(arg))
if (!m_util.is_numeral(arg1) && is_factor(arg1, s))
return arg1;
return nullptr;
}
}
}
return nullptr;
};
br_status arith_rewriter::factor_le_ge_eq(expr * arg1, expr * arg2, op_kind kind, expr_ref & result) {
if (is_zero(arg2)) { if (is_zero(arg2)) {
expr* f = find_nl_factor(arg1); expr* f = find_nl_factor(arg1);
if (!f) if (!f)
@ -604,8 +625,7 @@ br_status arith_rewriter::factor_le_ge_eq(expr * arg1, expr * arg2, op_kind kind
break; break;
case LE: case LE:
result = m.mk_or(m.mk_not(m.mk_iff(m_util.mk_ge(f, z), m_util.mk_ge(f2, z))), result); result = m.mk_or(m.mk_not(m.mk_iff(m_util.mk_ge(f, z), m_util.mk_ge(f2, z))), result);
break; break;
} }
return BR_REWRITE3; return BR_REWRITE3;
} }

View file

@ -73,7 +73,10 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> {
br_status is_separated(expr * arg1, expr * arg2, op_kind kind, expr_ref & result); br_status is_separated(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
bool is_non_negative(expr* e); bool is_non_negative(expr* e);
br_status mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kind, expr_ref & result); br_status mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);
bool is_factor(expr* s, expr* t); bool is_add_factor(expr* s, expr* t);
bool is_mul_factor(expr* s, expr* t);
expr* find_nl_factor(expr* t);
void get_nl_muls(expr* t, ptr_buffer<expr>& muls);
expr_ref remove_factor(expr* s, expr* t); expr_ref remove_factor(expr* s, expr* t);
br_status factor_le_ge_eq(expr * arg1, expr * arg2, op_kind kind, expr_ref & result); br_status factor_le_ge_eq(expr * arg1, expr * arg2, op_kind kind, expr_ref & result);

View file

@ -558,7 +558,6 @@ namespace sls {
ctx.force_restart(); ctx.force_restart();
num_fail = 0; num_fail = 0;
} }
// m_stats.m_num_steps++;
return false; return false;
} }
@ -1673,7 +1672,7 @@ namespace sls {
result += 1; result += 1;
if (dtt_new != 0 && dtt_old == 0) { if (dtt_new != 0 && dtt_old == 0) {
if (/*m_use_tabu && */ctx.is_unit(lit)) if (m_use_tabu && ctx.is_unit(lit))
return 0; return 0;
result -= 1; result -= 1;
} }