mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	move to lex-leading resolvents
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									fa2d7a1c57
								
							
						
					
					
						commit
						4162d89170
					
				
					 2 changed files with 59 additions and 72 deletions
				
			
		|  | @ -469,97 +469,72 @@ namespace nla { | |||
| 
 | ||||
|         unsigned initial_false_constraints = m_false_constraints.size(); | ||||
|         for (unsigned it = 0; it < m_false_constraints.size(); ++it) { | ||||
|             if (it > 5*initial_false_constraints) | ||||
|             if (it > 5 * initial_false_constraints) | ||||
|                 break; | ||||
|             auto ci1 = m_false_constraints[it]; | ||||
|             auto const &con = m_solver.lra().constraints()[ci1]; | ||||
|             for (auto const &cv1 : con.lhs()) { | ||||
|                 auto j = cv1.j(); | ||||
|                 if (!is_mon_var(j)) | ||||
|                     continue; | ||||
|                 auto vars = m_mon2vars[j]; | ||||
|                 if (vars.size() > m_max_monomial_degree) | ||||
|                     continue; | ||||
|                 for (auto v : vars) { | ||||
|                     if (v >= m_occurs.size()) | ||||
|                         continue; | ||||
|                     svector<lpvar> _vars; | ||||
|                     _vars.push_back(v); | ||||
|                     for (unsigned cidx = 0; cidx < m_occurs[v].size(); ++cidx) { | ||||
|                         auto ci2 = m_occurs[v][cidx];  | ||||
|                         for (auto const & cv2 : m_solver.lra().constraints()[ci2].lhs()) { | ||||
|                             auto u = cv2.j(); | ||||
|                             if (u == v && is_resolvable(ci1, cv1.coeff(), ci2, cv2.coeff())) | ||||
|                                 resolve(j, ci1, saturate_constraint(ci2, j, _vars)); | ||||
|                             else if (is_mon_var(u) && is_subset(m_mon2vars[u], vars) && | ||||
|                                      is_resolvable(ci1, cv1.coeff(), ci2, cv2.coeff())) | ||||
|                                 resolve(j, ci1, saturate_constraint(ci2, j, m_mon2vars[u])); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         #if 0 | ||||
|         for (unsigned it = 0; it < m_monomials_to_refine.size(); ++it) { | ||||
|             auto j = m_monomials_to_refine[it]; | ||||
|             lpvar j = find_max_lex_monomial(con.lhs()); | ||||
|             if (j == lp::null_lpvar) | ||||
|                 continue; | ||||
|             auto vars = m_mon2vars[j]; | ||||
|             TRACE(arith, tout << "j" << j << " " << vars << "\n"); | ||||
|             if (vars.size() > m_max_monomial_degree) | ||||
|                 continue; | ||||
|             for (auto v : vars) { | ||||
|                 if (v >= m_occurs.size()) | ||||
|                     continue; | ||||
|                 svector<lpvar> _vars; | ||||
|                 _vars.push_back(v); | ||||
|                 for (unsigned cidx = 0; cidx < m_occurs[v].size(); ++cidx) { | ||||
|                     auto ci = m_occurs[v][cidx];                    | ||||
|                     for (auto const &cv1 : m_solver.lra().constraints()[ci].lhs()) { | ||||
|                         auto u = cv1.j(); | ||||
|                     auto ci2 = m_occurs[v][cidx]; | ||||
|                     if (ci1 == ci2) | ||||
|                         continue; | ||||
|                     for (auto const &cv2 : m_solver.lra().constraints()[ci2].lhs()) { | ||||
|                         auto u = cv2.j(); | ||||
|                         if (u == v) | ||||
|                             saturate_constraint(ci, j, _vars); | ||||
|                         else if (is_mon_var(u) && is_subset(m_mon2vars[u], vars))  | ||||
|                             saturate_constraint(ci, j, m_mon2vars[u]); | ||||
|                             resolve(j, ci1, saturate_constraint(ci2, j, _vars)); | ||||
|                         else if (is_mon_var(u) && is_subset(m_mon2vars[u], vars)) | ||||
|                             resolve(j, ci1, saturate_constraint(ci2, j, m_mon2vars[u])); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         #endif | ||||
|         }         | ||||
|         IF_VERBOSE(5, | ||||
|                    c().lra_solver().display(verbose_stream() << "original\n"); | ||||
|                    c().display(verbose_stream()); | ||||
|                    display(verbose_stream() << "saturated\n")); | ||||
|     } | ||||
| 
 | ||||
|     bool stellensatz::is_resolvable(lp::constraint_index ci1, rational const& c1, lp::constraint_index ci2, | ||||
|         rational const& c2) const { | ||||
|         SASSERT(c1 != 0); | ||||
|         SASSERT(c2 != 0); | ||||
|         auto const &con1 = m_solver.lra().constraints()[ci1]; | ||||
|         auto const &con2 = m_solver.lra().constraints()[ci2]; | ||||
|         auto k1 = con1.kind(); | ||||
|         auto k2 = con2.kind(); | ||||
|         for (auto const& cv : con1.lhs())  | ||||
|             if (is_mon_var(cv.j()) && m_mon2vars[cv.j()].size() > m_max_monomial_degree) | ||||
|                 return false; | ||||
|         for (auto const &cv : con2.lhs()) | ||||
|             if (is_mon_var(cv.j()) && m_mon2vars[cv.j()].size() > m_max_monomial_degree) | ||||
|                 return false;         | ||||
|         bool same_sign = (c1.is_pos() == c2.is_pos()); | ||||
|         if (k1 == lp::lconstraint_kind::EQ) | ||||
|             return true; | ||||
|         if (k2 == lp::lconstraint_kind::EQ) | ||||
|             return true; | ||||
|         bool is_le1 = (k1 == lp::lconstraint_kind::LE || k1 == lp::lconstraint_kind::LT); | ||||
|         bool is_le2 = (k2 == lp::lconstraint_kind::LE || k2 == lp::lconstraint_kind::LT); | ||||
|         if ((is_le1 == is_le2) && !same_sign) | ||||
|             return true; | ||||
|         if ((is_le1 != is_le2) && same_sign) | ||||
|             return true; | ||||
|     lpvar stellensatz::find_max_lex_monomial(lp::lar_term const& t) const { | ||||
|         lpvar result = lp::null_lpvar; | ||||
|         for (auto const &cv : t) { | ||||
|             auto j = cv.j(); | ||||
|             if (!is_mon_var(j)) | ||||
|                 continue; | ||||
|             auto const &vars = m_mon2vars[j]; | ||||
|             if (result == lp::null_lpvar) | ||||
|                 result = j; | ||||
|             else if (std::lexicographical_compare(m_mon2vars[result].begin(), m_mon2vars[result].end(), vars.begin(), | ||||
|                                                   vars.end())) | ||||
|                 result = j; | ||||
|             else if (false && is_lex_greater(vars, m_mon2vars[result])) | ||||
|                 result = j;             | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     bool stellensatz::is_lex_greater(svector<lpvar> const& a, svector<lpvar> const& b) const { | ||||
|        if (a.size() != b.size()) | ||||
|             return a.size() > b.size(); | ||||
|         for (unsigned i = a.size(); i-- > 0;) { | ||||
|             if (a[i] != b[i]) | ||||
|                 return a[i] > b[i]; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     void stellensatz::resolve(lpvar j, lp::constraint_index ci1, lp::constraint_index ci2) { | ||||
|         // resolut of saturate_constraint could swap inequality, 
 | ||||
|         // so the premise of is_resolveable may not hold.
 | ||||
|         return; | ||||
|         auto const &constraints = m_solver.lra().constraints(); | ||||
|         if (!constraints.valid_index(ci1)) | ||||
|             return; | ||||
|  | @ -567,15 +542,19 @@ namespace nla { | |||
|             return; | ||||
|         auto const &con1 = constraints[ci1]; | ||||
|         auto const &con2 = constraints[ci2]; | ||||
|         for (auto const &cv : con1.lhs()) | ||||
|             if (is_mon_var(cv.j()) && m_mon2vars[cv.j()].size() > m_max_monomial_degree) | ||||
|                 return; | ||||
|         for (auto const &cv : con2.lhs()) | ||||
|             if (is_mon_var(cv.j()) && m_mon2vars[cv.j()].size() > m_max_monomial_degree) | ||||
|                 return;   | ||||
| 
 | ||||
|         auto k1 = con1.kind(); | ||||
|         auto k2 = con2.kind(); | ||||
|         auto const & lhs1 = con1.lhs(); | ||||
|         auto const & lhs2 = con2.lhs(); | ||||
|         auto const& c1 = lhs1.get_coeff(j); | ||||
|         auto const& c2 = lhs2.get_coeff(j); | ||||
|         verbose_stream() << "resolve on " << m_mon2vars[j] << " c1: " << c1 << " c2: " << c2 << "\n"; | ||||
|         display_constraint(verbose_stream(), ci1) << "\n"; | ||||
|         display_constraint(verbose_stream(), ci2) << "\n"; | ||||
|         rational mul1, mul2; | ||||
|         bool is_le1 = (k1 == lp::lconstraint_kind::LE || k1 == lp::lconstraint_kind::LT); | ||||
|         bool is_le2 = (k2 == lp::lconstraint_kind::LE || k2 == lp::lconstraint_kind::LT); | ||||
|  | @ -589,23 +568,30 @@ namespace nla { | |||
|             mul2 = (c2 > 0 ? -1 : 1) * c1; | ||||
|         }  | ||||
|         else if (is_le1 == is_le2) { | ||||
|             SASSERT(c1.is_pos() != c2.is_pos()); | ||||
|             if (c1.is_pos() == c2.is_pos()) | ||||
|                 return;  | ||||
|             mul1 = abs(c2); | ||||
|             mul2 = abs(c1); | ||||
|         }  | ||||
|         else { | ||||
|             SASSERT(c1.is_pos() == c2.is_pos()); | ||||
|             if (c1.is_pos() != c2.is_pos()) | ||||
|                 return; | ||||
|             mul1 = abs(c2); | ||||
|             mul2 = -abs(c1); | ||||
|         } | ||||
|         auto lhs = mul1 * lhs1 + mul2 * lhs2; | ||||
|         auto rhs = mul1 * con1.rhs() + mul2 * con2.rhs(); | ||||
|         if (lhs.size() == 0) // trivial conflict, will be found using LIA
 | ||||
|             return; | ||||
|         assumptions bounds; | ||||
|         bounds.push_back(ci1); | ||||
|         bounds.push_back(ci2); | ||||
|         auto new_ci = add_ineq("resolve", bounds, lhs, k1, rhs); | ||||
|         insert_monomials_from_constraint(new_ci); | ||||
|         display_constraint(verbose_stream(), new_ci) << "\n"; | ||||
|         IF_VERBOSE(3, verbose_stream() << "resolve on " << m_mon2vars[j] << " c1: " << c1 << " c2: " << c2 << "\n"; | ||||
|                    display_constraint(verbose_stream(), ci1) << "\n"; | ||||
|                    display_constraint(verbose_stream(), ci2) << "\n"; | ||||
|                    display_constraint(verbose_stream(), new_ci) << "\n"); | ||||
|     } | ||||
| 
 | ||||
|     // multiply by remaining vars
 | ||||
|  |  | |||
|  | @ -55,6 +55,8 @@ namespace nla { | |||
|         map<unsigned_vector, unsigned, svector_hash<unsigned_hash>, eq> m_vars2mon; | ||||
|         u_map<unsigned_vector> m_mon2vars; | ||||
|         bool is_mon_var(lpvar v) const { return m_mon2vars.contains(v); } | ||||
|         lpvar find_max_lex_monomial(lp::lar_term const &t) const; | ||||
|         bool is_lex_greater(svector<lpvar> const &a, svector<lpvar> const &b) const; | ||||
|          | ||||
|         unsigned m_max_monomial_degree = 0; | ||||
| 
 | ||||
|  | @ -107,7 +109,6 @@ namespace nla { | |||
|         lbool add_bounds(svector<lpvar> const &vars, assumptions &bounds); | ||||
|         void saturate_constraints(); | ||||
|         lp::constraint_index saturate_constraint(lp::constraint_index con_id, lp::lpvar mi, svector<lpvar> const & xs); | ||||
|         bool is_resolvable(lp::constraint_index ci1, rational const& c1, lp::constraint_index ci2, rational const& c2) const; | ||||
|          | ||||
|         void resolve(lpvar j, lp::constraint_index ci1, lp::constraint_index ci2); | ||||
|         void saturate_basic_linearize(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue