z3-z3-4.12.6.src.muz.transforms.dl_mk_magic_sets.h Maven / Gradle / Ivy
/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
dl_mk_magic_sets.h
Abstract:
Author:
Krystof Hoder (t-khoder) 2010-10-4.
Revision History:
--*/
#pragma once
#include
#include "util/map.h"
#include "util/obj_pair_hashtable.h"
#include "muz/base/dl_context.h"
#include "muz/base/dl_rule_set.h"
#include "muz/base/dl_rule_transformer.h"
namespace datalog {
/**
\brief Implements magic sets rule transformation.
According to A. Voronkov. Foundations of Deductive Databases.
The stratified negation is not in the book addressed wrt. magic sets, but it seems
that, for the purpose of magic sets, the negated literals should be treated just as
if they were non-negated (we are interested only in values of arguments, not in the
actual content of relations, at that point).
*/
class mk_magic_sets : public rule_transformer::plugin {
enum a_flag {
AD_FREE,
AD_BOUND
};
struct a_flag_hash {
typedef a_flag data_t;
unsigned operator()(a_flag x) const { return x; }
};
struct adornment : public svector {
void populate(app * lit, const var_idx_set & bound_vars);
bool operator==(const adornment & o) const {
return vectors_equal(*this, o);
}
std::string to_string() const;
};
struct adornment_desc {
func_decl * m_pred;
adornment m_adornment;
adornment_desc() {}
adornment_desc(func_decl * pred) : m_pred(pred) {}
adornment_desc(func_decl * pred, const adornment & a)
: m_pred(pred), m_adornment(a) {}
bool operator==(const adornment_desc & o) const {
//m_tail_adornment value is implied by the rule and the head adornment
return m_pred==o.m_pred && m_adornment==o.m_adornment;
}
unsigned hash() const {
return m_pred->hash()^svector_hash()(m_adornment);
}
};
struct adorned_rule {
app * m_head;
adornment m_head_adornment;
ptr_vector m_tail;
};
typedef hashtable,
default_eq > adornment_set;
typedef map,
default_eq > adornment_map;
typedef obj_map pred_adornment_map;
typedef obj_map pred2pred;
context & m_context;
ast_manager & m;
rule_manager& rm;
ast_ref_vector m_pinned;
/**
\brief Predicates from the original set that appear in a head of a rule
*/
func_decl_set m_extentional;
//adornment_set m_processed;
vector m_todo;
adornment_map m_adorned_preds;
pred_adornment_map m_adornments;
pred2pred m_magic_preds;
func_decl_ref m_goal;
void reset();
float get_unbound_cost(app * lit, const var_idx_set & bound_vars);
int pop_bound(unsigned_vector & cont, rule * r, const var_idx_set & bound_vars);
app * create_magic_literal(app * l);
void create_magic_rules(app * head, unsigned tail_cnt, app * const * tail, bool const* negated, rule_set& result);
app * adorn_literal(app * lit, const var_idx_set & bound_vars);
void transform_rule(const adornment & head_adornment, rule * r, rule_set& result);
void create_transfer_rule(const adornment_desc & d, rule_set& result);
public:
/**
\brief Create magic sets rule transformer for \c goal_rule. When applying the transformer,
the \c goal_rule must be present in the \c rule_set that is being transformed.
*/
mk_magic_sets(context & ctx, func_decl* goal);
rule_set * operator()(rule_set const & source) override;
};
};