#pragma once
#include<utility>
#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 {
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<a_flag> {
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() = default;
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 {
return m_pred==o.m_pred && m_adornment==o.m_adornment;
}
unsigned hash() const {
return m_pred->hash()^svector_hash<a_flag_hash>()(m_adornment);
}
};
struct adorned_rule {
app * m_head;
adornment m_head_adornment;
ptr_vector<app> m_tail;
};
typedef hashtable<adornment_desc, obj_hash<adornment_desc>,
default_eq<adornment_desc> > adornment_set;
typedef map<adornment_desc, func_decl *, obj_hash<adornment_desc>,
default_eq<adornment_desc> > adornment_map;
typedef obj_map<func_decl, adornment> pred_adornment_map;
typedef obj_map<func_decl, func_decl *> pred2pred;
context & m_context;
ast_manager & m;
rule_manager& rm;
ast_ref_vector m_pinned;
func_decl_set m_extentional;
vector<adornment_desc> 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:
mk_magic_sets(context & ctx, func_decl* goal);
rule_set * operator()(rule_set const & source) override;
};
}