mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 03:32:28 +00:00 
			
		
		
		
	use fixed vars to explain tightening
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
		
							parent
							
								
									24aeaed50a
								
							
						
					
					
						commit
						472306c0b2
					
				
					 3 changed files with 56 additions and 42 deletions
				
			
		|  | @ -372,6 +372,7 @@ namespace lp { | ||||||
| 
 | 
 | ||||||
|         void subs_front_in_indexed_vector(std::queue<unsigned> & q) { |         void subs_front_in_indexed_vector(std::queue<unsigned> & q) { | ||||||
|             unsigned k = pop_front(q); |             unsigned k = pop_front(q); | ||||||
|  |             if (m_indexed_work_vector[k].is_zero()) return; | ||||||
|             const eprime_entry& e = entry_for_subs(k); |             const eprime_entry& e = entry_for_subs(k); | ||||||
|             TRACE("dioph_eq", tout << "k:" << k << ", in ";  print_term_o(create_term_from_ind_c(), tout) << std::endl; |             TRACE("dioph_eq", tout << "k:" << k << ", in ";  print_term_o(create_term_from_ind_c(), tout) << std::endl; | ||||||
|             tout << "subs with e:"; print_eprime_entry(e, tout) << std::endl;); |             tout << "subs with e:"; print_eprime_entry(e, tout) << std::endl;); | ||||||
|  | @ -557,7 +558,15 @@ namespace lp { | ||||||
|                 return false; |                 return false; | ||||||
|             }  |             }  | ||||||
|             // g is not trivial, trying to tighten the bounds
 |             // g is not trivial, trying to tighten the bounds
 | ||||||
|             return tighten_bounds_for_term(g, j);             |             // by using bitwise to explore both bounds
 | ||||||
|  |             return tighten_bounds_for_term(g, j, true) | tighten_bounds_for_term(g, j, false); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         void get_expl_from_meta_term(const lar_term& t, explanation& ex) { | ||||||
|  |             for (const auto& p: t) { | ||||||
|  |                 const auto& l = lra.get_term(p.j()); | ||||||
|  |                 get_expl_from_lar_term(l, ex);                 | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         void get_expl_from_lar_term(const lar_term & l, explanation& ex) { |         void get_expl_from_lar_term(const lar_term & l, explanation& ex) { | ||||||
|  | @ -580,13 +589,13 @@ namespace lp { | ||||||
|             u_dependency *b_dep = nullptr; |             u_dependency *b_dep = nullptr; | ||||||
|             if (lra.has_upper_bound(j, b_dep, rs, is_strict)) { |             if (lra.has_upper_bound(j, b_dep, rs, is_strict)) { | ||||||
|                 if (m_c > rs || (is_strict && m_c == rs)) { |                 if (m_c > rs || (is_strict && m_c == rs)) { | ||||||
|                     get_expl_from_lar_term(m_tmp_l, m_infeas_explanation); |                     get_expl_from_meta_term(m_tmp_l, m_infeas_explanation); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (lra.has_lower_bound(j, b_dep, rs, is_strict)) { |             if (lra.has_lower_bound(j, b_dep, rs, is_strict)) { | ||||||
|                 if (m_c < rs || (is_strict && m_c == rs)) { |                 if (m_c < rs || (is_strict && m_c == rs)) { | ||||||
|                     get_expl_from_lar_term(m_tmp_l, m_infeas_explanation); |                     get_expl_from_meta_term(m_tmp_l, m_infeas_explanation); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -595,36 +604,25 @@ namespace lp { | ||||||
|         // m_indexed_work_vector contains the coefficients of the term
 |         // m_indexed_work_vector contains the coefficients of the term
 | ||||||
|         // m_c contains the constant term
 |         // m_c contains the constant term
 | ||||||
|         // m_tmp_l is the linear combination of the equations that removs the substituted variablse
 |         // m_tmp_l is the linear combination of the equations that removs the substituted variablse
 | ||||||
|         bool tighten_bounds_for_term(const mpq& g, unsigned j) { |         bool tighten_bounds_for_term(const mpq& g, unsigned j, bool is_upper) { | ||||||
|             mpq rs; |             mpq rs; | ||||||
|             bool is_strict; |             bool is_strict; | ||||||
|             bool change = false; |  | ||||||
|             u_dependency *b_dep = nullptr; |             u_dependency *b_dep = nullptr; | ||||||
|             SASSERT(!g.is_zero()); |             SASSERT(!g.is_zero()); | ||||||
| 
 | 
 | ||||||
|             if (lra.has_upper_bound(j, b_dep, rs, is_strict)) { |             if (lra.has_bound_of_type(j, b_dep, rs, is_strict, is_upper)) { | ||||||
|                 TRACE("dioph_eq", tout << "current upper bound for x:" << j << ":" << rs << std::endl;); |                 TRACE("dioph_eq", tout << "current upper bound for x:" << j << ":" << rs << std::endl;); | ||||||
|                 rs = (rs - m_c) / g; |                 rs = (rs - m_c) / g; | ||||||
|                 TRACE("dioph_eq", tout << "(rs - m_c) / g:" << rs << std::endl;); |                 TRACE("dioph_eq", tout << "(rs - m_c) / g:" << rs << std::endl;); | ||||||
|                 if (!rs.is_int()) { |                 if (!rs.is_int()) { | ||||||
|                     tighten_bound_for_term_for_bound_kind(g, j, rs, true); |                     tighten_bound_for_term_for_bound_kind(g, j, rs, is_upper, b_dep); | ||||||
|                     change = true; |                     return true; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             if (lra.has_lower_bound(j, b_dep, rs, is_strict)) { |             return false; | ||||||
|                 TRACE("dioph_eq", tout << "current lower bound for x" << j << ":" << rs << std::endl;); |  | ||||||
|                 rs = (rs - m_c) / g; |  | ||||||
|                 TRACE("dioph_eq", tout << "(rs - m_c) / g:" << rs << std::endl;); |  | ||||||
|                 if (!rs.is_int()) { |  | ||||||
|                     tighten_bound_for_term_for_bound_kind(g, j, rs, false); |  | ||||||
|                     change = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return change; |  | ||||||
|              |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         void tighten_bound_for_term_for_bound_kind( const mpq& g, unsigned j, const mpq & ub, bool upper) { |         void tighten_bound_for_term_for_bound_kind( const mpq& g, unsigned j, const mpq & ub, bool upper, u_dependency* prev_dep) { | ||||||
|             // ub = (upper_bound(j) - m_c)/g.
 |             // ub = (upper_bound(j) - m_c)/g.
 | ||||||
|             // we have x[j] = t = g*t_+ m_c <= upper_bound(j), then
 |             // we have x[j] = t = g*t_+ m_c <= upper_bound(j), then
 | ||||||
|             // t_ <= floor((upper_bound(j) - m_c)/g) = floor(ub)
 |             // t_ <= floor((upper_bound(j) - m_c)/g) = floor(ub)
 | ||||||
|  | @ -638,14 +636,29 @@ namespace lp { | ||||||
|              |              | ||||||
|             SASSERT(upper && bound < lra.get_upper_bound(j).x || !upper && bound > lra.get_lower_bound(j).x); |             SASSERT(upper && bound < lra.get_upper_bound(j).x || !upper && bound > lra.get_lower_bound(j).x); | ||||||
|             lconstraint_kind kind = upper? lconstraint_kind::LE: lconstraint_kind::GE; |             lconstraint_kind kind = upper? lconstraint_kind::LE: lconstraint_kind::GE; | ||||||
|             u_dependency* dep = collect_explanation_from_indexed_vector(upper); |             u_dependency* dep = prev_dep; | ||||||
|             dep = lra.mk_join(dep, explain_fixed(m_tmp_l)); |             dep = lra.mk_join(dep, explain_fixed_in_meta_term(m_tmp_l)); | ||||||
|             u_dependency* j_bound_dep = upper? lra.get_column_upper_bound_witness(j): lra.get_column_lower_bound_witness(j); |             u_dependency* j_bound_dep = upper? lra.get_column_upper_bound_witness(j): lra.get_column_lower_bound_witness(j); | ||||||
|             dep = lra.mk_join(dep, j_bound_dep); |             dep = lra.mk_join(dep, j_bound_dep); | ||||||
|             TRACE("dioph_eq", tout << "jterm:"; print_lar_term_L(lra.get_term(j), tout) << "\ndep:"; print_dep(tout, dep) << std::endl;);             |             TRACE("dioph_eq", tout << "jterm:"; print_lar_term_L(lra.get_term(j), tout) << "\ndep:"; print_dep(tout, dep) << std::endl;);             | ||||||
|             lra.update_column_type_and_bound(j, kind, bound, dep);             |             lra.update_column_type_and_bound(j, kind, bound, dep);             | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         u_dependency* explain_fixed_in_meta_term(const lar_term& t) { | ||||||
|  |             u_dependency* dep = nullptr; | ||||||
|  | 
 | ||||||
|  |             for (const auto& p: t) { | ||||||
|  |                 lar_term const& term = lra.get_term(p.j()); | ||||||
|  |                 for (const auto& q: term) { | ||||||
|  |                     if (is_fixed(q.j())) { | ||||||
|  |                         u_dependency* bound_dep = lra.get_bound_constraint_witnesses_for_column(q.j()); | ||||||
|  |                         dep = lra.mk_join(dep, bound_dep); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return dep; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         u_dependency* explain_fixed(const lar_term& t) { |         u_dependency* explain_fixed(const lar_term& t) { | ||||||
|             u_dependency* dep = nullptr; |             u_dependency* dep = nullptr; | ||||||
|             for (const auto& p: t) { |             for (const auto& p: t) { | ||||||
|  | @ -657,23 +670,6 @@ namespace lp { | ||||||
|             return dep; |             return dep; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         u_dependency* collect_explanation_from_indexed_vector(bool upper) { |  | ||||||
|             TRACE("dioph_eq", |  | ||||||
|                 tout << (upper?"upper":"lower")  << std::endl; |  | ||||||
|                 tout << "indexed_vec:"; print_term_o(create_term_from_ind_c(), tout); |  | ||||||
|             ); |  | ||||||
| 
 |  | ||||||
|             term_o t = remove_fresh_vars(create_term_from_ind_c());     |  | ||||||
| 
 |  | ||||||
|             u_dependency* dep = nullptr; |  | ||||||
|             int bound_sign = upper? 1: -1; |  | ||||||
|             for (const auto& p: t) { |  | ||||||
|                 int var_bound_sign = p.coeff().is_pos()? bound_sign: -bound_sign; |  | ||||||
|                 u_dependency* bound_dep = (var_bound_sign == 1? lra.get_column_upper_bound_witness(p.var()): lra.get_column_lower_bound_witness(p.var())); |  | ||||||
|                 dep = lra.mk_join(dep, bound_dep); |  | ||||||
|             } |  | ||||||
|             return dep; |  | ||||||
|         } |  | ||||||
| public: | public: | ||||||
|         lia_move check() { |         lia_move check() { | ||||||
|             init(); |             init(); | ||||||
|  | @ -916,7 +912,17 @@ public: | ||||||
|                 out << "\tm_l:{"; print_lar_term_L(e.m_l, out) << "}, "; |                 out << "\tm_l:{"; print_lar_term_L(e.m_l, out) << "}, "; | ||||||
|                 print_ml(e.m_l, out<< " \topened m_l:") << "\n";    |                 print_ml(e.m_l, out<< " \topened m_l:") << "\n";    | ||||||
|             } |             } | ||||||
|             out << "}\n"; |             switch (e.m_entry_status) | ||||||
|  |             { | ||||||
|  |             case entry_status::F: | ||||||
|  |                 out << "\tF\n"; | ||||||
|  |                 break; | ||||||
|  |             case entry_status::S: | ||||||
|  |                 out << "\tS\n"; | ||||||
|  |                 break; | ||||||
|  |                 default: | ||||||
|  |                 out << "\tNOSF\n"; | ||||||
|  |             }  | ||||||
|             return out; |             return out; | ||||||
|         }       |         }       | ||||||
|          |          | ||||||
|  |  | ||||||
|  | @ -1060,7 +1060,13 @@ namespace lp { | ||||||
|         } |         } | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
| 
 |     bool lar_solver::has_bound_of_type(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict, bool is_upper) const { | ||||||
|  |         if (is_upper) { | ||||||
|  |             return has_upper_bound(var, ci, value, is_strict); | ||||||
|  |         } else { | ||||||
|  |             return has_lower_bound(var, ci, value, is_strict); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     bool lar_solver::has_lower_bound(lpvar var, u_dependency*& dep, mpq& value, bool& is_strict) const { |     bool lar_solver::has_lower_bound(lpvar var, u_dependency*& dep, mpq& value, bool& is_strict) const { | ||||||
| 
 | 
 | ||||||
|         if (var >= m_columns.size()) { |         if (var >= m_columns.size()) { | ||||||
|  |  | ||||||
|  | @ -527,6 +527,8 @@ public: | ||||||
|      |      | ||||||
|     bool has_lower_bound(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict) const; |     bool has_lower_bound(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict) const; | ||||||
|     bool has_upper_bound(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict) const; |     bool has_upper_bound(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict) const; | ||||||
|  |     bool has_bound_of_type(lpvar var, u_dependency*& ci, mpq& value, bool& is_strict, bool is_upper) const; | ||||||
|  |    | ||||||
|     bool has_value(lpvar var, mpq& value) const; |     bool has_value(lpvar var, mpq& value) const; | ||||||
|     bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>&) const; |     bool fetch_normalized_term_column(const lar_term& t, std::pair<mpq, lpvar>&) const; | ||||||
|     bool column_is_fixed(unsigned j) const; |     bool column_is_fixed(unsigned j) const; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue