mirror of
https://github.com/Z3Prover/z3
synced 2025-05-10 01:05: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
180
lib/qe_bool_plugin.cpp
Normal file
180
lib/qe_bool_plugin.cpp
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*++
|
||||
Copyright (c) 2010 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
qe_bool_plugin.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Eliminate Boolean variable from formula
|
||||
|
||||
Author:
|
||||
|
||||
Nikolaj Bjorner (nbjorner) 2010-02-19
|
||||
|
||||
Revision History:
|
||||
|
||||
Notes:
|
||||
|
||||
The procedure is a bit naive.
|
||||
Consider a co-factoring approach that eliminates all Boolean
|
||||
variables in scope in one shot, similar to what we do with
|
||||
BDDs.
|
||||
|
||||
--*/
|
||||
|
||||
#include "qe.h"
|
||||
#include "expr_replacer.h"
|
||||
#include "ast_pp.h"
|
||||
#include "model_evaluator.h"
|
||||
|
||||
|
||||
namespace qe {
|
||||
class bool_plugin : public qe_solver_plugin {
|
||||
scoped_ptr<expr_replacer> m_replace;
|
||||
public:
|
||||
bool_plugin(i_solver_context& ctx, ast_manager& m):
|
||||
qe_solver_plugin(m, m.get_basic_family_id(), ctx),
|
||||
m_replace(mk_default_expr_replacer(m))
|
||||
{}
|
||||
|
||||
virtual void assign(contains_app& x, expr* fml, rational const& vl) {
|
||||
SASSERT(vl.is_zero() || vl.is_one());
|
||||
}
|
||||
|
||||
virtual bool get_num_branches(contains_app& x, expr* fml, rational& nb) {
|
||||
nb = rational(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void subst(contains_app& x, rational const& vl, expr_ref& fml, expr_ref* def) {
|
||||
SASSERT(vl.is_one() || vl.is_zero());
|
||||
expr* tf = (vl.is_one())?m.mk_true():m.mk_false();
|
||||
m_replace->apply_substitution(x.x(), tf, 0, fml);
|
||||
if (def) {
|
||||
*def = tf;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool project(contains_app& x, model_ref& model, expr_ref& fml) {
|
||||
model_evaluator model_eval(*model);
|
||||
expr_ref val_x(m);
|
||||
rational val;
|
||||
model_eval(x.x(), val_x);
|
||||
CTRACE("qe", (!m.is_true(val_x) && !m.is_false(val_x)),
|
||||
tout << "Boolean is a don't care: " << mk_pp(x.x(), m) << "\n";);
|
||||
val = m.is_true(val_x)?rational::one():rational::zero();
|
||||
subst(x, val, fml, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual unsigned get_weight(contains_app& contains_x, expr* fml) {
|
||||
app* x = contains_x.x();
|
||||
bool p = m_ctx.pos_atoms().contains(x);
|
||||
bool n = m_ctx.neg_atoms().contains(x);
|
||||
if (p && n) {
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual bool solve(conj_enum& conjs,expr* fml) {
|
||||
return
|
||||
solve_units(conjs, fml) ||
|
||||
solve_polarized(fml);
|
||||
}
|
||||
|
||||
virtual bool is_uninterpreted(app* a) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool solve_units(conj_enum& conjs, expr* _fml) {
|
||||
expr_ref fml(_fml, m);
|
||||
conj_enum::iterator it = conjs.begin(), end = conjs.end();
|
||||
unsigned idx;
|
||||
for (; it != end; ++it) {
|
||||
expr* e = *it;
|
||||
if (!is_app(e)) {
|
||||
continue;
|
||||
}
|
||||
app* a = to_app(e);
|
||||
expr* e1;
|
||||
if (m_ctx.is_var(a, idx)) {
|
||||
m_replace->apply_substitution(a, m.mk_true(), 0, fml);
|
||||
m_ctx.elim_var(idx, fml, m.mk_true());
|
||||
return true;
|
||||
}
|
||||
else if (m.is_not(e, e1) && m_ctx.is_var(e1, idx)) {
|
||||
m_replace->apply_substitution(to_app(e1), m.mk_false(), 0, fml);
|
||||
m_ctx.elim_var(idx, fml, m.mk_false());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool solve_polarized(expr* _fml) {
|
||||
unsigned num_vars = m_ctx.get_num_vars();
|
||||
expr_ref fml(_fml, m), def(m);
|
||||
for (unsigned i = 0; i < num_vars; ++i) {
|
||||
if (m.is_bool(m_ctx.get_var(i)) &&
|
||||
solve_polarized(m_ctx.contains(i), fml, def)) {
|
||||
m_ctx.elim_var(i, fml, def);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool solve_polarized( contains_app& contains_x, expr_ref& fml, expr_ref& def) {
|
||||
app* x = contains_x.x();
|
||||
bool p = m_ctx.pos_atoms().contains(x);
|
||||
bool n = m_ctx.neg_atoms().contains(x);
|
||||
TRACE("quant_elim", tout << mk_pp(x, m) << " " << mk_pp(fml, m) << "\n";);
|
||||
if (p && n) {
|
||||
return false;
|
||||
}
|
||||
else if (p && !n) {
|
||||
atom_set::iterator it = m_ctx.pos_atoms().begin(), end = m_ctx.pos_atoms().end();
|
||||
for (; it != end; ++it) {
|
||||
if (x != *it && contains_x(*it)) return false;
|
||||
}
|
||||
it = m_ctx.neg_atoms().begin(), end = m_ctx.neg_atoms().end();
|
||||
for (; it != end; ++it) {
|
||||
if (contains_x(*it)) return false;
|
||||
}
|
||||
// only occurrences of 'x' must be in positive atoms
|
||||
def = m.mk_true();
|
||||
m_replace->apply_substitution(x, def, 0, fml);
|
||||
return true;
|
||||
}
|
||||
else if (!p && n) {
|
||||
atom_set::iterator it = m_ctx.pos_atoms().begin(), end = m_ctx.pos_atoms().end();
|
||||
for (; it != end; ++it) {
|
||||
if (contains_x(*it)) return false;
|
||||
}
|
||||
it = m_ctx.neg_atoms().begin(), end = m_ctx.neg_atoms().end();
|
||||
for (; it != end; ++it) {
|
||||
if (x != *it && contains_x(*it)) return false;
|
||||
}
|
||||
def = m.mk_false();
|
||||
m_replace->apply_substitution(x, def, 0, fml);
|
||||
return true;
|
||||
}
|
||||
else if (contains_x(fml)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
def = m.mk_false();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
qe_solver_plugin* mk_bool_plugin(i_solver_context& ctx) {
|
||||
return alloc(bool_plugin, ctx, ctx.get_manager());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue