@@ -1666,10 +1666,11 @@ namespace lp {
16661666 TRACE (" dio" ,
16671667 tout << " current " << (is_upper? " upper" :" lower" ) << " bound for x" << j << " :"
16681668 << rs << std::endl;);
1669- rs = (rs - m_c) / g;
1670- TRACE (" dio" , tout << " ((rs - m_c) / g):" << rs << std::endl;);
1671- if (!rs.is_int ()) {
1672- if (tighten_bound_kind (g, j, rs, is_upper))
1669+ mpq rs_mod_g = (rs - m_c) % g;
1670+ SASSERT (!rs_mod_g.is_neg () && rs_mod_g.is_int ());
1671+ TRACE (" dio" , tout << " (rs - m_c) % g:" << rs_mod_g << std::endl;);
1672+ if (!rs_mod_g.is_zero ()) {
1673+ if (tighten_bound_kind (g, j, rs, rs_mod_g, is_upper))
16731674 return lia_move::conflict;
16741675 } else {
16751676 TRACE (" dio" , tout << " no improvement in the bound\n " ;);
@@ -1678,16 +1679,22 @@ namespace lp {
16781679 return lia_move::undef;
16791680 }
16801681
1681- // returns true only on a conflict
1682- bool tighten_bound_kind (const mpq& g, unsigned j, const mpq& ub, bool upper) {
1683- // ub = (upper_bound(j) - m_c)/g.
1684- // we have xj = t = g*t_+ m_c <= upper_bound(j), then
1685- // t_ <= floor((upper_bound(j) - m_c)/g) = floor(ub)
1686- //
1687- // so xj = g*t_+m_c <= g*floor(ub) + m_c is new upper bound
1688- // <= can be replaced with >= for lower bounds, with ceil instead of
1689- // floor
1690- mpq bound = g * (upper ? floor (ub) : ceil (ub)) + m_c;
1682+ // returns true only on a conflict
1683+ bool tighten_bound_kind (const mpq& g, unsigned j, const mpq& rs, const mpq& rs_mod_g, bool upper) {
1684+ // In case of an upper bound we have
1685+ // xj = t = g*t_+ m_c <= rs, also, by definition fo rs_mod_g, for some integer k holds rs - m_c = k*g + rs_mod_g.
1686+ // Then g*t_ <= rs - mc = k*g + rs_mod_g => g*t_ <= k*g = rs - m_c - rs_mod_g.
1687+ // Adding m_c to both parts gets us
1688+ // xj = g*t_ + m_c <= rs - rs_mod_g
1689+
1690+ // In case of a lower bound we have
1691+ // xj = t = g*t_+ m_c >= rs, also, by definition fo rs_mod_g, for some integer k holds rs - m_c = k*g + rs_mod_g.
1692+ // Then g*t_ >= rs - mc = k*g + rs_mod_g => g*t_ >= k*g = rs - m_c + g - rs_mod_g.
1693+ // Adding m_c to both parts gets us
1694+ // xj = g*t_ + m_c >= rs + g - rs_mod_g
1695+
1696+
1697+ mpq bound = upper ? rs - rs_mod_g : rs + g - rs_mod_g;
16911698 TRACE (" dio" , tout << " is upper:" << upper << std::endl;
16921699 tout << " new " << (upper ? " upper" : " lower" )
16931700 << " bound:" << bound << std::endl;);
@@ -1696,15 +1703,20 @@ namespace lp {
16961703 (!upper && bound > lra.get_lower_bound (j).x ));
16971704 lconstraint_kind kind = upper ? lconstraint_kind::LE : lconstraint_kind::GE;
16981705 u_dependency* dep = upper ? lra.get_column_upper_bound_witness (j) : lra.get_column_lower_bound_witness (j);
1699- auto rs = open_fixed_from_ml (m_lspace);
1706+ auto fixed_part_of_the_term = open_fixed_from_ml (m_lspace);
17001707 // the right side is off by 1*j from m_espace
17011708 if (is_fixed (j))
1702- rs.add (mpq (1 ), j);
1703- for (const auto & p: rs) {
1704- SASSERT (is_fixed (p.var ()));
1705- if ((p.coeff () / g).is_int ())
1706- continue ; // explain todo!!!
1707-
1709+ fixed_part_of_the_term.add (mpq (1 ), j);
1710+ for (const auto & p: fixed_part_of_the_term) {
1711+ SASSERT (is_fixed (p.var ()));
1712+ if ((p.coeff () % g).is_zero ()) {
1713+ // we can skip thise dependency,
1714+ // because the monomial p.coeff()*p.var() is null by modulo g, and it does not matter that p.var() is fixed.
1715+ // We could have added p.coeff()*p.var() to t_, substructed the value of p.coeff()*p.var() from m_c and
1716+ // still get the same result.
1717+ TRACE (" dio" , tout << " skipped dep:\n " ; print_deps (tout, lra.get_bound_constraint_witnesses_for_column (p.var ())););
1718+ continue ;
1719+ }
17081720 dep = lra.join_deps (dep, lra.get_bound_constraint_witnesses_for_column (p.var ()));
17091721 }
17101722 TRACE (" dio" , tout << " jterm:" ;
0 commit comments