mirror of
https://github.com/Z3Prover/z3
synced 2026-02-09 02:25:38 +00:00
115 lines
4.1 KiB
C++
115 lines
4.1 KiB
C++
/*++
|
|
Copyright (c) 2022 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
flatten_clauses.h
|
|
|
|
Abstract:
|
|
|
|
flatten clauses
|
|
|
|
Author:
|
|
|
|
Nikolaj Bjorner (nbjorner) 2022-11-24
|
|
|
|
--*/
|
|
|
|
#pragma once
|
|
|
|
#include "ast/simplifiers/dependent_expr_state.h"
|
|
#include "ast/rewriter/th_rewriter.h"
|
|
#include "ast/ast_util.h"
|
|
|
|
|
|
class flatten_clauses : public dependent_expr_simplifier {
|
|
|
|
unsigned m_num_flat = 0;
|
|
|
|
bool is_literal(expr* a) {
|
|
m.is_not(a, a);
|
|
if (m.is_eq(a) && !m.is_iff(a))
|
|
return true;
|
|
if (!is_app(a))
|
|
return true;
|
|
return to_app(a)->get_family_id() != m.get_basic_family_id();
|
|
}
|
|
|
|
bool is_reducible(expr* a, expr* b) {
|
|
return b->get_ref_count() == 1 || is_literal(a);
|
|
}
|
|
|
|
public:
|
|
flatten_clauses(ast_manager& m, params_ref const& p, dependent_expr_state& fmls):
|
|
dependent_expr_simplifier(m, fmls) {
|
|
}
|
|
|
|
char const* name() const override { return "flatten-clauses"; }
|
|
|
|
void reset_statistics() override { m_num_flat = 0; }
|
|
|
|
void collect_statistics(statistics& st) const override {
|
|
st.update("flatten-clauses-rewrites", m_num_flat);
|
|
}
|
|
|
|
void reduce() override {
|
|
unsigned nf = m_num_flat + 1;
|
|
while (nf != m_num_flat) {
|
|
nf = m_num_flat;
|
|
for (unsigned idx : indices()) {
|
|
auto de = m_fmls[idx];
|
|
expr* f = de.fml(), *a, *b, *c;
|
|
bool decomposed = false;
|
|
// (or a (not (or b_i)) => and_i (or a (not b_i))
|
|
if (m.is_or(f, a, b) && m.is_not(b, b) && m.is_or(b) && is_reducible(a, b))
|
|
decomposed = true;
|
|
else if (m.is_or(f, b, a) && m.is_not(b, b) && m.is_or(b) && is_reducible(a, b))
|
|
decomposed = true;
|
|
if (decomposed) {
|
|
for (expr* arg : *to_app(b))
|
|
m_fmls.add(dependent_expr(m, m.mk_or(a, mk_not(m, arg)), nullptr, de.dep()));
|
|
m_fmls.update(idx, dependent_expr(m, m.mk_true(), nullptr, nullptr));
|
|
++m_num_flat;
|
|
continue;
|
|
}
|
|
// (or a (and b_i)) => and_i (or a b_i)
|
|
if (m.is_or(f, a, b) && m.is_and(b) && is_reducible(a, b))
|
|
decomposed = true;
|
|
else if (m.is_or(f, b, a) && m.is_and(b) && is_reducible(a, b))
|
|
decomposed = true;
|
|
if (decomposed) {
|
|
for (expr * arg : *to_app(b))
|
|
m_fmls.add(dependent_expr(m, m.mk_or(a, arg), nullptr, de.dep()));
|
|
m_fmls.update(idx, dependent_expr(m, m.mk_true(), nullptr, nullptr));
|
|
++m_num_flat;
|
|
continue;
|
|
}
|
|
// not (and a (or b_i)) => and_i (not a) or (not b_i)
|
|
if (m.is_not(f, c) && m.is_and(c, a, b) && m.is_or(b) && is_reducible(a, b))
|
|
decomposed = true;
|
|
else if (m.is_not(f, c) && m.is_and(c, b, a) && m.is_or(b) && is_reducible(a, b))
|
|
decomposed = true;
|
|
if (decomposed) {
|
|
expr* na = mk_not(m, a);
|
|
for (expr* arg : *to_app(b))
|
|
m_fmls.add(dependent_expr(m, m.mk_or(na, mk_not(m, arg)), nullptr, de.dep()));
|
|
m_fmls.update(idx, dependent_expr(m, m.mk_true(), nullptr, nullptr));
|
|
++m_num_flat;
|
|
continue;
|
|
}
|
|
if (m.is_implies(f, a, b)) {
|
|
m_fmls.update(idx, dependent_expr(m, m.mk_or(mk_not(m, a), b), nullptr, de.dep()));
|
|
++m_num_flat;
|
|
continue;
|
|
}
|
|
if (m.is_ite(f, a, b, c)) {
|
|
m_fmls.add(dependent_expr(m, m.mk_or(mk_not(m, a), b), nullptr, de.dep()));
|
|
m_fmls.add(dependent_expr(m, m.mk_or(a, c), nullptr, de.dep()));
|
|
m_fmls.update(idx, dependent_expr(m, m.mk_true(), nullptr, nullptr));
|
|
++m_num_flat;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|