3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-25 12:35:59 +00:00

working on reconciling perf for arithmetic solvers

this update integrates inferences to smt.arith.solver=6 related to grobner basis computation and handling of div/mod axioms to reconcile performance with smt.arith.solver=2.

The default of smt.arth.nl.grobner_subs_fixed is changed to 1 to make comparison with solver=2 more direct.

The selection of cluster equalities for solver=6 was reconciled with how it is done for solver=2.
This commit is contained in:
Nikolaj Bjorner 2022-07-11 07:38:51 -07:00
parent 9d9414c111
commit b68af0c1e5
19 changed files with 357 additions and 282 deletions

View file

@ -80,14 +80,12 @@ void theory_arith<Ext>::mark_dependents(theory_var v, svector<theory_var> & vars
if (is_fixed(v))
return;
column & c = m_columns[v];
typename svector<col_entry>::iterator it = c.begin_entries();
typename svector<col_entry>::iterator end = c.end_entries();
for (; it != end; ++it) {
if (it->is_dead() || already_visited_rows.contains(it->m_row_id))
for (auto& ce : c) {
if (ce.is_dead() || already_visited_rows.contains(ce.m_row_id))
continue;
TRACE("non_linear_bug", tout << "visiting row: " << it->m_row_id << "\n";);
already_visited_rows.insert(it->m_row_id);
row & r = m_rows[it->m_row_id];
TRACE("non_linear_bug", tout << "visiting row: " << ce.m_row_id << "\n";);
already_visited_rows.insert(ce.m_row_id);
row & r = m_rows[ce.m_row_id];
theory_var s = r.get_base_var();
// ignore quasi base vars... actually they should not be used if the problem is non linear...
if (is_quasi_base(s))
@ -97,14 +95,10 @@ void theory_arith<Ext>::mark_dependents(theory_var v, svector<theory_var> & vars
// was eliminated by substitution.
if (s != null_theory_var && is_free(s) && s != v)
continue;
typename vector<row_entry>::const_iterator it2 = r.begin_entries();
typename vector<row_entry>::const_iterator end2 = r.end_entries();
for (; it2 != end2; ++it2) {
if (!it2->is_dead() && !is_fixed(it2->m_var))
mark_var(it2->m_var, vars, already_found);
if (!it2->is_dead() && is_fixed(it2->m_var)) {
TRACE("non_linear", tout << "skipped fixed\n";);
}
for (auto& re : r) {
if (!re.is_dead() && !is_fixed(re.m_var))
mark_var(re.m_var, vars, already_found);
CTRACE("non_linear", !re.is_dead() && is_fixed(re.m_var), tout << "skipped fixed\n");
}
}
}
@ -119,6 +113,7 @@ void theory_arith<Ext>::get_non_linear_cluster(svector<theory_var> & vars) {
return;
var_set already_found;
row_set already_visited_rows;
for (theory_var v : m_nl_monomials) {
expr * n = var2expr(v);
if (ctx.is_relevant(n))
@ -130,9 +125,9 @@ void theory_arith<Ext>::get_non_linear_cluster(svector<theory_var> & vars) {
TRACE("non_linear", tout << "marking dependents of: v" << v << "\n";);
mark_dependents(v, vars, already_found, already_visited_rows);
}
TRACE("non_linear", tout << "variables in non linear cluster:\n";
for (theory_var v : vars) tout << "v" << v << " ";
tout << "\n";);
TRACE("non_linear", tout << "variables in non linear cluster: ";
for (theory_var v : vars) tout << "v" << v << " "; tout << "\n";
for (theory_var v : m_nl_monomials) tout << "non-linear v" << v << " " << mk_pp(var2expr(v), m) << "\n";);
}
@ -1740,22 +1735,21 @@ grobner::monomial * theory_arith<Ext>::mk_gb_monomial(rational const & _coeff, e
*/
template<typename Ext>
void theory_arith<Ext>::add_row_to_gb(row const & r, grobner & gb) {
TRACE("non_linear", tout << "adding row to gb\n"; display_row(tout, r););
TRACE("grobner", tout << "adding row to gb\n"; display_row(tout, r););
ptr_buffer<grobner::monomial> monomials;
v_dependency * dep = nullptr;
m_tmp_var_set.reset();
typename vector<row_entry>::const_iterator it = r.begin_entries();
typename vector<row_entry>::const_iterator end = r.end_entries();
for (; it != end; ++it) {
if (!it->is_dead()) {
rational coeff = it->m_coeff.to_rational();
expr * m = var2expr(it->m_var);
TRACE("non_linear", tout << "monomial: " << mk_pp(m, get_manager()) << "\n";);
grobner::monomial * new_m = mk_gb_monomial(coeff, m, gb, dep, m_tmp_var_set);
TRACE("non_linear", tout << "new monomial:\n"; if (new_m) gb.display_monomial(tout, *new_m); else tout << "null"; tout << "\n";);
if (new_m)
monomials.push_back(new_m);
}
for (auto& re : r) {
if (re.is_dead())
continue;
rational coeff = re.m_coeff.to_rational();
expr * m = var2expr(re.m_var);
grobner::monomial * new_m = mk_gb_monomial(coeff, m, gb, dep, m_tmp_var_set);
if (new_m)
monomials.push_back(new_m);
TRACE("grobner",
tout << "monomial: " << mk_pp(m, get_manager()) << "\n";
tout << "new monomial: "; if (new_m) gb.display_monomial(tout, *new_m); else tout << "null"; tout << "\n";);
}
gb.assert_eq_0(monomials.size(), monomials.data(), dep);
}
@ -2158,8 +2152,9 @@ bool theory_arith<Ext>::get_gb_eqs_and_look_for_conflict(ptr_vector<grobner::equ
eqs.reset();
gb.get_equations(eqs);
TRACE("grobner", tout << "after gb\n";
std::function<void(std::ostream& out, expr* v)> _fn = [&](std::ostream& out, expr* v) { out << "v" << expr2var(v); };
for (grobner::equation* eq : eqs)
gb.display_equation(tout, *eq);
gb.display_equation(tout, *eq, _fn);
);
for (grobner::equation* eq : eqs) {
if (is_inconsistent(eq, gb) || is_inconsistent2(eq, gb)) {
@ -2259,7 +2254,9 @@ typename theory_arith<Ext>::gb_result theory_arith<Ext>::compute_grobner(svector
ptr_vector<grobner::equation> eqs;
do {
TRACE("non_linear_gb", tout << "before:\n"; gb.display(tout););
TRACE("grobner", tout << "before grobner:\n";
std::function<void(std::ostream& out, expr* v)> _fn = [&](std::ostream& out, expr* v) { out << "v" << expr2var(v); };
gb.display(tout, _fn));
compute_basis(gb, warn);
update_statistics(gb);
TRACE("non_linear_gb", tout << "after:\n"; gb.display(tout););