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

235 lines
7.8 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
spc_semantic_tautology.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-02-11.
Revision History:
--*/
#include"spc_semantic_tautology.h"
#include"ast_pp.h"
namespace spc {
expr * find(expr2expr & f, expr * n) {
#ifdef _TRACE
expr * _n = n;
#endif
ptr_buffer<expr> path;
expr * next;
while (f.find(n, next)) {
path.push_back(n);
n = next;
}
ptr_buffer<expr>::iterator it = path.begin();
ptr_buffer<expr>::iterator end = path.end();
for (; it != end; ++it) {
expr * prev = *it;
f.insert(prev, n);
}
SASSERT(n);
TRACE("semantic_tautology_detail", tout << "find(#" << _n->get_id() << ") = #" << n->get_id() << "\n";);
return n;
}
semantic_tautology::semantic_tautology(ast_manager & m):
m_manager(m),
m_cg_table(DEFAULT_HASHTABLE_INITIAL_CAPACITY, cg_hash(m_manager, m_find), cg_eq(m_find)) {
}
unsigned semantic_tautology::cg_hash::operator()(app * n) const {
TRACE("semantic_tautology_detail", tout << "hash code of:\n" << mk_pp(n, m_manager) << "\n";);
unsigned r = get_composite_hash<app *, k_hash, c_hash>(n, n->get_num_args(), m_k_hash, m_c_hash);
TRACE("semantic_tautology_detail", tout << "result: " << r << "\n";);
return r;
}
bool semantic_tautology::cg_eq::operator()(app * n1, app * n2) const {
if (n1->get_decl() != n2->get_decl() || n1->get_num_args() != n2->get_num_args())
return false;
unsigned num_args = n1->get_num_args();
for (unsigned i = 0; i < num_args; i++)
if (spc::find(m_find, n1->get_arg(i)) != spc::find(m_find, n2->get_arg(i)))
return false;
return true;
}
bool semantic_tautology::is_target(unsigned num_lits, literal * lits) {
bool has_diseq = false;
bool has_non_diseq = false;
for (unsigned i = 0; i < num_lits; i++) {
literal const & l = lits[i];
if (l.sign() && m_manager.is_eq(l.atom()))
has_diseq = true;
else
has_non_diseq = true;
}
return has_diseq && has_non_diseq;
}
void semantic_tautology::reset() {
m_region.reset();
m_init_todo.reset();
m_todo.reset();
m_already_found.reset();
m_use_list.reset();
m_find.reset();
m_size.reset();
m_cg_table.reset();
}
void semantic_tautology::update_use_list(app * parent, expr * child) {
list<app*> * use_list = 0;
m_use_list.find(child, use_list);
use_list = new (m_region) list<app*>(parent, use_list);
m_use_list.insert(child, use_list);
}
inline void semantic_tautology::push_init_core(expr * n) {
if (is_app(n) && to_app(n)->get_num_args() > 0)
m_init_todo.push_back(to_app(n));
}
inline void semantic_tautology::push_init(expr * atom) {
if (m_manager.is_eq(atom)) {
push_init_core(to_app(atom)->get_arg(0));
push_init_core(to_app(atom)->get_arg(1));
}
else
push_init_core(atom);
}
void semantic_tautology::init_use_list() {
while (!m_init_todo.empty()) {
app * n = m_init_todo.back();
m_init_todo.pop_back();
if (!m_already_found.contains(n)) {
unsigned num_args = n->get_num_args();
SASSERT(num_args > 0);
m_cg_table.insert(n);
m_already_found.insert(n);
for (unsigned i = 0; i < num_args; i++) {
expr * c = n->get_arg(i);
update_use_list(n, c);
push_init_core(c);
}
}
}
}
void semantic_tautology::init(unsigned num_lits, literal * lits) {
reset();
for (unsigned i = 0; i < num_lits; i++) {
literal const & l = lits[i];
expr * atom = l.atom();
push_init(atom);
if (l.sign() && m_manager.is_eq(atom))
m_todo.push_back(expr_pair(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1)));
}
init_use_list();
}
void semantic_tautology::remove_parents(expr * n1) {
list<app*> * use_list = 0;
m_use_list.find(n1, use_list);
while (use_list) {
TRACE("semantic_tautology", tout << "removing parent from cg_table:\n" << mk_pp(use_list->head(), m_manager) << "\n";);
m_cg_table.erase(use_list->head());
use_list = use_list->tail();
}
}
void semantic_tautology::restore_parents(expr * n1, expr * n2) {
list<app*> * use_list = 0;
m_use_list.find(n1, use_list);
while (use_list) {
app * parent = use_list->head();
app * other = 0;
if (m_cg_table.find(parent, other)) {
TRACE("semantic_tautology", tout << "new congruence:\n" << mk_pp(parent, m_manager) << "\n" << mk_pp(other, m_manager) << "\n";);
if (parent != other)
m_todo.push_back(expr_pair(parent, other));
}
else {
TRACE("semantic_tautology", tout << "restoring parent to cg_table:\n" << mk_pp(parent, m_manager) << "\n";);
m_cg_table.insert(parent);
update_use_list(parent, n2);
}
use_list = use_list->tail();
}
}
void semantic_tautology::assert_eq(expr * n1, expr * n2) {
n1 = find(n1);
n2 = find(n2);
if (n1 == n2)
return;
TRACE("semantic_tautology", tout << "processing equality:\n" << mk_pp(n1, m_manager) << " " << n1->get_id() << "\n" <<
mk_pp(n2, m_manager) << " " << n2->get_id() << "\n";);
unsigned sz1 = 1;
unsigned sz2 = 1;
m_size.find(n1, sz1);
m_size.find(n2, sz2);
if (sz1 > sz2)
std::swap(n1, n2);
remove_parents(n1);
TRACE("semantic_tautology", tout << "merging equivalence classes\n";);
m_find.insert(n1, n2);
m_size.insert(n2, sz1 + sz2);
restore_parents(n1, n2);
}
void semantic_tautology::process_eqs() {
while (!m_todo.empty()) {
expr_pair const & p = m_todo.back();
expr * lhs = p.first;
expr * rhs = p.second;
m_todo.pop_back();
assert_eq(lhs, rhs);
}
}
bool semantic_tautology::contains_complement(unsigned num_lits, literal * lits, unsigned i, bool sign, expr * atom) {
atom = find(atom);
for (unsigned j = i + 1; j < num_lits; j++) {
literal const & l = lits[j];
if (l.sign() != sign && find(l.atom()) == atom)
return true;
}
return false;
}
bool semantic_tautology::is_tautology(unsigned num_lits, literal * lits) {
for (unsigned i = 0; i < num_lits; i++) {
literal const & l = lits[i];
expr * atom = l.atom();
if (!l.sign() && m_manager.is_eq(atom) && find(to_app(atom)->get_arg(0)) == find(to_app(atom)->get_arg(1)))
return true;
if (!m_manager.is_eq(atom) && contains_complement(num_lits, lits, i, l.sign(), atom))
return true;
}
return false;
}
bool semantic_tautology::operator()(unsigned num_lits, literal * lits) {
if (!is_target(num_lits, lits))
return false;
init(num_lits, lits);
process_eqs();
bool r = is_tautology(num_lits, lits);
TRACE("semantic_tautology", display(tout, num_lits, lits, m_manager); tout << "\nis semantic tautology: " << r << "\n";);
return r;
}
};