mirror of
https://github.com/Z3Prover/z3
synced 2025-04-11 19:53:34 +00:00
199 lines
6.6 KiB
C++
199 lines
6.6 KiB
C++
/*++
|
|
Copyright (c) 2006 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dl_mk_interp_tail_simplifier.h
|
|
|
|
Abstract:
|
|
|
|
Rule transformer which inlines some of the rules
|
|
|
|
Author:
|
|
|
|
Krystof Hoder (t-khoder) 2011-10-02.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _DL_MK_RULE_INLINER_H_
|
|
#define _DL_MK_RULE_INLINER_H_
|
|
|
|
#include "dl_context.h"
|
|
#include "dl_rule_transformer.h"
|
|
#include "dl_mk_interp_tail_simplifier.h"
|
|
#include "unifier.h"
|
|
#include "substitution.h"
|
|
#include "substitution_tree.h"
|
|
|
|
namespace datalog {
|
|
|
|
class rule_unifier {
|
|
ast_manager& m;
|
|
rule_manager& m_rm;
|
|
context& m_context;
|
|
/** We use this simplifier after inlining to get nicer intermediate rules */
|
|
mk_interp_tail_simplifier m_interp_simplifier;
|
|
substitution m_subst;
|
|
unifier m_unif;
|
|
bool m_ready;
|
|
unsigned m_deltas[2];
|
|
public:
|
|
rule_unifier(rule_manager& rm, context& ctx, ast_manager& m)
|
|
: m(m), m_rm(rm), m_context(ctx), m_interp_simplifier(ctx), m_subst(m), m_unif(m), m_ready(false) {}
|
|
|
|
/** Reset subtitution and unify tail tgt_idx of the target rule and the head of the src rule */
|
|
bool unify_rules(const rule& tgt, unsigned tgt_idx, const rule& src);
|
|
|
|
/**
|
|
\brief Apply unifier to rules.
|
|
Return false if the resulting rule is a tautology (the interpreted tail is unsat).
|
|
*/
|
|
bool apply(rule& tgt, unsigned tgt_idx, rule& src, rule_ref& result);
|
|
|
|
void display(std::ostream& stm) { m_subst.display(stm, 2, m_deltas); }
|
|
|
|
/**
|
|
Retrieve substitutions for src/tgt. (second argument of unify_rules).
|
|
*/
|
|
expr_ref_vector get_rule_subst(const rule& r, bool is_tgt);
|
|
|
|
private:
|
|
void apply(app * a, bool is_tgt, app_ref& res);
|
|
|
|
/**
|
|
Apply substitution to a rule tail. Tail with skipped_index is skipped,
|
|
unless skipped_index is equal to UINT_MAX
|
|
*/
|
|
void apply(rule& r, bool is_tgt, unsigned skipped_index, app_ref_vector& res,
|
|
svector<bool>& res_neg);
|
|
|
|
};
|
|
|
|
class mk_rule_inliner : public rule_transformer::plugin {
|
|
|
|
class visitor : public st_visitor {
|
|
context& m_context;
|
|
unsigned_vector m_unifiers;
|
|
svector<bool> m_can_remove, m_can_expand;
|
|
obj_map<expr, unsigned_vector> m_positions;
|
|
public:
|
|
visitor(context& c, substitution & s): st_visitor(s), m_context(c) {}
|
|
virtual bool operator()(expr* e);
|
|
void reset() { m_unifiers.reset(); }
|
|
void reset(unsigned sz);
|
|
svector<bool>& can_remove() { return m_can_remove; }
|
|
svector<bool>& can_expand() { return m_can_expand; }
|
|
unsigned_vector const& add_position(expr* e, unsigned j);
|
|
unsigned_vector const& del_position(expr* e, unsigned j);
|
|
unsigned_vector const& get_unifiers() { return m_unifiers; }
|
|
};
|
|
|
|
typedef obj_map<func_decl, func_decl *> decl_map;
|
|
|
|
ast_manager & m;
|
|
rule_manager & m_rm;
|
|
context & m_context;
|
|
th_rewriter& m_simp;
|
|
rule_ref_vector m_pinned;
|
|
decl_set m_forbidden_preds;
|
|
decl_set m_preds_with_facts;
|
|
decl_set m_preds_with_neg_occurrence;
|
|
ast_counter m_head_pred_ctr;
|
|
ast_counter m_head_pred_non_empty_tails_ctr;
|
|
ast_counter m_tail_pred_ctr;
|
|
rule_set m_inlined_rules;
|
|
horn_subsume_model_converter* m_mc;
|
|
replace_proof_converter* m_pc;
|
|
|
|
|
|
//used in try_to_inline_rule and do_eager_inlining
|
|
rule_unifier m_unifier;
|
|
|
|
substitution_tree m_head_index; // for straight-line relation inlining.
|
|
substitution_tree m_tail_index;
|
|
substitution m_subst;
|
|
visitor m_head_visitor;
|
|
visitor m_tail_visitor;
|
|
|
|
bool tail_matches_head(app * tail, app* head);
|
|
|
|
bool try_to_inline_rule(rule& tgt, rule& src, unsigned tail_index, rule_ref& res);
|
|
|
|
bool inlining_allowed(func_decl * pred);
|
|
|
|
void count_pred_occurrences(rule_set const & orig);
|
|
|
|
void plan_inlining(rule_set const & orig);
|
|
|
|
rule_set * create_allowed_rule_set(rule_set const & orig);
|
|
|
|
bool forbid_preds_from_cycles(rule_set const & r);
|
|
|
|
/** Ensure we don't inline two multi-head rules that would appear together in some tail */
|
|
bool forbid_multiple_multipliers(const rule_set & orig, rule_set const & proposed_inlined_rules);
|
|
|
|
/** Return true if the rule was modified */
|
|
bool transform_rule(rule * r, rule_set& tgt);
|
|
|
|
/** Return true if some transformation was performed */
|
|
bool transform_rules(const rule_set & orig, rule_set & tgt);
|
|
|
|
bool is_oriented_rewriter(rule * r, rule_stratifier const& strat);
|
|
|
|
/**
|
|
Return false if nothing was done with the rule.
|
|
res may be set to zero if we managed to prove the rule unsatisfiable.
|
|
*/
|
|
bool do_eager_inlining(rule * r, rule_set const& rules, rule_ref& res);
|
|
|
|
|
|
/**
|
|
Inline rules even if it doesn't lead to elimination of the whole predicate.
|
|
|
|
The inlining is done as long as it doesn't increase the number of rules
|
|
(i.e. when only one rule defining a predicate can replace tail atom).
|
|
|
|
The original rule-set must be closed before passing t this function
|
|
*/
|
|
bool do_eager_inlining(scoped_ptr<rule_set> & rules);
|
|
|
|
bool has_quantifier(rule const& r) const;
|
|
|
|
/**
|
|
Inline predicates that are known to not be join-points.
|
|
*/
|
|
bool inline_linear(scoped_ptr<rule_set>& rules);
|
|
|
|
void add_rule(rule* r, unsigned i);
|
|
void del_rule(rule* r, unsigned i);
|
|
|
|
public:
|
|
mk_rule_inliner(context & ctx, unsigned priority=35000)
|
|
: plugin(priority),
|
|
m(ctx.get_manager()),
|
|
m_rm(ctx.get_rule_manager()),
|
|
m_context(ctx),
|
|
m_simp(m_context.get_rewriter()),
|
|
m_pinned(m_rm),
|
|
m_inlined_rules(m_context),
|
|
m_unifier(ctx.get_rule_manager(), ctx, m),
|
|
m_mc(0),
|
|
m_pc(0),
|
|
m_head_index(m),
|
|
m_tail_index(m),
|
|
m_subst(m),
|
|
m_head_visitor(ctx, m_subst),
|
|
m_tail_visitor(ctx, m_subst)
|
|
{}
|
|
virtual ~mk_rule_inliner() { }
|
|
|
|
rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc);
|
|
};
|
|
|
|
};
|
|
|
|
#endif /* _DL_MK_INTERP_TAIL_SIMPLIFIER_H_ */
|
|
|