mirror of
https://github.com/Z3Prover/z3
synced 2025-10-08 00:41:56 +00:00
move to global occurs list, throttle saturation lemmas based on monomial size
This commit is contained in:
parent
eff17a6252
commit
69a9d9f0b0
2 changed files with 45 additions and 36 deletions
|
@ -96,8 +96,10 @@ namespace nla {
|
|||
m_new_bounds.reset();
|
||||
m_to_refine.reset();
|
||||
m_factored_constraints.reset();
|
||||
m_max_monomial_degree = 0;
|
||||
m_coi.init();
|
||||
init_vars();
|
||||
init_occurs();
|
||||
}
|
||||
|
||||
void stellensatz::init_vars() {
|
||||
|
@ -141,6 +143,8 @@ namespace nla {
|
|||
m_ci2dep.setx(ci, dep, nullptr);
|
||||
}
|
||||
}
|
||||
for (auto const &[v, vars] : m_mon2vars)
|
||||
m_max_monomial_degree = std::max(m_max_monomial_degree, vars.size());
|
||||
}
|
||||
|
||||
void stellensatz::init_monomial(unsigned mon_var) {
|
||||
|
@ -404,6 +408,7 @@ namespace nla {
|
|||
SASSERT(m_values.size() - 1 == ti);
|
||||
m_new_bounds.insert(new_ci, bounds);
|
||||
m_ci2dep.setx(new_ci, nullptr, nullptr);
|
||||
init_occurs(new_ci);
|
||||
return new_ci;
|
||||
}
|
||||
|
||||
|
@ -412,35 +417,39 @@ namespace nla {
|
|||
auto new_ci = m_solver.lra().add_var_bound(j, k, rhs);
|
||||
m_new_bounds.insert(new_ci, bounds);
|
||||
m_ci2dep.setx(new_ci, nullptr, nullptr);
|
||||
init_occurs(new_ci);
|
||||
return new_ci;
|
||||
}
|
||||
|
||||
void stellensatz::init_occurs() {
|
||||
m_occurs.reset();
|
||||
for (auto ci : m_solver.lra().constraints().indices())
|
||||
init_occurs(ci);
|
||||
}
|
||||
|
||||
void stellensatz::init_occurs(lp::constraint_index ci) {
|
||||
auto const &con = m_solver.lra().constraints()[ci];
|
||||
for (auto [coeff, v] : con.coeffs()) {
|
||||
if (m_mon2vars.contains(v)) {
|
||||
for (auto w : m_mon2vars[v]) {
|
||||
if (w >= m_occurs.size())
|
||||
m_occurs.resize(w + 1);
|
||||
m_occurs[w].push_back(ci);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (v >= m_occurs.size())
|
||||
m_occurs.resize(v + 1);
|
||||
m_occurs[v].push_back(ci);
|
||||
}
|
||||
}
|
||||
|
||||
// record new monomials that are created and recursively down-saturate with respect to these.
|
||||
// this is a simplistic pass
|
||||
void stellensatz::saturate_constraints() {
|
||||
vector<svector<lp::constraint_index>> var2cs; // cs contain a term using v
|
||||
vector<svector<lp::constraint_index>> vars2cs; // cs contain a term with a monomial using v
|
||||
|
||||
// current approach: only resolve against var2cs, which is initialized
|
||||
// with monomials in the input.
|
||||
|
||||
for (auto ci : m_solver.lra().constraints().indices()) {
|
||||
auto const& con = m_solver.lra().constraints()[ci];
|
||||
for (auto [coeff, v] : con.coeffs()) {
|
||||
if (v >= var2cs.size())
|
||||
var2cs.resize(v + 1);
|
||||
var2cs[v].push_back(ci);
|
||||
if (m_mon2vars.contains(v)) {
|
||||
for (auto w : m_mon2vars[v]) {
|
||||
if (w >= vars2cs.size())
|
||||
vars2cs.resize(w + 1);
|
||||
vars2cs[w].push_back(ci);
|
||||
}
|
||||
}
|
||||
}
|
||||
// insert monomials to be refined
|
||||
insert_monomials_from_constraint(ci);
|
||||
}
|
||||
for (auto ci : m_solver.lra().constraints().indices())
|
||||
insert_monomials_from_constraint(ci);
|
||||
|
||||
auto is_subset = [&](svector<lpvar> const &a, svector<lpvar> const& b) {
|
||||
if (a.size() >= b.size())
|
||||
|
@ -459,24 +468,19 @@ namespace nla {
|
|||
auto j = m_to_refine[it];
|
||||
auto vars = m_mon2vars[j];
|
||||
for (auto v : vars) {
|
||||
if (v >= var2cs.size())
|
||||
if (v >= m_occurs.size())
|
||||
continue;
|
||||
svector<lpvar> _vars;
|
||||
_vars.push_back(v);
|
||||
for (auto ci : var2cs[v]) {
|
||||
for (auto [coeff, u] : m_solver.lra().constraints()[ci].coeffs()) {
|
||||
for (unsigned cidx = 0; cidx < m_occurs[v].size(); ++cidx) {
|
||||
auto ci = m_occurs[v][cidx];
|
||||
for (unsigned uidx = 0; uidx < m_solver.lra().constraints()[ci].coeffs().size(); ++uidx) {
|
||||
auto const &[coeff, u] = m_solver.lra().constraints()[ci].coeffs()[uidx];
|
||||
if (u == v)
|
||||
saturate_constraint(ci, j, _vars);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto v : vars) {
|
||||
if (v >= vars2cs.size())
|
||||
continue;
|
||||
for (auto ci : vars2cs[v]) {
|
||||
for (auto [coeff, u] : m_solver.lra().constraints()[ci].coeffs())
|
||||
if (m_mon2vars.contains(u) && is_subset(m_mon2vars[u], vars))
|
||||
else if (m_mon2vars.contains(u) && is_subset(m_mon2vars[u], vars))
|
||||
saturate_constraint(ci, j, m_mon2vars[u]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -550,7 +554,6 @@ namespace nla {
|
|||
IF_VERBOSE(4, display_constraint(verbose_stream(), old_ci) << " -> ";
|
||||
display_constraint(verbose_stream(), new_lhs.coeffs_as_vector(), k, new_rhs) << "\n");
|
||||
insert_monomials_from_constraint(new_ci);
|
||||
m_ci2dep.setx(new_ci, nullptr, nullptr);
|
||||
m_old_constraints.insert(new_ci, old_ci);
|
||||
m_factored_constraints.insert(new_ci); // don't bother to factor this because it comes from factors already
|
||||
}
|
||||
|
@ -822,12 +825,13 @@ namespace nla {
|
|||
|
||||
// if a constraint is false, then insert _all_ monomials from that constraint.
|
||||
// other approach: use a lex ordering on monomials and insert the lex leading monomial.
|
||||
// to avoid blowup, only insert monomials up to a certain degree.
|
||||
void stellensatz::insert_monomials_from_constraint(lp::constraint_index ci) {
|
||||
if (constraint_is_true(ci))
|
||||
return;
|
||||
auto const& con = m_solver.lra().constraints()[ci];
|
||||
for (auto [coeff, v] : con.coeffs())
|
||||
if (c().emons().is_monic_var(v))
|
||||
if (m_mon2vars.contains(v) && m_mon2vars[v].size() <= m_max_monomial_degree)
|
||||
m_to_refine.insert(v);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ namespace nla {
|
|||
};
|
||||
map<unsigned_vector, unsigned, svector_hash<unsigned_hash>, eq> m_vars2mon;
|
||||
u_map<unsigned_vector> m_mon2vars;
|
||||
unsigned m_max_monomial_degree = 0;
|
||||
|
||||
vector<svector<lp::constraint_index>> m_occurs; // map from variable to constraints they occur.
|
||||
|
||||
// for factoring
|
||||
small_object_allocator m_allocator;
|
||||
|
@ -82,6 +85,8 @@ namespace nla {
|
|||
void init_solver();
|
||||
void init_vars();
|
||||
void init_monomial(unsigned mon_var);
|
||||
void init_occurs();
|
||||
void init_occurs(lp::constraint_index ci);
|
||||
|
||||
bool constraint_is_true(lp::constraint_index ci);
|
||||
void insert_monomials_from_constraint(lp::constraint_index ci);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue