3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-25 00:12:34 +00:00

Parallel tactic (#9824) (#9825)

Add new parallel algorithm as a tactic (parallel_tactical2.cpp)
Don't port over old experiments from smt_parallel that we aren't using
(sls, inprocessing, failed_literal_mode for bb detection)
Fix bugs: lease cancellation/reslimit race condition, involves changing
lease epoch to simple boolean flag
Also, now there is a single shared set of params for the tactic and
smt_parallel

**Test runs for the parallel_tactical2 vs old smt_parallel version:**
run-2747-Z3-threads-4-qflia-30s-stats.md
run-2746-Z3-threads-4-qflia-30s-parallel_tactic-stats.md
run-2745-Z3-threads-1-qfbv-30s-stats.md
run-3013-Z3-threads-4-qfbv-30s-parallel_tactic-stats.md --> note this is
indeed run-3013, I reran after a bugfix in inc_sat_solver
run-2743-Z3-threads-4-qfnia-30s-stats.md
run-2742-Z3-threads-4-qfnia-30s-parallel_tactic-stats.md

**Test runs for the new smt_parallel with bugfixes:**
run-2801-Z3-threads-4-qflia-30s-smtparallel-bugfixes-stats.md,
run-2800-Z3-threads-4-qflia-30s-smtparallel-bugfixes-stats.md
run-2797-Z3-threads-4-qfnia-30s-smtparallel-bugfixes-stats.md
compare to old smt_parallel:
run-2747-Z3-threads-4-qflia-30s-stats.md
run-2743-Z3-threads-4-qfnia-30s-stats.md

Note that there is a slight regression on lia in run-2800. The source of
this appears to be the new new LP largest-cube LIA heuristic param,
which is enabled by default. disabling this param in run-2801 restored
performance (I didn't change this in this PR though, just something to
note)

http://mtzguido.tplinkdns.com:8081/z3/compare_stats.html

---------

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
Co-authored-by: Ilana Shapiro <ilanashapiro@Ilanas-MacBook-Pro.local>
Co-authored-by: Ilana Shapiro <ilanashapiro@Ilanas-MBP.localdomain>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Nikolaj Bjorner 2026-06-26 09:36:15 -07:00 committed by GitHub
parent 15f33f458d
commit 612fab1c9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 2694 additions and 1796 deletions

View file

@ -27,7 +27,6 @@ Notes:
#include "solver/tactic2solver.h"
#include "solver/parallel_params.hpp"
#include "solver/parallel_tactical.h"
#include "solver/parallel_tactical2.h"
#include "tactic/tactical.h"
#include "tactic/aig/aig_tactic.h"
#include "tactic/core/propagate_values_tactic.h"
@ -391,6 +390,15 @@ public:
if (m_preprocess) m_preprocess->collect_statistics(st);
m_solver.collect_statistics(st);
}
void set_max_conflicts(unsigned max_conflicts) override {
m_solver.set_max_conflicts(max_conflicts);
}
unsigned get_max_conflicts() const override {
return m_solver.get_max_conflicts();
}
void get_unsat_core(expr_ref_vector & r) override {
r.reset();
r.append(m_core.size(), m_core.data());
@ -405,6 +413,46 @@ public:
}
}
unsigned get_assign_level(expr* e) const override {
m.is_not(e, e);
sat::bool_var bv = m_map.to_bool_var(e);
return bv == sat::null_bool_var ? UINT_MAX : m_solver.lvl(bv);
}
bool is_relevant(expr* e) const override {
m.is_not(e, e);
sat::bool_var bv = m_map.to_bool_var(e);
if (bv == sat::null_bool_var)
return true;
auto* ext = dynamic_cast<euf::solver*>(m_solver.get_extension());
return !ext || ext->is_relevant(bv);
}
unsigned get_num_bool_vars() const override {
return m_solver.num_vars();
}
sat::bool_var get_bool_var(expr* e) const override {
m.is_not(e, e);
return m_map.to_bool_var(e);
}
expr* bool_var2expr(sat::bool_var v) const override {
return v < m_solver.num_vars() ? m_map.bool_var2expr(v) : nullptr;
}
lbool get_assignment(sat::bool_var v) const override {
return v < m_solver.num_vars() ? m_solver.value(v) : l_undef;
}
double get_activity(sat::bool_var v) const override {
return v < m_solver.num_vars() ? static_cast<double>(m_solver.get_activity(v)) : 0.0;
}
bool was_eliminated(sat::bool_var v) const override {
return v < m_solver.num_vars() && m_solver.was_eliminated(v);
}
expr_ref_vector get_trail(unsigned max_level) override {
expr_ref_vector result(m);
unsigned sz = m_solver.trail_size();
@ -482,6 +530,70 @@ public:
return fmls;
}
expr_ref cube_vsids(expr_ref_vector const& invalid_split_atoms) override {
if (!is_internalized()) {
lbool r = internalize_formulas();
if (r != l_true)
return expr_ref(m);
}
convert_internalized();
if (m_solver.inconsistent())
return expr_ref(m);
obj_hashtable<expr> invalid_split_atoms_set;
for (expr* e : invalid_split_atoms) {
expr* atom = e;
m.is_not(e, atom);
invalid_split_atoms_set.insert(atom);
}
expr_ref result(m);
double score = 0.0;
unsigned n = 0;
unsigned search_lvl = m_solver.search_lvl();
for (auto& kv : m_map) {
sat::bool_var v = kv.m_value;
if (was_eliminated(v))
continue;
if (get_assignment(v) != l_undef && m_solver.lvl(v) <= search_lvl)
continue;
expr* e = kv.m_key;
if (!e)
continue;
expr* atom = e;
m.is_not(e, atom);
if (invalid_split_atoms_set.contains(atom))
continue;
double new_score = get_activity(v);
if (new_score > score || !result || (new_score == score && m_solver.rand()(++n) == 0)) {
score = new_score;
result = e;
}
}
return result;
}
void get_backbone_candidates(vector<solver::scored_literal>& candidates, unsigned max_num) override {
if (!is_internalized()) {
lbool r = internalize_formulas();
if (r != l_true)
return;
}
convert_internalized();
sat::literal_vector lits;
m_solver.get_backbone_candidates(lits, max_num);
expr_ref_vector lit2expr(m);
lit2expr.resize(m_solver.num_vars() * 2);
m_map.mk_inv(lit2expr);
uint64_t now = m_solver.get_stats().m_conflicts;
for (sat::literal lit : lits) {
expr* e = lit2expr.get(lit.index());
if (!e)
continue;
candidates.push_back(scored_literal(m, e, static_cast<double>(now - m_solver.get_phase_birthdate(lit.var()))));
}
}
expr* congruence_next(expr* e) override { return e; }
expr* congruence_root(expr* e) override { return e; }
expr_ref congruence_explain(expr* a, expr* b) override { return expr_ref(m.mk_eq(a, b), m); }
@ -1186,7 +1298,5 @@ tactic * mk_psat_tactic(ast_manager& m, params_ref const& p) {
parallel_params pp(p);
if (pp.enable())
return mk_parallel_tactic(mk_inc_sat_solver(m, p, false), p);
if (pp.enable2())
return mk_parallel_tactic2(mk_inc_sat_solver(m, p, false), p);
return mk_sat_tactic(m);
}