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

171 lines
5.5 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
spc_asserted_literals.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-02-14.
Revision History:
--*/
#include"spc_asserted_literals.h"
#include"ast_pp.h"
namespace spc {
asserted_literals::asserted_literals(ast_manager & m):
m_manager(m),
m_subst(m),
m_tmp_eq1(2),
m_tmp_eq2(2) {
for (unsigned i = 0; i < 2; i++) {
m_st[i] = alloc(substitution_tree, m_manager);
m_expr2clause[i] = alloc(expr2clause);
}
m_subst.reserve_offsets(3);
}
asserted_literals::~asserted_literals() {
for (unsigned i = 0; i < 2; i++) {
dealloc(m_st[i]);
dealloc(m_expr2clause[i]);
}
}
void asserted_literals::insert(clause * cls) {
if (cls->get_num_literals() == 1) {
TRACE("asserted_literals", tout << "inserting clause into asserted_literals index:\n";
cls->display(tout, m_manager); tout << "\n";);
literal const & l = cls->get_literal(0);
unsigned neg = static_cast<unsigned>(l.sign());
expr * atom = l.atom();
m_st[neg]->insert(to_app(atom));
m_expr2clause[neg]->insert(atom, cls);
m_subst.reserve_vars(m_st[neg]->get_approx_num_regs());
}
}
void asserted_literals::erase(clause * cls) {
if (cls->get_num_literals() == 1) {
literal const & l = cls->get_literal(0);
unsigned neg = static_cast<unsigned>(l.sign());
expr * atom = l.atom();
m_expr2clause[neg]->erase(atom);
m_st[neg]->erase(to_app(atom));
}
}
void asserted_literals::reset() {
for (unsigned i = 0; i < 2; i++) {
m_st[i]->reset();
m_expr2clause[i]->reset();
}
}
struct asserted_literals_visitor : public st_visitor {
expr * m_target;
asserted_literals_visitor(substitution & s):st_visitor(s), m_target(0) {}
virtual bool operator()(expr * e) {
m_target = e;
return false; // stop
}
};
/**
\brief Return an unit clause that is a generalization
of the given literal.
Return 0 if such clause does not exist.
*/
clause * asserted_literals::gen(expr * atom, bool n) {
if (is_app(atom)) {
TRACE("asserted_literals", tout << "checking if there is generalizer for: " << n << "\n" <<
mk_pp(atom, m_manager) << "\n";);
unsigned neg = static_cast<unsigned>(n);
m_subst.reset_subst();
asserted_literals_visitor visitor(m_subst);
TRACE("asserted_literals_bug", tout << "query: " << mk_pp(atom, m_manager) << "\n"; m_st[neg]->display(tout);
m_subst.display(tout););
m_st[neg]->gen(to_app(atom), visitor);
if (visitor.m_target != 0) {
clause * cls = 0;
m_expr2clause[neg]->find(visitor.m_target, cls);
SASSERT(cls);
return cls;
}
if (m_manager.is_eq(atom)) {
m_subst.reset();
m_tmp_eq1.copy_swapping_args(to_app(atom));
m_st[neg]->gen(m_tmp_eq1.get_app(), visitor);
if (visitor.m_target != 0) {
clause * cls = 0;
m_expr2clause[neg]->find(visitor.m_target, cls);
SASSERT(cls);
return cls;
}
}
}
return 0;
}
/**
\brief Return an unit clause that is a generalization
of the equality (= lhs rhs)
Return 0 if such clause does not exist.
*/
clause * asserted_literals::gen_eq(expr * lhs, expr * rhs) {
expr * args[2] = { lhs, rhs };
func_decl_ref eq_decl(m_manager.mk_func_decl(m_manager.get_basic_family_id(), OP_EQ, 0, 0, 2, args), m_manager);
m_tmp_eq2.set_decl(eq_decl);
m_tmp_eq2.set_arg(0, lhs);
m_tmp_eq2.set_arg(1, rhs);
return gen(m_tmp_eq2.get_app(), false);
}
/**
\brief Return a unit equality clause (= s t) that (eq) subsumes (= lhs rhs).
That is, lhs and rhs have the form u[s'] and u[t'] and there is
a substitution sigma s.t. sigma(s) = s' and sigma(t) = t'.
Return 0 if such clause does not exist.
*/
clause * asserted_literals::subsumes(expr * lhs, expr * rhs) {
while (true) {
TRACE("eq_subsumption", tout << "eq_subsumption loop:\n" << mk_pp(lhs, m_manager) << "\n" <<
mk_pp(rhs, m_manager) << "\n";);
clause * subsumer = gen_eq(lhs, rhs);
if (subsumer)
return subsumer;
if (!is_app(lhs) || !is_app(rhs) ||
to_app(lhs)->get_decl() != to_app(rhs)->get_decl() ||
to_app(lhs)->get_num_args() != to_app(rhs)->get_num_args())
return 0;
expr * d1 = 0;
expr * d2 = 0;
unsigned num_args = to_app(lhs)->get_num_args();
for (unsigned i = 0; i < num_args; i++) {
expr * c1 = to_app(lhs)->get_arg(i);
expr * c2 = to_app(rhs)->get_arg(i);
if (c1 != c2) {
if (d1)
return 0;
d1 = c1;
d2 = c2;
}
}
SASSERT(d1);
lhs = d1;
rhs = d2;
}
return 0;
}
};