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

219 lines
6.3 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
smt_formula_compiler.cpp
Abstract:
Auxiliary class for smt::solver
Convert Exprs into Internal data-structures.
Author:
Leonardo de Moura (leonardo) 2011-06-25.
Revision History:
This was an experiment to rewrite Z3 kernel.
It will be deleted after we finish revamping Z3 kernel.
--*/
#include"smt_formula_compiler.h"
#include"smt_solver_exp.h"
#include"assertion_set_util.h"
#include"assertion_set2sat.h"
#include"for_each_expr.h"
namespace smt {
formula_compiler::formula_compiler(solver_exp & _s, params_ref const & p):
s(_s),
m_a_util(s.m),
m_normalizer(s.m),
m_elim_ite(s.m) {
updt_params(p);
params_ref s_p;
s_p.set_bool(":elim-and", true);
s_p.set_bool(":blast-distinct", true);
s_p.set_bool(":eq2ineq", true);
s_p.set_bool(":arith-lhs", true);
s_p.set_bool(":gcd-rounding", true);
s_p.set_bool(":sort-sums", true);
s_p.set_bool(":som", true);
m_normalizer.updt_params(s_p);
}
formula_compiler::~formula_compiler() {
}
// mark theory axioms: literals that do not occur in the boolean structure
void formula_compiler::mark_axioms(assertion_set const & s, expr_fast_mark2 & axioms) {
ast_manager & m = s.m();
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = s.form(i);
while (m.is_not(f, f));
if (!is_app(f) || to_app(f)->get_family_id() != m.get_basic_family_id()) {
axioms.mark(f);
continue;
}
SASSERT(is_app(f));
SASSERT(to_app(f)->get_family_id() == m.get_basic_family_id());
switch (to_app(f)->get_decl_kind()) {
case OP_OR:
case OP_IFF:
break;
case OP_ITE:
SASSERT(m.is_bool(to_app(f)->get_arg(1)));
break;
case OP_EQ:
if (!m.is_bool(to_app(f)->get_arg(1)))
axioms.mark(f);
break;
case OP_AND:
case OP_XOR:
case OP_IMPLIES:
case OP_DISTINCT:
UNREACHABLE();
break;
default:
break;
}
}
}
struct unmark_axioms_proc {
expr_fast_mark2 & m_axioms;
unmark_axioms_proc(expr_fast_mark2 & axioms):m_axioms(axioms) {}
void operator()(quantifier *) {}
void operator()(var *) {}
void operator()(app * t) {
m_axioms.reset_mark(t);
}
};
/**
\brief Unmark atoms that occur in the boolean structure.
*/
void formula_compiler::unmark_nested_atoms(assertion_set const & s, expr_fast_mark2 & axioms) {
ast_manager & m = s.m();
expr_fast_mark1 visited;
unmark_axioms_proc proc(axioms);
unsigned sz = s.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = s.form(i);
while (m.is_not(f, f));
if (axioms.is_marked(f))
continue;
quick_for_each_expr(proc, visited, f);
}
}
void formula_compiler::assert_axiom(expr * f, bool neg) {
if (is_app(f)) {
if (to_app(f)->get_family_id() == m_a_util.get_family_id())
s.m_arith.assert_axiom(f, neg);
}
}
void formula_compiler::register_atom(expr * f, sat::bool_var p) {
if (is_app(f)) {
if (to_app(f)->get_family_id() == m_a_util.get_family_id())
s.m_arith.mk_atom(f, p);
}
}
void formula_compiler::compile_formulas(assertion_set const & assertions) {
ast_manager & m = assertions.m();
expr_fast_mark2 axioms;
mark_axioms(assertions, axioms);
unmark_nested_atoms(assertions, axioms);
ptr_vector<expr> formulas;
// send axioms to theories, and save formulas to compile
unsigned sz = assertions.size();
for (unsigned i = 0; i < sz; i++) {
expr * f = assertions.form(i);
bool neg = false;
while (m.is_not(f, f))
neg = !neg;
if (axioms.is_marked(f)) {
assert_axiom(f, neg);
}
else {
formulas.push_back(f);
}
}
// compile formulas into sat::solver
m_to_sat(m, formulas.size(), formulas.c_ptr(), s.m_params, *(s.m_sat), s.m_atom2bvar);
// register atoms nested in the boolean structure in the theories
atom2bool_var::recent_iterator it = s.m_atom2bvar.begin_recent();
atom2bool_var::recent_iterator end = s.m_atom2bvar.end_recent();
for (; it != end; ++it) {
expr * atom = *it;
register_atom(atom, s.m_atom2bvar.to_bool_var(atom));
}
s.m_atom2bvar.reset_recent();
}
void formula_compiler::normalize() {
// make sure that the assertions are in the right format.
m_normalizer(s.m_assertions);
m_normalizer.cleanup();
}
void formula_compiler::elim_term_ite() {
if (has_term_ite(s.m_assertions)) {
model_converter_ref mc;
m_elim_ite(s.m_assertions, mc);
s.m_mc = concat(s.m_mc.get(), mc.get());
m_elim_ite.cleanup();
}
}
void formula_compiler::operator()() {
if (s.m_assertions.inconsistent())
return;
// normalization
elim_term_ite();
normalize();
TRACE("before_formula_compiler", s.m_assertions.display(tout););
s.init();
compile_formulas(s.m_assertions);
s.m_arith.preprocess();
TRACE("after_formula_compiler", s.display_state(tout););
}
void formula_compiler::updt_params(params_ref const & p) {
// TODO
}
void formula_compiler::collect_param_descrs(param_descrs & d) {
// TODO
}
void formula_compiler::collect_statistics(statistics & st) {
// TODO
}
void formula_compiler::reset_statistics() {
// TODO
}
void formula_compiler::set_cancel(bool f) {
m_normalizer.set_cancel(f);
m_elim_ite.set_cancel(f);
m_to_sat.set_cancel(f);
}
};