3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00
z3/lib/sat_model_converter.cpp
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

241 lines
8.3 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
sat_model_converter.cpp
Abstract:
Low level model converter for SAT solver.
Author:
Leonardo de Moura (leonardo) 2011-05-26.
Revision History:
--*/
#include"sat_model_converter.h"
#include"sat_clause.h"
#include"trace.h"
namespace sat {
model_converter::model_converter() {
}
model_converter::~model_converter() {
reset();
}
void model_converter::reset() {
m_entries.finalize();
}
void model_converter::operator()(model & m) const {
vector<entry>::const_iterator begin = m_entries.begin();
vector<entry>::const_iterator it = m_entries.end();
while (it != begin) {
--it;
SASSERT(it->get_kind() != ELIM_VAR || m[it->var()] == l_undef);
// if it->get_kind() == BLOCK_LIT, then it might be the case that m[it->var()] != l_undef,
// and the following procedure flips its value.
bool sat = false;
bool var_sign;
literal_vector::const_iterator it2 = it->m_clauses.begin();
literal_vector::const_iterator end2 = it->m_clauses.end();
for (; it2 != end2; ++it2) {
literal l = *it2;
if (l == null_literal) {
// end of clause
if (!sat) {
m[it->var()] = var_sign ? l_false : l_true;
break;
}
sat = false;
continue;
}
if (sat)
continue;
bool sign = l.sign();
bool_var v = l.var();
if (v == it->var())
var_sign = sign;
if (value_at(l, m) == l_true)
sat = true;
else if (!sat && v != it->var() && m[v] == l_undef) {
// clause can be satisfied by assigning v.
m[v] = sign ? l_false : l_true;
sat = true;
}
}
DEBUG_CODE({
// all clauses must be satisfied
bool sat = false;
it2 = it->m_clauses.begin();
for (; it2 != end2; ++it2) {
literal l = *it2;
if (l == null_literal) {
SASSERT(sat);
sat = false;
continue;
}
if (sat)
continue;
if (value_at(l, m) == l_true)
sat = true;
}
});
}
}
/**
\brief Test if after applying the model converter, all eliminated clauses are
satisfied by m.
*/
bool model_converter::check_model(model const & m) const {
bool ok = true;
vector<entry>::const_iterator begin = m_entries.begin();
vector<entry>::const_iterator it = m_entries.end();
while (it != begin) {
--it;
bool sat = false;
literal_vector::const_iterator it2 = it->m_clauses.begin();
literal_vector::const_iterator itbegin = it2;
literal_vector::const_iterator end2 = it->m_clauses.end();
for (; it2 != end2; ++it2) {
literal l = *it2;
if (l == null_literal) {
// end of clause
if (!sat) {
TRACE("sat_model_bug", tout << "failed eliminated: " << mk_lits_pp(static_cast<unsigned>(it2 - itbegin), itbegin) << "\n";);
ok = false;
}
sat = false;
itbegin = it2;
itbegin++;
continue;
}
if (sat)
continue;
if (value_at(l, m) == l_true)
sat = true;
}
}
return ok;
}
model_converter::entry & model_converter::mk(kind k, bool_var v) {
m_entries.push_back(entry(k, v));
entry & e = m_entries.back();
SASSERT(e.var() == v);
SASSERT(e.get_kind() == k);
return e;
}
void model_converter::insert(entry & e, clause const & c) {
SASSERT(c.contains(e.var()));
SASSERT(m_entries.begin() <= &e);
SASSERT(&e < m_entries.end());
unsigned sz = c.size();
for (unsigned i = 0; i < sz; i++) {
e.m_clauses.push_back(c[i]);
}
e.m_clauses.push_back(null_literal);
TRACE("sat_mc_bug", tout << "adding: " << c << "\n";);
}
void model_converter::insert(entry & e, literal l1, literal l2) {
SASSERT(l1.var() == e.var() || l2.var() == e.var());
SASSERT(m_entries.begin() <= &e);
SASSERT(&e < m_entries.end());
e.m_clauses.push_back(l1);
e.m_clauses.push_back(l2);
e.m_clauses.push_back(null_literal);
TRACE("sat_mc_bug", tout << "adding (binary): " << l1 << " " << l2 << "\n";);
}
void model_converter::insert(entry & e, clause_wrapper const & c) {
SASSERT(c.contains(e.var()));
SASSERT(m_entries.begin() <= &e);
SASSERT(&e < m_entries.end());
unsigned sz = c.size();
for (unsigned i = 0; i < sz; i++)
e.m_clauses.push_back(c[i]);
e.m_clauses.push_back(null_literal);
TRACE("sat_mc_bug", tout << "adding (wrapper): "; for (unsigned i = 0; i < c.size(); i++) tout << c[i] << " "; tout << "\n";);
}
bool model_converter::check_invariant(unsigned num_vars) const {
// After a variable v occurs in an entry n and the entry has kind ELIM_VAR,
// then the variable must not occur in any other entry occurring after it.
vector<entry>::const_iterator it = m_entries.begin();
vector<entry>::const_iterator end = m_entries.end();
for (; it != end; ++it) {
SASSERT(it->var() < num_vars);
if (it->get_kind() == ELIM_VAR) {
svector<entry>::const_iterator it2 = it;
it2++;
for (; it2 != end; ++it2) {
SASSERT(it2->var() != it->var());
literal_vector::const_iterator it3 = it2->m_clauses.begin();
literal_vector::const_iterator end3 = it2->m_clauses.end();
for (; it3 != end3; ++it3) {
CTRACE("sat_model_converter", it3->var() == it->var(), tout << "var: " << it->var() << "\n"; display(tout););
SASSERT(it3->var() != it->var());
SASSERT(*it3 == null_literal || it3->var() < num_vars);
}
}
}
}
return true;
}
void model_converter::display(std::ostream & out) const {
out << "(sat::model-converter";
vector<entry>::const_iterator it = m_entries.begin();
vector<entry>::const_iterator end = m_entries.end();
for (; it != end; ++it) {
out << "\n (" << (it->get_kind() == ELIM_VAR ? "elim" : "blocked") << " " << it->var();
bool start = true;
literal_vector::const_iterator it2 = it->m_clauses.begin();
literal_vector::const_iterator end2 = it->m_clauses.end();
for (; it2 != end2; ++it2) {
if (start) {
out << "\n (";
start = false;
}
else {
if (*it2 != null_literal)
out << " ";
}
if (*it2 == null_literal) {
out << ")";
start = true;
continue;
}
out << *it2;
}
out << ")";
}
out << ")\n";
}
void model_converter::copy(model_converter const & src) {
vector<entry>::const_iterator it = src.m_entries.begin();
vector<entry>::const_iterator end = src.m_entries.end();
for (; it != end; ++it)
m_entries.push_back(*it);
}
void model_converter::collect_vars(bool_var_set & s) const {
vector<entry>::const_iterator it = m_entries.begin();
vector<entry>::const_iterator end = m_entries.end();
for (; it != end; ++it) {
s.insert(it->m_var);
}
}
};