mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	t
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
		
							parent
							
								
									a4f9eee822
								
							
						
					
					
						commit
						d8ce5c6795
					
				
					 1 changed files with 115 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -557,6 +557,7 @@ namespace nlsat {
 | 
			
		|||
        void add_ord_inv_discriminant_for(const property& p) {
 | 
			
		||||
            polynomial_ref disc(m_pm);
 | 
			
		||||
            disc = discriminant(p.poly, p.level);
 | 
			
		||||
            TRACE(levelwise, ::nlsat::display(tout << "discriminant: ", m_solver, disc) << "\n";);
 | 
			
		||||
            if (!is_const(disc)) {
 | 
			
		||||
                if (coeffs_are_zeroes_on_sample(disc, m_pm, sample(), m_am)) {
 | 
			
		||||
                    m_fail = true; // ambiguous multiplicity -- not handled yet
 | 
			
		||||
| 
						 | 
				
			
			@ -650,19 +651,131 @@ namespace nlsat {
 | 
			
		|||
            add_to_Q_if_new(property(prop_enum::connected, empty, /*level*/ p.level - 1));
 | 
			
		||||
            add_to_Q_if_new(property(prop_enum::repr,      empty, /*level*/ p.level - 1));
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            NOT_IMPLEMENTED_YET();
 | 
			
		||||
            // todo!!!! add missing preconditions
 | 
			
		||||
            // connected property has been processed
 | 
			
		||||
            erase_from_Q(p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void apply_pre_non_null(const property& p) {
 | 
			
		||||
            TRACE(levelwise, tout << "apply_pre_non_null:";
 | 
			
		||||
                  if (p.level != static_cast<unsigned>(-1)) tout << " level=" << p.level;
 | 
			
		||||
                  tout << std::endl;);
 | 
			
		||||
            // First try subrule 1 of Rule 4.2. If it succeeds we do not apply the fallback (subrule 2).
 | 
			
		||||
            if (try_non_null_via_coeffs(p, nullptr))
 | 
			
		||||
                return;
 | 
			
		||||
            // fallback: apply the first subrule
 | 
			
		||||
            apply_pre_non_null_fallback(p);
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
        bool have_non_zero_const(const polynomial_ref& p, unsigned level) {
 | 
			
		||||
            unsigned deg = m_pm.degree(p, level); 
 | 
			
		||||
            for (unsigned j = deg; --j > 0; )
 | 
			
		||||
                if (m_pm.nonzero_const_coeff(p.get(), level, j))  
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
            return false;         
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Helper for Rule 4.2, subrule 2:
 | 
			
		||||
        // If some coefficient c_j of p is constant non-zero at the sample, or
 | 
			
		||||
        // if c_j evaluates non-zero at the sample and we already have sgn_inv(c_j) in m_Q,
 | 
			
		||||
        // then non_null(p) holds on the region represented by 'rs' (if provided).
 | 
			
		||||
        // Returns true if non_null was established and the property p was removed.
 | 
			
		||||
        bool try_non_null_via_coeffs(const property& p, result_struct* rs) {
 | 
			
		||||
            if (have_non_zero_const(p.poly, p.level)) {
 | 
			
		||||
                TRACE(levelwise, tout << "have a non-zero const coefficient\n";);
 | 
			
		||||
                erase_from_Q(p);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (have_sgn_inv_property(p, p.level)) {
 | 
			
		||||
                erase_from_Q(p);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
                
 | 
			
		||||
            poly* pp = p.poly.get();
 | 
			
		||||
            unsigned deg = m_pm.degree(pp, p.level);
 | 
			
		||||
            for (unsigned j = 0; j <= deg; ++j) {
 | 
			
		||||
                polynomial_ref coeff(m_pm);
 | 
			
		||||
                coeff = m_pm.coeff(pp, p.level, j);
 | 
			
		||||
                // If coefficient is constant and non-zero at sample -> non_null holds
 | 
			
		||||
                if (is_const(coeff)) {
 | 
			
		||||
                    SASSERT(m_pm.nonzero_const_coeff(pp, p.level, j));
 | 
			
		||||
                    continue; 
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                if (sign(coeff, sample(), m_am) == 0)
 | 
			
		||||
                    continue;
 | 
			
		||||
 | 
			
		||||
                auto it = std::find_if(m_Q.begin(), m_Q.end(), [&](const property & q) {
 | 
			
		||||
                    return (q.prop_tag == prop_enum::sgn_inv_irreducible || q.prop_tag == prop_enum::sgn_inv_reducible)
 | 
			
		||||
                        && q.poly == p.poly;
 | 
			
		||||
                });
 | 
			
		||||
                if (it != m_Q.end()) {
 | 
			
		||||
                    erase_from_Q(p);
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                add_to_Q_if_new(property(prop_enum::sgn_inv_reducible, coeff, 0u, max_var(coeff)));
 | 
			
		||||
                erase_from_Q(p);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Helper for Rule 4.2, subrule 1: fallback when subrule 2 does not apply.
 | 
			
		||||
        // sample(s)(R), degx_{i+1} (p) > 1, disc(x_{i+1} (p)(s)) ̸= 0, sgn_inv(disc(x_{i+1} (p))(R) 
 | 
			
		||||
        void apply_pre_non_null_fallback(const property& p) {
 | 
			
		||||
            // basic sanity checks
 | 
			
		||||
            if (!p.poly) {
 | 
			
		||||
                TRACE(levelwise, tout << "apply_pre_non_null_fallback: null poly -> fail" << std::endl;);
 | 
			
		||||
                m_fail = true;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (p.level == static_cast<unsigned>(-1)) {
 | 
			
		||||
                TRACE(levelwise, tout << "apply_pre_non_null_fallback: unspecified level -> skip" << std::endl;);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            poly * pp = p.poly.get();
 | 
			
		||||
            unsigned deg = m_pm.degree(pp, p.level);
 | 
			
		||||
            // fallback applies only for degree > 1
 | 
			
		||||
            if (deg <= 1) return;
 | 
			
		||||
 | 
			
		||||
            // compute discriminant w.r.t. the variable at p.level
 | 
			
		||||
            polynomial_ref disc(m_pm);
 | 
			
		||||
            disc = discriminant(p.poly, p.level);
 | 
			
		||||
            TRACE(levelwise, ::nlsat::display(tout << "discriminant: ", m_solver, disc) << "\n";);
 | 
			
		||||
 | 
			
		||||
            // If discriminant evaluates to zero at the sample, we cannot proceed
 | 
			
		||||
            // (ambiguous multiplicity) -> fail per instruction
 | 
			
		||||
            if (sign(disc, sample(), m_am) == 0) {
 | 
			
		||||
                TRACE(levelwise, tout << "apply_pre_non_null_fallback: discriminant vanishes at sample -> failing" << std::endl;);
 | 
			
		||||
                m_fail = true;
 | 
			
		||||
                NOT_IMPLEMENTED_YET();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // If discriminant is non-constant, add sign-invariance requirement for it
 | 
			
		||||
            if (!is_const(disc)) {
 | 
			
		||||
                unsigned lvl = max_var(disc);
 | 
			
		||||
                add_to_Q_if_new(property(prop_enum::sgn_inv_irreducible, disc, /*s_idx*/ 0u, lvl));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // non_null is established by the discriminant being non-zero at the sample
 | 
			
		||||
            erase_from_Q(p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void apply_pre(const property& p, result_struct* rs) {
 | 
			
		||||
            TRACE(levelwise, display(tout << "property p:", p) << std::endl;);
 | 
			
		||||
            if (p.prop_tag == prop_enum::an_del)
 | 
			
		||||
                apply_pre_an_del(p);
 | 
			
		||||
            else if (p.prop_tag == prop_enum::connected)
 | 
			
		||||
                apply_pre_connected(p, rs ); 
 | 
			
		||||
            else 
 | 
			
		||||
            else if (p.prop_tag == prop_enum::non_null)
 | 
			
		||||
                apply_pre_non_null(p);
 | 
			
		||||
            else      
 | 
			
		||||
                NOT_IMPLEMENTED_YET();
 | 
			
		||||
        }
 | 
			
		||||
        // return an empty vector on failure, otherwise returns the cell representations with intervals
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue