mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	na
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									179c9c2da2
								
							
						
					
					
						commit
						99043399ce
					
				
					 3 changed files with 69 additions and 80 deletions
				
			
		|  | @ -207,11 +207,11 @@ void basics::negate_strict_sign(new_lemma& lemma, lpvar j) { | |||
|     }  | ||||
|     else {  // val(j).is_zero()
 | ||||
|         if (c().has_lower_bound(j) && c().get_lower_bound(j) >= rational(0)) { | ||||
|             c().explain_existing_lower_bound(lemma, j); | ||||
|             lemma.explain_existing_lower_bound(j); | ||||
|             lemma |= ineq(j, llc::GT, 0); | ||||
|         } else { | ||||
|             SASSERT(c().has_upper_bound(j) && c().get_upper_bound(j) <= rational(0)); | ||||
|             c().explain_existing_upper_bound(lemma, j); | ||||
|             lemma.explain_existing_upper_bound(j); | ||||
|             lemma |= ineq(j, llc::LT, 0); | ||||
|         } | ||||
|     } | ||||
|  | @ -302,7 +302,7 @@ bool basics::basic_lemma_for_mon_non_zero_derived(const monic& rm, const factori | |||
|             continue; | ||||
|         new_lemma lemma(c(), "x = 0 or y = 0 -> xy = 0"); | ||||
|         lemma.explain_fixed(var(fc)); | ||||
|         c().explain_var_separated_from_zero(lemma, var(rm)); | ||||
|         lemma.explain_var_separated_from_zero(var(rm)); | ||||
|         lemma &= rm; | ||||
|         lemma &= f; | ||||
|         return true; | ||||
|  | @ -328,7 +328,7 @@ bool basics::basic_lemma_for_mon_neutral_derived(const monic& rm, const factoriz | |||
|         return false; | ||||
|     } | ||||
|     bool mon_var_is_sep_from_zero =  c().var_is_separated_from_zero(mon_var); | ||||
|     lpvar jl = null_lpvar, not_one_j = null_lpvar; | ||||
|     lpvar u = null_lpvar, v = null_lpvar; | ||||
|     bool all_int = true; | ||||
|     for (auto fc : f) { | ||||
|         lpvar j = var(fc); | ||||
|  | @ -336,31 +336,22 @@ bool basics::basic_lemma_for_mon_neutral_derived(const monic& rm, const factoriz | |||
|         if (j == null_lpvar && abs(val(j)) == abs_mv &&  | ||||
|             c().vars_are_equiv(j, mon_var) && | ||||
|             (mon_var_is_sep_from_zero ||  c().var_is_separated_from_zero(j)))  | ||||
|             jl = j; | ||||
|         else if (j == jl) | ||||
|             return false; | ||||
|             u = j; | ||||
|         else if (abs(val(j)) != rational(1))  | ||||
|             not_one_j = j; | ||||
|             v = j; | ||||
|     } | ||||
|     if (jl == null_lpvar || not_one_j == null_lpvar) | ||||
|     if (u == null_lpvar || v == null_lpvar) | ||||
|         return false;     | ||||
|     if (!all_int && f.size() > 2) | ||||
|         return false; | ||||
| 
 | ||||
|     //    (mon_var != 0 || u != 0) & mon_var = +/- u =>
 | ||||
|     //    v = 1 or v = -1
 | ||||
|     new_lemma lemma(c(), "|xa| = |x| & x != 0 -> |a| = 1"); | ||||
|     // mon_var = 0
 | ||||
|     if (mon_var_is_sep_from_zero) | ||||
|         c().explain_var_separated_from_zero(lemma, mon_var); | ||||
|     else | ||||
|         c().explain_var_separated_from_zero(lemma, jl); | ||||
|      | ||||
|     lemma.explain_equiv(mon_var, jl); | ||||
|          | ||||
|     // not_one_j = 1
 | ||||
|     lemma |= ineq(not_one_j, llc::EQ, 1); | ||||
|          | ||||
|     // not_one_j = -1
 | ||||
|     lemma |= ineq(not_one_j, llc::EQ, -1); | ||||
|     lemma.explain_var_separated_from_zero(mon_var_is_sep_from_zero ? mon_var : u);     | ||||
|     lemma.explain_equiv(mon_var, u);         | ||||
|     lemma |= ineq(v, llc::EQ, 1);         | ||||
|     lemma |= ineq(v, llc::EQ, -1); | ||||
|     lemma &= rm; | ||||
|     lemma &= f; | ||||
|     return true; | ||||
|  | @ -422,9 +413,6 @@ NSB review: | |||
| 
 | ||||
|    sign_m*m < 0 or f_j = 0 or \/_{i != j} sign_m*m >= sign_i*f_i | ||||
| 
 | ||||
| - or even, without reference to factor index: | ||||
|    sign_m*m < 0 or \/_i sign_m*m >= sign_i*f_i | ||||
| 
 | ||||
| */ | ||||
| void basics::generate_pl_on_mon(const monic& m, unsigned factor_index) { | ||||
|     SASSERT(!mon_has_real(m)); | ||||
|  | @ -529,7 +517,7 @@ void basics::basic_lemma_for_mon_zero_model_based(const monic& rm, const factori | |||
|     } else { | ||||
|         lemma |= ineq(var(rm), llc::NE, 0); | ||||
|         for (auto j : f) { | ||||
|             c().explain_separation_from_zero(lemma, var(j)); | ||||
|             lemma.explain_separation_from_zero(var(j)); | ||||
|         }             | ||||
|     } | ||||
|     lemma &= f; | ||||
|  | @ -601,8 +589,8 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based_fm(co | |||
|         | ||||
|     new_lemma lemma(c(), __FUNCTION__); | ||||
|     for (auto j : m.vars()) { | ||||
|         if (not_one == j) continue; | ||||
|         lemma |= ineq(j, llc::NE, val(j)); | ||||
|         if (not_one != j)  | ||||
|             lemma |= ineq(j, llc::NE, val(j)); | ||||
|     } | ||||
| 
 | ||||
|     if (not_one == null_lpvar)  | ||||
|  | @ -613,7 +601,7 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based_fm(co | |||
| } | ||||
| 
 | ||||
| // use the fact that
 | ||||
| // |xabc| = |x| and x != 0 -> |a| = |b| = |c| = 1 
 | ||||
| // |uvw| = |u| and uvw != 0 -> |v| = 1 
 | ||||
| bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based(const monic& rm, const factorization& f) { | ||||
|     lpvar mon_var = c().emons()[rm.var()].var(); | ||||
|     TRACE("nla_solver_bl", c().trace_print_monic_and_factorization(rm, f, tout); tout << "\nmon_var = " << mon_var << "\n";); | ||||
|  | @ -624,36 +612,32 @@ bool basics::basic_lemma_for_mon_neutral_monic_to_factor_model_based(const monic | |||
|     if (abs_mv == rational::zero()) { | ||||
|         return false; | ||||
|     } | ||||
|     lpvar jl = null_lpvar, not_one_j = null_lpvar; | ||||
|     lpvar u = null_lpvar, v = null_lpvar; | ||||
|     bool all_int = true; | ||||
|     for (auto fc : f) { | ||||
|         lpvar j = var(fc); | ||||
|         all_int &= c().var_is_int(j);         | ||||
|         if (j == null_lpvar && abs(val(fc)) == abs_mv)  | ||||
|             jl = j; | ||||
|         else if (j == jl) | ||||
|             return false; | ||||
|             u = j; | ||||
|         else if (abs(val(fc)) != rational(1))  | ||||
|             not_one_j = j; | ||||
|             v = j; | ||||
|     } | ||||
|     if (jl == null_lpvar || not_one_j == null_lpvar) | ||||
|     if (u == null_lpvar || v == null_lpvar) | ||||
|         return false;     | ||||
|     if (!all_int && f.size() > 2) | ||||
|         return false; | ||||
| 
 | ||||
|     new_lemma lemma(c(), __FUNCTION__); | ||||
|     // mon_var = 0
 | ||||
|     lemma |= ineq(mon_var, llc::EQ, 0); | ||||
|          | ||||
|     // negate abs(jl) == abs()    
 | ||||
|     lemma |= ineq(term(jl, rational(val(jl) == -val(mon_var) ? 1 : -1), mon_var), llc::NE, 0); | ||||
|     // abs(u) != abs(mon_var)    
 | ||||
|     // v = 1
 | ||||
|     // v = -1
 | ||||
| 
 | ||||
|     // not_one_j = 1
 | ||||
|     lemma |= ineq(not_one_j, llc::EQ, 1); | ||||
|          | ||||
|     // not_one_j = -1
 | ||||
|     lemma |= ineq(not_one_j, llc::EQ, -1); | ||||
|     lemma &= rm; | ||||
|     new_lemma lemma(c(), __FUNCTION__); | ||||
|     lemma |= ineq(mon_var, llc::EQ, 0);         | ||||
|     lemma |= ineq(term(u, rational(val(u) == -val(mon_var) ? 1 : -1), mon_var), llc::NE, 0); | ||||
|     lemma |= ineq(v, llc::EQ, 1);         | ||||
|     lemma |= ineq(v, llc::EQ, -1); | ||||
|     lemma &= rm; // NSB review: is this dependency required?
 | ||||
|     lemma &= f; | ||||
| 
 | ||||
|     return true; | ||||
|  | @ -695,7 +679,7 @@ bool basics::basic_lemma_for_mon_neutral_from_factors_to_monic_model_based(const | |||
|         } | ||||
|              | ||||
|         if (v == -rational(1)) {  | ||||
|             sign = - sign; | ||||
|             sign = -sign; | ||||
|             continue; | ||||
|         }  | ||||
|              | ||||
|  |  | |||
|  | @ -625,24 +625,6 @@ bool core::is_canonical_monic(lpvar j) const { | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| void core::explain_existing_lower_bound(new_lemma& lemma, lpvar j) { | ||||
|     SASSERT(has_lower_bound(j)); | ||||
|     lemma &= m_lar_solver.get_column_lower_bound_witness(j); | ||||
| } | ||||
| 
 | ||||
| void core::explain_existing_upper_bound(new_lemma& lemma, lpvar j) { | ||||
|     SASSERT(has_upper_bound(j)); | ||||
|     lemma &= m_lar_solver.get_column_upper_bound_witness(j); | ||||
| } | ||||
|      | ||||
| void core::explain_separation_from_zero(new_lemma& lemma, lpvar j) { | ||||
|     SASSERT(!val(j).is_zero()); | ||||
|     if (val(j).is_pos()) | ||||
|         explain_existing_lower_bound(lemma, j); | ||||
|     else | ||||
|         explain_existing_upper_bound(lemma, j); | ||||
| } | ||||
| 
 | ||||
| void core::trace_print_monic_and_factorization(const monic& rm, const factorization& f, std::ostream& out) const { | ||||
|     out << "rooted vars: "; | ||||
|     print_product(rm.rvars(), out) << "\n"; | ||||
|  | @ -651,14 +633,6 @@ void core::trace_print_monic_and_factorization(const monic& rm, const factorizat | |||
|     print_factorization(f, out << "fact: ") << "\n"; | ||||
| } | ||||
| 
 | ||||
| void core::explain_var_separated_from_zero(new_lemma& lemma, lpvar j) { | ||||
|     SASSERT(var_is_separated_from_zero(j)); | ||||
|     if (m_lar_solver.column_has_upper_bound(j) && (m_lar_solver.get_upper_bound(j)< lp::zero_of_type<lp::impq>()))  | ||||
|         lemma &= m_lar_solver.get_column_upper_bound_witness(j); | ||||
|     else  | ||||
|         lemma &= m_lar_solver.get_column_lower_bound_witness(j); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| bool core::var_has_positive_lower_bound(lpvar j) const { | ||||
|     return m_lar_solver.column_has_lower_bound(j) && m_lar_solver.get_lower_bound(j) > lp::zero_of_type<lp::impq>(); | ||||
|  | @ -1187,6 +1161,38 @@ new_lemma& new_lemma::explain_equiv(lpvar a, lpvar b) { | |||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| new_lemma& new_lemma::explain_var_separated_from_zero(lpvar j) { | ||||
|     SASSERT(c.var_is_separated_from_zero(j)); | ||||
|     if (c.m_lar_solver.column_has_upper_bound(j) &&  | ||||
|         (c.m_lar_solver.get_upper_bound(j)< lp::zero_of_type<lp::impq>()))  | ||||
|         *this &= c.m_lar_solver.get_column_upper_bound_witness(j); | ||||
|     else  | ||||
|         *this &= c.m_lar_solver.get_column_lower_bound_witness(j); | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| new_lemma& new_lemma::explain_existing_lower_bound(lpvar j) { | ||||
|     SASSERT(c.has_lower_bound(j)); | ||||
|     *this &= c.m_lar_solver.get_column_lower_bound_witness(j); | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| new_lemma& new_lemma::explain_existing_upper_bound(lpvar j) { | ||||
|     SASSERT(c.has_upper_bound(j)); | ||||
|     *this &= c.m_lar_solver.get_column_upper_bound_witness(j); | ||||
|     return *this; | ||||
| } | ||||
|      | ||||
| new_lemma& new_lemma::explain_separation_from_zero(lpvar j) { | ||||
|     SASSERT(!c.val(j).is_zero()); | ||||
|     if (c.val(j).is_pos()) | ||||
|         explain_existing_lower_bound(j); | ||||
|     else | ||||
|         explain_existing_upper_bound(j); | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& new_lemma::display(std::ostream & out) const { | ||||
|     auto const& lemma = current(); | ||||
|  |  | |||
|  | @ -105,6 +105,11 @@ public: | |||
|     new_lemma& operator|=(ineq const& i); | ||||
|     new_lemma& explain_fixed(lpvar j); | ||||
|     new_lemma& explain_equiv(lpvar u, lpvar v); | ||||
|     new_lemma& explain_var_separated_from_zero(lpvar j); | ||||
|     new_lemma& explain_existing_lower_bound(lpvar j); | ||||
|     new_lemma& explain_existing_upper_bound(lpvar j);     | ||||
|     new_lemma& explain_separation_from_zero(lpvar j); | ||||
| 
 | ||||
|     unsigned num_ineqs() const { return current().ineqs().size(); } | ||||
| }; | ||||
| 
 | ||||
|  | @ -245,13 +250,7 @@ public: | |||
|      | ||||
|     // return true iff the monic value is equal to the product of the values of the factors
 | ||||
|     bool check_monic(const monic& m) const; | ||||
|      | ||||
|     // NSB review: these should really be methods on new_lemma
 | ||||
|     void explain_existing_lower_bound(new_lemma& lemma, lpvar j); | ||||
|     void explain_existing_upper_bound(new_lemma& lemma, lpvar j);     | ||||
|     void explain_separation_from_zero(new_lemma& lemma, lpvar j); | ||||
|     void explain_var_separated_from_zero(new_lemma& lemma, lpvar j); | ||||
| 
 | ||||
|     | ||||
| 
 | ||||
|     std::ostream & print_ineq(const ineq & in, std::ostream & out) const; | ||||
|     std::ostream & print_var(lpvar j, std::ostream & out) const; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue