3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-16 05:48:44 +00:00

wip - trim

This commit is contained in:
Nikolaj Bjorner 2022-10-06 18:19:03 +02:00
parent 4e780d0cc8
commit 9f78a96c1d
5 changed files with 114 additions and 22 deletions

View file

@ -189,8 +189,10 @@ class proof_trim {
cmd_context& ctx; cmd_context& ctx;
ast_manager& m; ast_manager& m;
sat::proof_trim trim; sat::proof_trim trim;
euf::proof_checker m_checker;
vector<expr_ref_vector> m_clauses; vector<expr_ref_vector> m_clauses;
bool_vector m_is_infer; bool_vector m_is_infer;
symbol m_rup;
void mk_clause(expr_ref_vector const& clause) { void mk_clause(expr_ref_vector const& clause) {
trim.init_clause(); trim.init_clause();
@ -208,12 +210,18 @@ class proof_trim {
bool sign = m.is_not(arg, arg); bool sign = m.is_not(arg, arg);
trim.add_literal(mk_var(arg), sign); trim.add_literal(mk_var(arg), sign);
} }
bool is_rup(expr* hint) const {
return hint && is_app(hint) && to_app(hint)->get_decl()->get_name() == m_rup;
}
public: public:
proof_trim(cmd_context& ctx): proof_trim(cmd_context& ctx):
ctx(ctx), ctx(ctx),
m(ctx.m()), m(ctx.m()),
trim(gparams::get_module("sat"), m.limit()) { trim(gparams::get_module("sat"), m.limit()),
m_checker(m) {
m_rup = symbol("rup");
} }
void assume(expr_ref_vector const& clause) { void assume(expr_ref_vector const& clause) {
@ -227,14 +235,52 @@ public:
mk_clause(_clause); mk_clause(_clause);
trim.del(); trim.del();
} }
/**
* Theory axioms are treated as assumptions.
* Some literals in the theory axioms may have been removed
* because they are false at base level. To reconstruct this
* dependency rely on the proof_checker to produce the original
* clauses. Thus, trim isn't correct for theory axioms that don't
* have a way to return clauses.
* The clauses can be retrieved directly from the justification
* that is used internally, so adding clause retrieval for every
* theory axiom is possible even if there are no checkers.
* In this case, the proof_checker::check dependency should not
* be used.
*/
void infer(expr_ref_vector const& clause, app* hint) { void infer(expr_ref_vector const& clause, app* hint) {
if (hint && !is_rup(hint) && m_checker.check(hint)) {
auto clause1 = m_checker.clause(hint);
if (clause1.size() != clause.size()) {
mk_clause(clause1);
trim.assume(m_clauses.size());
clause1.push_back(hint);
m_clauses.push_back(clause1);
m_is_infer.push_back(false);
mk_clause(clause);
trim.infer(m_clauses.size());
m_clauses.push_back(clause);
m_clauses.back().push_back(hint);
m_is_infer.push_back(true);
if (clause.empty())
do_trim(std::cout);
return;
}
}
mk_clause(clause); mk_clause(clause);
trim.infer(m_clauses.size()); if (is_rup(hint))
trim.infer(m_clauses.size());
else
trim.assume(m_clauses.size());
m_clauses.push_back(clause); m_clauses.push_back(clause);
if (hint) if (hint)
m_clauses.back().push_back(hint); m_clauses.back().push_back(hint);
m_is_infer.push_back(true); m_is_infer.push_back(is_rup(hint));
if (clause.empty())
do_trim(std::cout);
} }
void updt_params(params_ref const& p) { void updt_params(params_ref const& p) {
@ -254,7 +300,7 @@ public:
pp.define_expr(out, e); pp.define_expr(out, e);
if (!is_infer) if (!is_infer)
out << "(assume "; out << "(assume";
else else
out << "(infer"; out << "(infer";
for (expr* e : clause) for (expr* e : clause)

View file

@ -40,7 +40,10 @@ namespace sat {
revive(cl, clp); revive(cl, clp);
continue; continue;
} }
IF_VERBOSE(0, s.display(verbose_stream()));
prune_trail(cl, clp); prune_trail(cl, clp);
IF_VERBOSE(0, verbose_stream() << cl << " " << in_core(cl, clp) << ": "; for (auto const& c : m_core_literals) verbose_stream() << "{" << c << "} ");
IF_VERBOSE(0, s.display(verbose_stream() << "\n"));
del(cl, clp); del(cl, clp);
if (!in_core(cl, clp)) if (!in_core(cl, clp))
continue; continue;
@ -88,6 +91,9 @@ namespace sat {
m_in_clause.reset(); m_in_clause.reset();
m_in_coi.reset(); m_in_coi.reset();
if (cl.empty())
return;
for (literal lit : cl) for (literal lit : cl)
m_in_clause.insert(lit.index()); m_in_clause.insert(lit.index());
@ -130,6 +136,9 @@ namespace sat {
s.m_trail[j++] = s.m_trail[i]; s.m_trail[j++] = s.m_trail[i];
} }
s.m_trail.shrink(j); s.m_trail.shrink(j);
s.m_inconsistent = false;
s.m_qhead = s.m_trail.size();
s.propagate(false);
} }
@ -160,24 +169,38 @@ namespace sat {
*/ */
void proof_trim::conflict_analysis_core(literal_vector const& cl, clause* cp) { void proof_trim::conflict_analysis_core(literal_vector const& cl, clause* cp) {
IF_VERBOSE(3, verbose_stream() << "core " << cl << "\n");
if (cl.empty()) {
add_core(~s.m_not_l, s.m_conflict);
add_core(s.m_not_l, s.get_justification(s.m_not_l));
return;
}
SASSERT(!s.inconsistent());
s.push(); s.push();
unsigned lvl = s.scope_lvl(); unsigned lvl = s.scope_lvl();
for (auto lit : cl) for (auto lit : cl)
s.assign(~lit, justification(lvl)); s.assign(~lit, justification(lvl));
unsigned trail_size0 = s.m_trail.size(); unsigned trail_size0 = s.m_trail.size();
s.push();
s.propagate(false); s.propagate(false);
if (!s.inconsistent()) { if (!s.inconsistent()) {
s.m_qhead = 0; s.m_qhead = 0;
s.propagate(false); s.propagate(false);
} }
if (!s.inconsistent())
IF_VERBOSE(0, s.display(verbose_stream()));
SASSERT(s.inconsistent()); SASSERT(s.inconsistent());
for (unsigned i = trail_size0; i < s.m_trail.size(); ++i) for (unsigned i = trail_size0; i < s.m_trail.size(); ++i)
m_propagated[s.m_trail[i].var()] = true; m_propagated[s.m_trail[i].var()] = true;
if (s.m_not_l != null_literal) SASSERT(s.inconsistent());
IF_VERBOSE(3, verbose_stream() << s.m_not_l << " " << s.m_conflict << "\n");
if (s.m_not_l != null_literal) {
if (s.lvl(s.m_not_l) == 0)
add_core(~s.m_not_l, s.m_conflict);
add_dependency(s.m_not_l); add_dependency(s.m_not_l);
}
add_dependency(s.m_conflict); add_dependency(s.m_conflict);
for (unsigned i = s.m_trail.size(); i-- > trail_size0; ) { for (unsigned i = s.m_trail.size(); i-- > trail_size0; ) {
@ -188,7 +211,7 @@ namespace sat {
s.reset_mark(v); s.reset_mark(v);
add_dependency(s.get_justification(v)); add_dependency(s.get_justification(v));
} }
s.pop(2); s.pop(1);
} }
void proof_trim::add_dependency(literal lit) { void proof_trim::add_dependency(literal lit) {
@ -230,7 +253,8 @@ namespace sat {
m_clause.reset(); m_clause.reset();
switch (j.get_kind()) { switch (j.get_kind()) {
case justification::NONE: case justification::NONE:
return; m_clause.push_back(l);
break;
case justification::BINARY: case justification::BINARY:
m_clause.push_back(l); m_clause.push_back(l);
m_clause.push_back(j.get_literal()); m_clause.push_back(j.get_literal());
@ -242,12 +266,14 @@ namespace sat {
break; break;
case justification::CLAUSE: case justification::CLAUSE:
s.get_clause(j).mark_used(); s.get_clause(j).mark_used();
IF_VERBOSE(3, verbose_stream() << "add core " << s.get_clause(j) << "\n");
return; return;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
} }
std::sort(m_clause.begin(), m_clause.end()); std::sort(m_clause.begin(), m_clause.end());
IF_VERBOSE(3, verbose_stream() << "add core " << m_clause << "\n");
m_core_literals.insert(m_clause); m_core_literals.insert(m_clause);
} }
@ -268,7 +294,7 @@ namespace sat {
clause* proof_trim::del(literal_vector const& cl) { clause* proof_trim::del(literal_vector const& cl) {
clause* cp = nullptr; clause* cp = nullptr;
IF_VERBOSE(3, verbose_stream() << "del: " << cl << "\n"); IF_VERBOSE(3, verbose_stream() << "del: " << cl << "\n");
if (m_clause.size() == 2) { if (cl.size() == 2) {
s.detach_bin_clause(cl[0], cl[1], true); s.detach_bin_clause(cl[0], cl[1], true);
return cp; return cp;
} }
@ -294,12 +320,13 @@ namespace sat {
} }
proof_trim::proof_trim(params_ref const& p, reslimit& lim): proof_trim::proof_trim(params_ref const& p, reslimit& lim):
s(p, lim) s(p, lim) {
{} s.set_trim();
}
void proof_trim::assume(unsigned id, bool is_initial) { void proof_trim::assume(unsigned id, bool is_initial) {
std::sort(m_clause.begin(), m_clause.end()); std::sort(m_clause.begin(), m_clause.end());
IF_VERBOSE(3, verbose_stream() << "add: " << m_clause << "\n"); IF_VERBOSE(3, verbose_stream() << (is_initial?"assume ":"rup ") << m_clause << "\n");
auto* cl = s.mk_clause(m_clause, status::redundant()); auto* cl = s.mk_clause(m_clause, status::redundant());
m_trail.push_back({ id, m_clause, cl, true, is_initial }); m_trail.push_back({ id, m_clause, cl, true, is_initial });
s.propagate(false); s.propagate(false);

View file

@ -416,7 +416,7 @@ namespace sat {
bool logged = false; bool logged = false;
if (!redundant || !st.is_sat()) { if (!redundant || !st.is_sat()) {
unsigned old_sz = num_lits; unsigned old_sz = num_lits;
bool keep = simplify_clause(num_lits, lits); bool keep = m_trim || simplify_clause(num_lits, lits);
TRACE("sat_mk_clause", tout << "mk_clause (after simp), keep: " << keep << "\n" << mk_lits_pp(num_lits, lits) << "\n";); TRACE("sat_mk_clause", tout << "mk_clause (after simp), keep: " << keep << "\n" << mk_lits_pp(num_lits, lits) << "\n";);
if (!keep) { if (!keep) {
return nullptr; // clause is equivalent to true. return nullptr; // clause is equivalent to true.
@ -461,16 +461,16 @@ namespace sat {
m_touched[l1.var()] = m_touch_index; m_touched[l1.var()] = m_touch_index;
m_touched[l2.var()] = m_touch_index; m_touched[l2.var()] = m_touch_index;
if (redundant && find_binary_watch(get_wlist(~l1), ~l2) && value(l1) == l_undef) { if (redundant && !m_trim && find_binary_watch(get_wlist(~l1), ~l2) && value(l1) == l_undef) {
assign_unit(l1); assign_unit(l1);
return; return;
} }
if (redundant && find_binary_watch(get_wlist(~l2), ~l1) && value(l2) == l_undef) { if (redundant && !m_trim && find_binary_watch(get_wlist(~l2), ~l1) && value(l2) == l_undef) {
assign_unit(l2); assign_unit(l2);
return; return;
} }
watched* w0 = redundant ? find_binary_watch(get_wlist(~l1), l2) : nullptr; watched* w0 = redundant ? find_binary_watch(get_wlist(~l1), l2) : nullptr;
if (w0) { if (w0 && !m_trim) {
TRACE("sat", tout << "found binary " << l1 << " " << l2 << "\n";); TRACE("sat", tout << "found binary " << l1 << " " << l2 << "\n";);
if (w0->is_learned() && !redundant) { if (w0->is_learned() && !redundant) {
w0->set_learned(false); w0->set_learned(false);
@ -487,9 +487,10 @@ namespace sat {
if (m_config.m_drat) if (m_config.m_drat)
m_drat.add(l1, l2, st); m_drat.add(l1, l2, st);
if (propagate_bin_clause(l1, l2)) { if (propagate_bin_clause(l1, l2)) {
if (at_base_lvl()) if (!at_base_lvl())
push_reinit_stack(l1, l2);
else if (!m_trim)
return; return;
push_reinit_stack(l1, l2);
} }
else if (has_variables_to_reinit(l1, l2)) else if (has_variables_to_reinit(l1, l2))
push_reinit_stack(l1, l2); push_reinit_stack(l1, l2);
@ -950,7 +951,8 @@ namespace sat {
if (j.level() == 0) { if (j.level() == 0) {
if (m_config.m_drat) if (m_config.m_drat)
drat_log_unit(l, j); drat_log_unit(l, j);
j = justification(0); // erase justification for level 0 if (!m_trim)
j = justification(0); // erase justification for level 0
} }
else { else {
VERIFY(!at_base_lvl()); VERIFY(!at_base_lvl());

View file

@ -174,6 +174,7 @@ namespace sat {
literal_vector m_trail; literal_vector m_trail;
clause_wrapper_vector m_clauses_to_reinit; clause_wrapper_vector m_clauses_to_reinit;
std::string m_reason_unknown; std::string m_reason_unknown;
bool m_trim = false;
svector<unsigned> m_visited; svector<unsigned> m_visited;
unsigned m_visited_ts; unsigned m_visited_ts;
@ -203,7 +204,7 @@ namespace sat {
class lookahead* m_cuber; class lookahead* m_cuber;
class i_local_search* m_local_search; class i_local_search* m_local_search;
statistics m_aux_stats; statistics m_aux_stats;
void del_clauses(clause_vector& clauses); void del_clauses(clause_vector& clauses);
@ -283,6 +284,8 @@ namespace sat {
random_gen& rand() { return m_rand; } random_gen& rand() { return m_rand; }
void set_trim() { m_trim = true; }
protected: protected:
void reset_var(bool_var v, bool ext, bool dvar); void reset_var(bool_var v, bool ext, bool dvar);
@ -399,7 +402,7 @@ namespace sat {
} }
} }
void update_assign(literal l, justification j) { void update_assign(literal l, justification j) {
if (j.level() == 0) if (j.level() == 0 && !m_trim)
m_justification[l.var()] = j; m_justification[l.var()] = j;
} }
void assign_unit(literal l) { assign(l, justification(0)); } void assign_unit(literal l) { assign(l, justification(0)); }

View file

@ -323,10 +323,12 @@ void theory_user_propagator::propagate_consequence(prop_info const& prop) {
ctx.set_conflict(js); ctx.set_conflict(js);
} }
else { else {
#if 1
for (auto& lit : m_lits) for (auto& lit : m_lits)
lit.neg(); lit.neg();
for (auto const& [a,b] : m_eqs) for (auto const& [a,b] : m_eqs)
m_lits.push_back(~mk_eq(a->get_expr(), b->get_expr(), false)); m_lits.push_back(~mk_eq(a->get_expr(), b->get_expr(), false));
#endif
literal lit; literal lit;
if (has_quantifiers(prop.m_conseq)) { if (has_quantifiers(prop.m_conseq)) {
@ -339,8 +341,20 @@ void theory_user_propagator::propagate_consequence(prop_info const& prop) {
else else
lit = mk_literal(prop.m_conseq); lit = mk_literal(prop.m_conseq);
ctx.mark_as_relevant(lit); ctx.mark_as_relevant(lit);
#if 0
justification* js =
ctx.mk_justification(
ext_theory_propagation_justification(
get_id(), ctx, m_lits.size(), m_lits.data(), m_eqs.size(), m_eqs.data(), lit));
ctx.assign(lit, js);
#endif
#if 1
m_lits.push_back(lit); m_lits.push_back(lit);
ctx.mk_th_lemma(get_id(), m_lits); ctx.mk_th_lemma(get_id(), m_lits);
#endif
TRACE("user_propagate", ctx.display(tout);); TRACE("user_propagate", ctx.display(tout););
} }
} }