3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 12:08:18 +00:00

fix a bug in unit nl prop

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2023-10-10 07:32:07 -07:00
parent adbee0cd3f
commit 180ab727e7
2 changed files with 41 additions and 23 deletions

View file

@ -305,8 +305,8 @@ namespace nla {
void monomial_bounds::unit_propagate(monic & m) { void monomial_bounds::unit_propagate(monic & m) {
if (m.is_propagated()) if (m.is_propagated())
return; return;
lpvar w, fixed_to_zero;
if (!is_linear(m)) { if (!is_linear(m, w, fixed_to_zero)) {
#if UNIT_PROPAGATE_BOUNDS #if UNIT_PROPAGATE_BOUNDS
propagate(m); propagate(m);
#endif #endif
@ -315,12 +315,16 @@ namespace nla {
c().emons().set_propagated(m); c().emons().set_propagated(m);
rational k = fixed_var_product(m); if (fixed_to_zero != null_lpvar) {
lpvar w = non_fixed_var(m); propagate_fixed_to_zero(m, fixed_to_zero);
if (w == null_lpvar || k == 0) }
propagate_fixed(m, k); else {
else rational k = fixed_var_product(m, w);
propagate_nonfixed(m, k, w); if (w == null_lpvar)
propagate_fixed(m, k);
else
propagate_nonfixed(m, k, w);
}
++c().lra.settings().stats().m_nla_propagate_eq; ++c().lra.settings().stats().m_nla_propagate_eq;
} }
@ -332,13 +336,19 @@ namespace nla {
exp.add_pair(d, mpq(1)); exp.add_pair(d, mpq(1));
return exp; return exp;
} }
void monomial_bounds::propagate_fixed_to_zero(monic const& m, lpvar fixed_to_zero) {
auto* dep = c().lra.get_bound_constraint_witnesses_for_column(fixed_to_zero);
TRACE("nla_solver", tout << "propagate fixed " << m << " = 0, fixed_to_zero = " << fixed_to_zero << "\n";);
c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, rational(0), dep);
// propagate fixed equality
auto exp = get_explanation(dep);
c().add_fixed_equality(c().lra.column_to_reported_index(m.var()), rational(0), exp);
}
void monomial_bounds::propagate_fixed(monic const& m, rational const& k) { void monomial_bounds::propagate_fixed(monic const& m, rational const& k) {
auto* dep = explain_fixed(m, k); auto* dep = explain_fixed(m, k);
if (!c().lra.is_base(m.var())) {
lp::impq val(k);
c().lra.set_value_for_nbasic_column(m.var(), val);
}
TRACE("nla_solver", tout << "propagate fixed " << m << " = " << k << "\n";); TRACE("nla_solver", tout << "propagate fixed " << m << " = " << k << "\n";);
c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, k, dep); c().lra.update_column_type_and_bound(m.var(), lp::lconstraint_kind::EQ, k, dep);
@ -385,24 +395,31 @@ namespace nla {
} }
bool monomial_bounds::is_linear(monic const& m) { bool monomial_bounds::is_linear(monic const& m, lpvar& w, lpvar & fixed_to_zero) {
unsigned non_fixed = 0; w = fixed_to_zero = null_lpvar;
for (lpvar v : m) { for (lpvar v : m) {
if (!c().var_is_fixed(v)) if (!c().var_is_fixed(v)) {
++non_fixed; if (w != null_lpvar)
else if (c().val(v).is_zero()) return false;
w = v;
}
else if (c().get_lower_bound(v).is_zero()) {
fixed_to_zero = v;
return true; return true;
}
} }
return non_fixed <= 1; return true;
} }
rational monomial_bounds::fixed_var_product(monic const& m) { rational monomial_bounds::fixed_var_product(monic const& m, lpvar w) {
rational r(1); rational r(1);
for (lpvar v : m) { for (lpvar v : m) {
// we have to use the column bounds here, because the column value may be outside the bounds // we have to use the column bounds here, because the column value may be outside the bounds
if (c().var_is_fixed(v)) if (v != w ){
r *= c().lra.get_lower_bound(v).x; SASSERT(c().var_is_fixed(v));
r *= c().lra.get_lower_bound(v).x;
}
} }
return r; return r;
} }

View file

@ -24,6 +24,7 @@ namespace nla {
bool propagate_value(dep_interval& range, lpvar v, unsigned power); bool propagate_value(dep_interval& range, lpvar v, unsigned power);
void compute_product(unsigned start, monic const& m, scoped_dep_interval& i); void compute_product(unsigned start, monic const& m, scoped_dep_interval& i);
bool propagate(monic const& m); bool propagate(monic const& m);
void propagate_fixed_to_zero(monic const& m, lpvar fixed_to_zero);
void propagate_fixed(monic const& m, rational const& k); void propagate_fixed(monic const& m, rational const& k);
void propagate_nonfixed(monic const& m, rational const& k, lpvar w); void propagate_nonfixed(monic const& m, rational const& k, lpvar w);
u_dependency* explain_fixed(monic const& m, rational const& k); u_dependency* explain_fixed(monic const& m, rational const& k);
@ -35,8 +36,8 @@ namespace nla {
// monomial propagation // monomial propagation
void unit_propagate(monic & m); void unit_propagate(monic & m);
bool is_linear(monic const& m); bool is_linear(monic const& m, lpvar& w, lpvar & fixed_to_zero);
rational fixed_var_product(monic const& m); rational fixed_var_product(monic const& m, lpvar w);
lpvar non_fixed_var(monic const& m); lpvar non_fixed_var(monic const& m);
public: public:
monomial_bounds(core* core); monomial_bounds(core* core);