mirror of
https://github.com/Z3Prover/z3
synced 2025-05-09 00:35:47 +00:00
Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
3f9edad676
commit
e9eab22e5c
1186 changed files with 381859 additions and 0 deletions
269
lib/spc_rewriter.cpp
Normal file
269
lib/spc_rewriter.cpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
spc_rewrite.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-02-12.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"spc_rewriter.h"
|
||||
#include"spc_decl_plugin.h"
|
||||
#include"ast_pp.h"
|
||||
|
||||
namespace spc {
|
||||
|
||||
rewriter::rewriter(ast_manager & m, simplifier & simp, order & ord, asserted_literals & al):
|
||||
simplifier(m),
|
||||
m_asserted_literals(al),
|
||||
m_order(ord),
|
||||
m_spc_fid(m.get_family_id("spc")),
|
||||
m_subst(m),
|
||||
m_st(m),
|
||||
m_visitor(m_order, m_subst, m_cls_use_list) {
|
||||
|
||||
reserve_offsets(3);
|
||||
|
||||
borrow_plugins(simp);
|
||||
}
|
||||
|
||||
rewriter::~rewriter() {
|
||||
release_plugins();
|
||||
}
|
||||
|
||||
inline void rewriter::reserve_vars(unsigned num_vars) {
|
||||
m_subst.reserve_vars(num_vars);
|
||||
m_order.reserve_vars(num_vars);
|
||||
m_asserted_literals.reserve_vars(num_vars);
|
||||
}
|
||||
|
||||
void rewriter::reserve_offsets(unsigned num_offsets) {
|
||||
m_subst.reserve_offsets(num_offsets);
|
||||
m_order.reserve_offsets(num_offsets);
|
||||
}
|
||||
|
||||
inline bool rewriter::demodulator(clause * cls) const {
|
||||
if (cls->get_num_literals() != 1)
|
||||
return false;
|
||||
literal const & l = cls->get_literal(0);
|
||||
return !l.sign() && m_manager.is_eq(l.atom());
|
||||
}
|
||||
|
||||
inline void rewriter::insert(clause * cls, expr * source) {
|
||||
if (!is_var(source)) {
|
||||
TRACE("rewriter_detail", tout << "inserting into rewriter index:\n"; cls->display(tout, m_manager); tout << "\n";);
|
||||
flush_cache();
|
||||
m_st.insert(to_app(source));
|
||||
m_cls_use_list.insert(cls, source);
|
||||
}
|
||||
}
|
||||
|
||||
void rewriter::insert(clause * cls) {
|
||||
if (demodulator(cls)) {
|
||||
reserve_vars(cls->get_num_vars());
|
||||
literal const & l = cls->get_literal(0);
|
||||
app * eq = to_app(l.atom());
|
||||
if (l.is_oriented()) {
|
||||
expr * source = l.is_left() ? eq->get_arg(0) : eq->get_arg(1);
|
||||
insert(cls, source);
|
||||
}
|
||||
else {
|
||||
insert(cls, eq->get_arg(0));
|
||||
insert(cls, eq->get_arg(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void rewriter::erase(clause * cls, expr * source) {
|
||||
if (!is_var(source)) {
|
||||
flush_cache();
|
||||
m_cls_use_list.erase(cls, source);
|
||||
if (m_cls_use_list.empty(source))
|
||||
m_st.erase(to_app(source));
|
||||
}
|
||||
}
|
||||
|
||||
void rewriter::erase(clause * cls) {
|
||||
if (demodulator(cls)) {
|
||||
literal const & l = cls->get_literal(0);
|
||||
app * eq = to_app(l.atom());
|
||||
if (l.is_oriented()) {
|
||||
expr * source = l.is_left() ? eq->get_arg(0) : eq->get_arg(1);
|
||||
erase(cls, source);
|
||||
}
|
||||
else {
|
||||
erase(cls, eq->get_arg(0));
|
||||
erase(cls, eq->get_arg(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool rewriter::visitor::operator()(expr * e) {
|
||||
if (m_cls_use_list.empty(e))
|
||||
return true; // continue;
|
||||
clause_use_list::iterator it = m_cls_use_list.begin(e);
|
||||
clause_use_list::iterator end = m_cls_use_list.end(e);
|
||||
for (; it != end; ++it) {
|
||||
m_clause = *it;
|
||||
SASSERT(m_clause->get_num_literals() == 1);
|
||||
literal & l = m_clause->get_literal(0);
|
||||
expr * atom = l.atom();
|
||||
SASSERT(!l.sign() && m_manager.is_eq(atom));
|
||||
SASSERT(to_app(atom)->get_arg(0) == e || to_app(atom)->get_arg(1) == e);
|
||||
m_source = to_app(atom)->get_arg(0);
|
||||
m_target = to_app(atom)->get_arg(1);
|
||||
if (m_source != e)
|
||||
std::swap(m_source, m_target);
|
||||
SASSERT(m_source == e);
|
||||
TRACE("rewriter", tout << "found generalization:\n" << mk_pp(m_source, m_manager) << "\n" <<
|
||||
mk_pp(m_target, m_manager) << "\nsubstitution\n";
|
||||
m_subst.display(tout); tout << "m_subst: " << &m_subst << "\n";
|
||||
tout << "checking ordering constraints...\n";);
|
||||
if (l.is_oriented() || m_order.greater(expr_offset(m_source, 1), expr_offset(m_target, 1), &m_subst)) {
|
||||
m_found = true;
|
||||
return false; // stop
|
||||
}
|
||||
TRACE("rewriter", tout << "failed ordering constraints...\n";);
|
||||
}
|
||||
return true; // continue
|
||||
}
|
||||
|
||||
void rewriter::save_justification(justification * j) {
|
||||
if (std::find(m_justifications.begin(), m_justifications.end(), j) == m_justifications.end())
|
||||
m_justifications.push_back(j);
|
||||
}
|
||||
|
||||
proof * rewriter::mk_demodulation_proof(expr * old_expr, expr * new_expr, proof * parent) {
|
||||
if (m_manager.fine_grain_proofs()) {
|
||||
SASSERT(parent);
|
||||
return m_manager.mk_app(m_spc_fid, PR_DEMODULATION, parent, m_manager.mk_eq(old_expr, new_expr));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rewriter::reset() {
|
||||
m_st.reset();
|
||||
m_cls_use_list.reset();
|
||||
}
|
||||
|
||||
void rewriter::reduce_literal(literal const & l, literal & l_r, proof * & l_pr) {
|
||||
if (m_st.empty()) {
|
||||
l_r = l;
|
||||
l_pr = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
expr * atom = l.atom();
|
||||
expr * r;
|
||||
proof * r_pr;
|
||||
m_proofs.reset();
|
||||
while (true) {
|
||||
reduce_core(atom);
|
||||
get_cached(atom, r, r_pr);
|
||||
if (m_manager.fine_grain_proofs() && r_pr)
|
||||
m_proofs.push_back(r_pr);
|
||||
if (atom == r)
|
||||
break;
|
||||
atom = r;
|
||||
}
|
||||
l_r = literal(atom, l.sign());
|
||||
if (m_manager.fine_grain_proofs())
|
||||
l_pr = m_proofs.empty() ? 0 : m_manager.mk_transitivity(m_proofs.size(), m_proofs.c_ptr());
|
||||
}
|
||||
|
||||
clause * rewriter::operator()(clause * cls) {
|
||||
reserve_vars(cls->get_num_vars());
|
||||
SASSERT(m_found_literals.empty());
|
||||
m_justifications.reset();
|
||||
m_max_scope_lvl = cls->get_scope_lvl();
|
||||
|
||||
literal_buffer new_literals(m_manager);
|
||||
proof_ref_buffer new_proofs(m_manager);
|
||||
bool changed = false;
|
||||
|
||||
unsigned num_lits = cls->get_num_literals();
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
literal & l = cls->get_literal(i);
|
||||
literal l_r;
|
||||
proof * l_pr = 0;
|
||||
reduce_literal(l, l_r, l_pr);
|
||||
|
||||
if (l != l_r) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (!l_r.is_false(m_manager) && !m_found_literals.contains(l_r)) {
|
||||
m_found_literals.insert(l_r);
|
||||
|
||||
// apply simplify reflect rules
|
||||
expr * atom = l_r.atom();
|
||||
clause * unit = 0;
|
||||
TRACE("rewriter", tout << "adding literal: " << mk_pp(atom, m_manager) << "\n";);
|
||||
if (l_r.sign()) {
|
||||
if (m_manager.is_eq(atom))
|
||||
unit = m_asserted_literals.subsumes(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1));
|
||||
else
|
||||
unit = m_asserted_literals.gen(atom, false);
|
||||
}
|
||||
else {
|
||||
// check if there is a generalization of the negation of the current literal.
|
||||
unit = m_asserted_literals.gen(atom, true);
|
||||
}
|
||||
|
||||
if (unit) {
|
||||
// new literal was resolved
|
||||
justification * j = unit->get_justification();
|
||||
m_justifications.push_back(j);
|
||||
changed = true;
|
||||
}
|
||||
else {
|
||||
// keep new literal
|
||||
new_literals.push_back(l_r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// removed duplicate or resolved literal.
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (m_manager.fine_grain_proofs() && l_pr != 0) {
|
||||
new_proofs.push_back(l_pr);
|
||||
}
|
||||
}
|
||||
|
||||
m_found_literals.reset();
|
||||
|
||||
if (!changed) {
|
||||
m_found_literals.reset();
|
||||
return cls;
|
||||
}
|
||||
|
||||
proof * new_pr = mk_rewrite_proof(m_manager, m_spc_fid, new_literals.size(), new_literals.c_ptr(), cls->get_justification()->get_proof(),
|
||||
new_proofs.size(), new_proofs.c_ptr());
|
||||
|
||||
justification * new_j = rewrite_justification::mk(m_manager, cls->get_justification(), m_justifications.size(), m_justifications.c_ptr(), new_pr);
|
||||
|
||||
if (m_max_scope_lvl == cls->get_scope_lvl()) {
|
||||
// peform destructive update
|
||||
cls->update_lits(m_manager, new_literals.size(), new_literals.c_ptr(), new_j);
|
||||
return cls;
|
||||
}
|
||||
else {
|
||||
SASSERT(m_max_scope_lvl > cls->get_scope_lvl());
|
||||
// create new clause
|
||||
// the old clause will be frozen
|
||||
return clause::mk(m_manager, new_literals.size(), new_literals.c_ptr(), new_j, m_max_scope_lvl);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue