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

151 lines
5 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
split_clause_tactic.cpp
Abstract:
Tactic that creates a subgoal for each literal in a clause (l_1 or ... or l_n).
The tactic fails if the main goal does not contain any clause.
Author:
Leonardo (leonardo) 2011-11-21
Notes:
--*/
#include"tactical.h"
#include"split_clause_tactic.h"
class split_clause_tactic : public tactic {
bool m_largest_clause;
unsigned select_clause(ast_manager & m, goal_ref const & in) {
unsigned result_idx = UINT_MAX;
unsigned len = 0;
unsigned sz = in->size();
for (unsigned i = 0; i < sz; i++) {
expr * f = in->form(i);
if (m.is_or(f)) {
unsigned curr_len = to_app(f)->get_num_args();
if (curr_len >= 2) {
// consider only non unit clauses
if (!m_largest_clause)
return i;
if (curr_len > len) {
result_idx = i;
len = curr_len;
}
}
}
}
return result_idx;
}
class split_pc : public proof_converter {
ast_manager & m_manager;
app * m_clause;
proof * m_clause_pr;
public:
split_pc(ast_manager & m, app * cls, proof * pr):m_manager(m), m_clause(cls), m_clause_pr(pr) {
m.inc_ref(cls);
m.inc_ref(pr);
}
~split_pc() {
m_manager.dec_ref(m_clause);
m_manager.dec_ref(m_clause_pr);
}
virtual void operator()(ast_manager & m, unsigned num_source, proof * const * source, proof_ref & result) {
// Let m_clause be of the form (l_0 or ... or l_{num_source - 1})
// Each source[i] proof is a proof for "false" using l_i as a hypothesis
// So, I use lemma for producing a proof for (not l_i) that does not contain the hypothesis,
// and unit_resolution for building a proof for the goal.
SASSERT(num_source == m_clause->get_num_args());
proof_ref_buffer prs(m);
prs.push_back(m_clause_pr);
for (unsigned i = 0; i < num_source; i++) {
proof * pr_i = source[i];
expr * not_li = m.mk_not(m_clause->get_arg(i));
prs.push_back(m.mk_lemma(pr_i, not_li));
}
result = m.mk_unit_resolution(prs.size(), prs.c_ptr());
}
virtual proof_converter * translate(ast_translation & translator) {
return alloc(split_pc, translator.to(), translator(m_clause), translator(m_clause_pr));
}
};
public:
split_clause_tactic(params_ref const & ref = params_ref()) {
updt_params(ref);
}
virtual tactic * translate(ast_manager & m) {
split_clause_tactic * t = alloc(split_clause_tactic);
t->m_largest_clause = m_largest_clause;
return t;
}
virtual ~split_clause_tactic() {
}
virtual void updt_params(params_ref const & p) {
m_largest_clause = p.get_bool(":split-largest-clause", false);
}
virtual void collect_param_descrs(param_descrs & r) {
r.insert(":split-largest-clause", CPK_BOOL, "(default: false) split the largest clause in the goal.");
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
SASSERT(in->is_well_sorted());
tactic_report report("split-clause", *in);
TRACE("before_split_clause", in->display(tout););
pc = 0; mc = 0; core = 0;
ast_manager & m = in->m();
unsigned cls_pos = select_clause(m, in);
if (cls_pos == UINT_MAX) {
throw tactic_exception("split-clause tactic failed, goal does not contain any clause");
}
bool produce_proofs = in->proofs_enabled();
app * cls = to_app(in->form(cls_pos));
expr_dependency * cls_dep = in->dep(cls_pos);
if (produce_proofs)
pc = alloc(split_pc, m, cls, in->pr(cls_pos));
unsigned cls_sz = cls->get_num_args();
report_tactic_progress(":num-new-branches", cls_sz);
for (unsigned i = 0; i < cls_sz; i++) {
goal * subgoal_i;
if (i == cls_sz - 1)
subgoal_i = in.get();
else
subgoal_i = alloc(goal, *in);
expr * lit_i = cls->get_arg(i);
proof * pr_i = 0;
if (produce_proofs)
pr_i = m.mk_hypothesis(lit_i);
subgoal_i->update(cls_pos, lit_i, pr_i, cls_dep);
subgoal_i->inc_depth();
result.push_back(subgoal_i);
}
}
virtual void cleanup() {
// do nothing this tactic is too simple
}
};
tactic * mk_split_clause_tactic(params_ref const & p) {
return clean(alloc(split_clause_tactic, p));
}