3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 14:13:23 +00:00

fixes to trim

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2023-07-05 12:58:17 -07:00
parent f0d3cbe39d
commit 4ad3324d2e
2 changed files with 35 additions and 48 deletions

View file

@ -7,15 +7,13 @@
Abstract: Abstract:
proof replay and trim The proof is trimmed by re-running the proof steps and collecting justified literals
at level 0. The proof is obtained by back-tracing the justificiations attached to literals.
Author: Author:
Nikolaj Bjorner 2023-10-04 Nikolaj Bjorner 2023-10-04
Notes:
--*/ --*/
#include "sat/sat_proof_trim.h" #include "sat/sat_proof_trim.h"
@ -31,10 +29,7 @@ namespace sat {
vector<std::pair<unsigned, unsigned_vector>> proof_trim::trim() { vector<std::pair<unsigned, unsigned_vector>> proof_trim::trim() {
m_result.reset(); m_result.reset();
m_core_literals.reset();
m_propagated.resize(num_vars(), false); m_propagated.resize(num_vars(), false);
m_core_literals.insert(literal_vector());
m_core_literals.insert(m_conflict);
IF_VERBOSE(10, s.display(verbose_stream() << "trim\n")); IF_VERBOSE(10, s.display(verbose_stream() << "trim\n"));
@ -58,7 +53,7 @@ namespace sat {
del(cl, clp); del(cl, clp);
if (!in_core(cl)) if (!in_core(cl))
continue; continue;
IF_VERBOSE(4, verbose_stream() << cl << " in-core " << in_core(cl) << ": "; for (auto const& c : m_core_literals) verbose_stream() << "{" << c << "} "; verbose_stream() << "\n"); IF_VERBOSE(4, verbose_stream() << cl << " in-core " << in_core(cl) << ": "; for (auto const& [k,v] : m_clauses) verbose_stream() << "{" << v.m_clauses << "} "; verbose_stream() << "\n");
m_result.push_back({id, unsigned_vector()}); m_result.push_back({id, unsigned_vector()});
if (is_initial) if (is_initial)
@ -122,7 +117,6 @@ namespace sat {
auto js = s.get_justification(l); auto js = s.get_justification(l);
bool in_coi = false; bool in_coi = false;
//verbose_stream() << l << " " << js << "\n";
if (js.is_clause()) if (js.is_clause())
for (literal lit : s.get_clause(js)) for (literal lit : s.get_clause(js))
in_coi |= m_in_coi.contains(lit.index()); in_coi |= m_in_coi.contains(lit.index());
@ -281,19 +275,18 @@ namespace sat {
} }
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"); IF_VERBOSE(3, verbose_stream() << "add core " << m_clause << "\n");
unsigned id; auto& [clauses, id, in_core] = m_clauses.find(m_clause);
VERIFY(m_clause2id.find(m_clause, id)); in_core = true;
m_result.back().second.push_back(id); m_result.back().second.push_back(id);
m_core_literals.insert(m_clause);
if (l != null_literal && s.lvl(l) == 0) { if (l != null_literal && s.lvl(l) == 0) {
m_clause.reset(); m_clause.reset();
m_clause.push_back(l); m_clause.push_back(l);
m_core_literals.insert(m_clause); m_clauses.insert_if_not_there(m_clause, {{}, 0, true }).m_in_core = true;
} }
} }
bool proof_trim::in_core(literal_vector const& cl) const { bool proof_trim::in_core(literal_vector const& cl) const {
return m_core_literals.contains(cl); return m_clauses.find(cl).m_in_core;
} }
void proof_trim::revive(literal_vector const& cl, clause* cp) { void proof_trim::revive(literal_vector const& cl, clause* cp) {
@ -313,24 +306,16 @@ namespace sat {
auto* e = m_clauses.find_core(cl); auto* e = m_clauses.find_core(cl);
if (!e) if (!e)
return cp; return cp;
auto& v = e->get_data().m_value; auto& [clauses, id, in_core] = e->get_data().m_value;
if (!v.empty()) { if (!clauses.empty()) {
cp = v.back(); cp = clauses.back();
TRACE("sat", tout << "del: " << *cp << "\n"); TRACE("sat", tout << "del: " << *cp << "\n");
s.detach_clause(*cp); s.detach_clause(*cp);
v.pop_back(); clauses.pop_back();
} }
return cp; return cp;
} }
void proof_trim::save(literal_vector const& lits, clause* cl) {
if (!cl)
return;
IF_VERBOSE(3, verbose_stream() << "add: " << *cl << "\n");
auto& v = m_clauses.insert_if_not_there(lits, clause_vector());
v.push_back(cl);
}
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(); s.set_trim();
@ -340,21 +325,23 @@ namespace sat {
std::sort(m_clause.begin(), m_clause.end()); std::sort(m_clause.begin(), m_clause.end());
if (unit_or_binary_occurs()) if (unit_or_binary_occurs())
return; return;
if (!m_conflict.empty() && m_clause.empty()) if (!m_conflict.empty() && m_clause.empty()) {
m_trail.push_back({id , m_clause, nullptr, true, is_initial}); m_clauses.insert(m_clause, { {}, id, m_clause.empty() });
m_trail.push_back({ id , m_clause, nullptr, true, is_initial });
}
if (!m_conflict.empty()) if (!m_conflict.empty())
return; return;
IF_VERBOSE(3, verbose_stream() << (is_initial?"assume ":"rup ") << m_clause << "\n"); IF_VERBOSE(3, verbose_stream() << (is_initial?"assume ":"rup ") << m_clause << "\n");
std::sort(m_clause.begin(), m_clause.end());
m_clause2id.insert(m_clause, id);
auto* cl = s.mk_clause(m_clause, status::redundant()); auto* cl = s.mk_clause(m_clause, status::redundant());
auto& [clauses, id2, in_core] = m_clauses.insert_if_not_there(m_clause, { {}, id, m_clause.empty() });
if (cl)
clauses.push_back(cl);
m_trail.push_back({ id, m_clause, cl, true, is_initial });
auto is_unit2 = [&]() { auto is_unit2 = [&]() {
if (s.value(m_clause[0]) == l_false) { if (s.value(m_clause[0]) == l_false)
std::swap(m_clause[0], m_clause[1]); std::swap(m_clause[0], m_clause[1]);
return true;
}
return s.value(m_clause[1]) == l_false; return s.value(m_clause[1]) == l_false;
}; };
@ -375,7 +362,6 @@ namespace sat {
return false; return false;
}; };
m_trail.push_back({ id, m_clause, cl, true, is_initial });
if (m_clause.size() == 2 && is_unit2()) if (m_clause.size() == 2 && is_unit2())
s.propagate_bin_clause(m_clause[0], m_clause[1]); s.propagate_bin_clause(m_clause[0], m_clause[1]);
else if (m_clause.size() > 2 && is_unit()) else if (m_clause.size() > 2 && is_unit())
@ -383,8 +369,6 @@ namespace sat {
s.propagate(false); s.propagate(false);
if (s.inconsistent() || all_of(m_clause, [&](sat::literal lit) { return s.value(lit) == l_false; })) if (s.inconsistent() || all_of(m_clause, [&](sat::literal lit) { return s.value(lit) == l_false; }))
set_conflict(m_clause, cl); set_conflict(m_clause, cl);
save(m_clause, cl);
} }
/** /**
@ -411,6 +395,4 @@ namespace sat {
void proof_trim::infer(unsigned id) { void proof_trim::infer(unsigned id) {
assume(id, false); assume(id, false);
} }
} }

View file

@ -47,10 +47,16 @@ namespace sat {
return a == b; return a == b;
} }
}; };
map<literal_vector, clause_vector, hash, eq> m_clauses;
map<literal_vector, unsigned, hash, eq> m_clause2id;
hashtable<literal_vector, hash, eq> m_core_literals;
struct clause_info {
clause_vector m_clauses;
unsigned m_id = 0;
bool m_in_core = false;
};
map<literal_vector, clause_info, hash, eq> m_clauses;
bool_vector m_propagated; bool_vector m_propagated;
void del(literal_vector const& cl, clause* cp); void del(literal_vector const& cl, clause* cp);
@ -65,7 +71,6 @@ namespace sat {
bool in_core(literal_vector const& cl) const; bool in_core(literal_vector const& cl) const;
void revive(literal_vector const& cl, clause* cp); void revive(literal_vector const& cl, clause* cp);
clause* del(literal_vector const& cl); clause* del(literal_vector const& cl);
void save(literal_vector const& lits, clause* cl);
uint_set m_units; uint_set m_units;
bool unit_or_binary_occurs(); bool unit_or_binary_occurs();