3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-10-09 17:31:57 +00:00

add a lot of debug prints that need to be removed. some bugs are resolved but others remain

This commit is contained in:
Ilana Shapiro 2025-09-02 14:02:23 -07:00
parent de99704d42
commit f243963927
2 changed files with 43 additions and 23 deletions

View file

@ -49,17 +49,17 @@ namespace smt {
return ctx->m_stats.m_num_decisions / std::max(1u, ctx->m_stats.m_num_conflicts); return ctx->m_stats.m_num_decisions / std::max(1u, ctx->m_stats.m_num_conflicts);
} }
double parallel::worker::explicit_hardness(expr_ref_vector const& cube) { double parallel::worker::explicit_hardness(expr_ref_vector const& cube, unsigned initial_scope_lvl) {
double total = 0.0; double total = 0.0;
unsigned clause_count = 0; unsigned clause_count = 0;
LOG_WORKER(1, " CUBE SIZE IN EXPLICIT HARDNESS: " << cube.size() << "\n");
// Get the scope level before the cube is assumed
unsigned scope_lvl = ctx->get_scope_level();
// Build a set of bool_vars corresponding to the cube literals // Build a set of bool_vars corresponding to the cube literals
svector<bool_var> cube_vars; svector<bool_var> cube_vars;
for (expr* e : cube) { for (auto& e : cube) {
LOG_WORKER(1, " PROCESSING CUBE\n");
bool_var v = ctx->get_bool_var(e); bool_var v = ctx->get_bool_var(e);
LOG_WORKER(1, " Cube contains var " << v << "\n");
if (v != null_bool_var) cube_vars.push_back(v); if (v != null_bool_var) cube_vars.push_back(v);
} }
@ -69,26 +69,30 @@ namespace smt {
unsigned n_false = 0; unsigned n_false = 0;
bool satisfied = false; bool satisfied = false;
LOG_WORKER(1, " Clause has num literals: " << clause.get_num_literals() << "\n");
for (literal l : clause) { for (literal l : clause) {
bool_var v = l.var(); bool_var v = l.var();
// Only consider literals that are part of the cube // Only consider literals that are part of the cube
LOG_WORKER(1, " Cube contains " << v << ": " << (cube_vars.contains(v)) << "\n");
if (!cube_vars.contains(v)) continue; if (!cube_vars.contains(v)) continue;
lbool val = ctx->get_assignment(l); lbool val = ctx->get_assignment(l);
unsigned lvl = ctx->get_assign_level(l); unsigned lvl = ctx->get_assign_level(l);
// Only include assignments made after the base scope level (i.e. those made by specifically assuming the cube) // Only include assignments made after the base scope level (i.e. those made by specifically assuming the cube)
if (lvl <= scope_lvl) continue; LOG_WORKER(1, " Literal " << l << " at level " << lvl << " is equal or below scope level " << initial_scope_lvl << ": " << bool(lvl <= initial_scope_lvl) << "\n");
if (lvl <= initial_scope_lvl) continue;
sz++; sz++;
if (val == l_true) { satisfied = true; break; } if (val == l_true) { satisfied = true; break; }
if (val == l_false) n_false++; if (val == l_false) n_false++;
} }
LOG_WORKER(1, " Clause of size " << sz << " has " << n_false << " false literals in cube. Is satisfied: " << satisfied << "\n");
if (satisfied || sz == 0) continue; if (satisfied || sz == 0) continue;
double m = static_cast<double>(sz) / std::max(1u, sz - n_false); double m = static_cast<double>(sz) / std::max(1u, sz - n_false);
LOG_WORKER(1, " Clause contributes " << m << " to hardness metric\n");
total += m; total += m;
clause_count++; clause_count++;
} }
@ -114,7 +118,7 @@ namespace smt {
} }
if (!occurs) continue; if (!occurs) continue;
if (clause.get_num_atoms() >= 2) { if (clause.get_num_literals() >= 2) {
count += 1; count += 1;
} }
} }
@ -123,12 +127,12 @@ namespace smt {
}; };
for (expr* e : cube) { for (expr* e : cube) {
literal lit = ctx->get_literal(e); // you may need your own expr→literal helper literal lit = ctx->get_literal(e);
double score = 0.0; double score = 0.0;
for (auto* cp : ctx->m_aux_clauses) { for (auto* cp : ctx->m_aux_clauses) {
auto& clause = *cp; auto& clause = *cp;
if (clause.get_num_atoms() == 2) { // binary clauses if (clause.get_num_literals() == 2) { // binary clauses
literal a = clause[0]; literal a = clause[0];
literal b = clause[1]; literal b = clause[1];
if (a == lit && ctx->get_assignment(b) == l_undef) { if (a == lit && ctx->get_assignment(b) == l_undef) {
@ -136,7 +140,7 @@ namespace smt {
} else if (b == lit && ctx->get_assignment(a) == l_undef) { } else if (b == lit && ctx->get_assignment(a) == l_undef) {
score += literal_occs(a) / 4.0; score += literal_occs(a) / 4.0;
} }
} else if (clause.get_num_atoms() == 3) { // ternary clauses containing ~lit } else if (clause.get_num_literals() == 3) { // ternary clauses containing ~lit
bool has_neg = false; bool has_neg = false;
std::vector<literal> others; std::vector<literal> others;
for (literal l2 : clause) { for (literal l2 : clause) {
@ -150,7 +154,7 @@ namespace smt {
score += (literal_occs(others[0]) + literal_occs(others[1])) / 8.0; score += (literal_occs(others[0]) + literal_occs(others[1])) / 8.0;
} }
} else { // n-ary clauses (size > 3) containing ~lit } else { // n-ary clauses (size > 3) containing ~lit
unsigned len = clause.get_num_atoms(); unsigned len = clause.get_num_literals();
if (len > 3) { if (len > 3) {
bool has_neg = false; bool has_neg = false;
double to_add = 0.0; double to_add = 0.0;
@ -182,14 +186,14 @@ namespace smt {
unsigned n = 0; unsigned n = 0;
for (expr* e : cube) { for (expr* e : cube) {
bool_var v = ctx->get_bool_var(e); // assumes you have expr→bool_var bool_var v = ctx->get_bool_var(e);
literal l(v, false); literal l(v, false);
auto big_occs = [&](literal lit) { auto big_occs = [&](literal lit) {
unsigned count = 0; unsigned count = 0;
for (auto* cp : ctx->m_aux_clauses) { for (auto* cp : ctx->m_aux_clauses) {
auto& clause = *cp; auto& clause = *cp;
if (clause.get_num_atoms() >= 3) { if (clause.get_num_literals() >= 3) {
for (literal li : clause) { for (literal li : clause) {
if (li == lit) { count++; break; } if (li == lit) { count++; break; }
} }
@ -206,7 +210,7 @@ namespace smt {
// binary neighbors of lit // binary neighbors of lit
for (auto* cp : ctx->m_aux_clauses) { for (auto* cp : ctx->m_aux_clauses) {
auto& clause = *cp; auto& clause = *cp;
if (clause.get_num_atoms() == 2) { // binary clauses if (clause.get_num_literals() == 2) { // binary clauses
literal a = clause[0]; literal a = clause[0];
literal b = clause[1]; literal b = clause[1];
if (a == lit && ctx->get_assignment(b) == l_undef) { if (a == lit && ctx->get_assignment(b) == l_undef) {
@ -244,8 +248,15 @@ namespace smt {
} }
LOG_WORKER(1, " checking cube\n"); LOG_WORKER(1, " checking cube\n");
unsigned initial_scope_lvl = ctx->get_scope_level();
LOG_WORKER(1, " CUBE SIZE IN MAIN LOOP: " << cube.size() << "\n");
lbool r = check_cube(cube); lbool r = check_cube(cube);
if (m.limit().is_canceled()) {
LOG_WORKER(1, " cancelled\n");
return;
}
switch (r) { switch (r) {
case l_undef: { case l_undef: {
LOG_WORKER(1, " found undef cube\n"); LOG_WORKER(1, " found undef cube\n");
@ -258,12 +269,14 @@ namespace smt {
auto split_atoms = get_split_atoms(); auto split_atoms = get_split_atoms();
LOG_WORKER(1, " CUBING\n"); LOG_WORKER(1, " CUBING\n");
if (m_config.m_iterative_deepening || m_config.m_beam_search) { // let's automatically do iterative deepening for beam search // let's automatically do iterative deepening for beam search.
// when using more advanced metrics like explicit_hardness etc: need one of two things: (1) split if greater than OR EQUAL TO than avg hardness, or (3) enter this branch only when cube.size() > 0, or else we get stuck in a loop of never deepening.
if (m_config.m_iterative_deepening || m_config.m_beam_search) {
LOG_WORKER(1, " applying iterative deepening\n"); LOG_WORKER(1, " applying iterative deepening\n");
double cube_hardness; double cube_hardness;
if (m_config.m_explicit_hardness) { if (m_config.m_explicit_hardness) {
cube_hardness = explicit_hardness(cube); cube_hardness = explicit_hardness(cube, initial_scope_lvl);
LOG_WORKER(1, " explicit hardness: " << cube_hardness << "\n"); LOG_WORKER(1, " explicit hardness: " << cube_hardness << "\n");
} else if (m_config.m_march_hardness) { } else if (m_config.m_march_hardness) {
cube_hardness = march_cu_hardness(cube); cube_hardness = march_cu_hardness(cube);
@ -278,7 +291,7 @@ namespace smt {
const double avg_hardness = b.update_avg_cube_hardness(cube_hardness); const double avg_hardness = b.update_avg_cube_hardness(cube_hardness);
const double factor = 1; // can tune for multiple of avg hardness later const double factor = 1; // can tune for multiple of avg hardness later
bool should_split = cube_hardness > avg_hardness * factor; bool should_split = cube_hardness >= avg_hardness * factor;
LOG_WORKER(1, " cube hardness: " << cube_hardness << " avg: " << avg_hardness << " avg*factor: " << avg_hardness * factor << " should-split: " << should_split << "\n"); LOG_WORKER(1, " cube hardness: " << cube_hardness << " avg: " << avg_hardness << " avg*factor: " << avg_hardness * factor << " should-split: " << should_split << "\n");
// we still need to call return_cubes, even if we don't split, since we need to re-enqueue the current unsolved cube to the batch manager! // we still need to call return_cubes, even if we don't split, since we need to re-enqueue the current unsolved cube to the batch manager!
@ -508,6 +521,7 @@ namespace smt {
|| m_config.m_depth_splitting_only && m_cubes_depth_sets.empty()) { || m_config.m_depth_splitting_only && m_cubes_depth_sets.empty()) {
// special initialization: the first cube is emtpy, have the worker work on an empty cube. // special initialization: the first cube is emtpy, have the worker work on an empty cube.
cubes.push_back(expr_ref_vector(g2l.to())); cubes.push_back(expr_ref_vector(g2l.to()));
IF_VERBOSE(1, verbose_stream() << "Batch manager giving out empty cube.\n");
return; return;
} }
@ -530,6 +544,7 @@ namespace smt {
} else if (m_config.m_beam_search) { } else if (m_config.m_beam_search) {
// get the highest ranked cube // get the highest ranked cube
SASSERT(!m_cubes_pq.empty()); SASSERT(!m_cubes_pq.empty());
IF_VERBOSE(1, verbose_stream() << "Batch manager giving out cube with score " << m_cubes_pq.top().score << ".\n");
ScoredCube const& scored_cube = m_cubes_pq.top(); ScoredCube const& scored_cube = m_cubes_pq.top();
auto& cube = scored_cube.cube; auto& cube = scored_cube.cube;
@ -541,6 +556,7 @@ namespace smt {
cubes.push_back(l_cube); cubes.push_back(l_cube);
m_cubes_pq.pop(); m_cubes_pq.pop();
} else { } else {
IF_VERBOSE(1, verbose_stream() << "Batch manager giving out cube.\n");
auto& cube = m_cubes.back(); auto& cube = m_cubes.back();
expr_ref_vector l_cube(g2l.to()); expr_ref_vector l_cube(g2l.to());
for (auto& e : cube) { for (auto& e : cube) {
@ -680,7 +696,7 @@ namespace smt {
*/ */
void parallel::batch_manager::return_cubes(ast_translation& l2g, vector<expr_ref_vector>const& C_worker, expr_ref_vector const& A_worker, const bool should_split, const double hardness) { void parallel::batch_manager::return_cubes(ast_translation& l2g, vector<expr_ref_vector>const& C_worker, expr_ref_vector const& A_worker, const bool should_split, const double hardness) {
// SASSERT(!m_config.never_cube()); // SASSERT(!m_config.never_cube());
IF_VERBOSE(1, verbose_stream() << " Batch manager returning " << C_worker.size() << " cubes and " << A_worker.size() << " split atoms\n");
auto atom_in_cube = [&](expr_ref_vector const& cube, expr* atom) { auto atom_in_cube = [&](expr_ref_vector const& cube, expr* atom) {
return any_of(cube, [&](expr* e) { return e == atom || (m.is_not(e, e) && e == atom); }); return any_of(cube, [&](expr* e) { return e == atom || (m.is_not(e, e) && e == atom); });
}; };
@ -731,9 +747,10 @@ namespace smt {
// apply the frugal strategy to ALL incoming worker cubes, but save in the PQ data structure for beam search // apply the frugal strategy to ALL incoming worker cubes, but save in the PQ data structure for beam search
auto add_split_atom_pq = [&](expr* atom) { auto add_split_atom_pq = [&](expr* atom) {
// IF_VERBOSE(1, verbose_stream() << " Adding split atom to PQ: " << mk_bounded_pp(atom, m, 3) << "\n");
for (auto& c : C_worker) { for (auto& c : C_worker) {
if (c.size() >= m_config.m_max_cube_depth || !should_split) { if (c.size() >= m_config.m_max_cube_depth || !should_split) {
IF_VERBOSE(1, verbose_stream() << " Skipping split of cube at max depth " << m_config.m_max_cube_depth << "\n";); // IF_VERBOSE(1, verbose_stream() << " Skipping split of cube at max depth " << m_config.m_max_cube_depth << "\n";);
continue; continue;
} }
@ -754,6 +771,8 @@ namespace smt {
cube_neg.push_back(m.mk_not(atom)); cube_neg.push_back(m.mk_not(atom));
m_cubes_pq.push(ScoredCube(d / hardness, cube_neg)); m_cubes_pq.push(ScoredCube(d / hardness, cube_neg));
// IF_VERBOSE(1, verbose_stream() << " PQ size now: " << m_cubes_pq.size() << ". PQ is empty: " << m_cubes_pq.empty() << "\n");
m_stats.m_num_cubes += 2; m_stats.m_num_cubes += 2;
m_stats.m_max_cube_depth = std::max(m_stats.m_max_cube_depth, d + 1); m_stats.m_max_cube_depth = std::max(m_stats.m_max_cube_depth, d + 1);
} }
@ -845,9 +864,10 @@ namespace smt {
if (!m_split_atoms.contains(g_atom)) if (!m_split_atoms.contains(g_atom))
m_split_atoms.push_back(g_atom); m_split_atoms.push_back(g_atom);
if (should_split && (m_config.m_depth_splitting_only || m_config.m_iterative_deepening)) { if (should_split && (m_config.m_depth_splitting_only || m_config.m_iterative_deepening)) {
IF_VERBOSE(1, verbose_stream() << " splitting worker cubes on new atom " << mk_bounded_pp(g_atom, m, 3) << "\n"); IF_VERBOSE(1, verbose_stream() << " splitting worker cubes on new atom for depth sets " << mk_bounded_pp(g_atom, m, 3) << "\n");
add_split_atom_deepest_cubes(g_atom); add_split_atom_deepest_cubes(g_atom);
} else if (m_config.m_beam_search) { } else if (should_split && m_config.m_beam_search) {
IF_VERBOSE(1, verbose_stream() << " splitting worker cubes on new atom for PQ " << mk_bounded_pp(g_atom, m, 3) << "\n");
add_split_atom_pq(g_atom); add_split_atom_pq(g_atom);
} else { } else {
add_split_atom(g_atom, initial_m_cubes_size); add_split_atom(g_atom, initial_m_cubes_size);

View file

@ -192,7 +192,7 @@ namespace smt {
expr_ref_vector get_backbones_from_candidates(expr_ref_vector const& candidates); expr_ref_vector get_backbones_from_candidates(expr_ref_vector const& candidates);
double naive_hardness(); double naive_hardness();
double explicit_hardness(expr_ref_vector const& cube); double explicit_hardness(expr_ref_vector const& cube, unsigned initial_scope_lvl);
double heule_schur_hardness(expr_ref_vector const& cube); double heule_schur_hardness(expr_ref_vector const& cube);
double march_cu_hardness(expr_ref_vector const& cube); double march_cu_hardness(expr_ref_vector const& cube);
public: public: