#pragma once
#include "ast/arith_decl_plugin.h"
#include "util/map.h"
#include "ast/rewriter/th_rewriter.h"
#include "util/str_hashtable.h"
#include "ast/rewriter/var_subst.h"
#include "muz/base/dl_costs.h"
#include "ast/dl_decl_plugin.h"
#include "muz/base/dl_rule_set.h"
#include "util/lbool.h"
#include "util/statistics.h"
#include "util/params.h"
#include "util/trail.h"
#include "ast/converters/model_converter.h"
#include "model/model2expr.h"
#include "params/smt_params.h"
#include "muz/base/dl_rule_transformer.h"
#include "ast/expr_functors.h"
#include "muz/base/dl_engine_base.h"
#include "muz/base/bind_variables.h"
#include "muz/base/rule_properties.h"
struct fp_params;
namespace datalog {
enum execution_result {
OK,
TIMEOUT,
MEMOUT,
INPUT_ERROR,
APPROX,
BOUNDED,
CANCELED
};
class relation_manager;
typedef sort * relation_sort;
typedef uint64_t table_element;
typedef svector<table_element> table_fact;
typedef app * relation_element;
typedef app_ref relation_element_ref;
class relation_fact : public app_ref_vector {
public:
class el_proxy {
friend class relation_fact;
relation_fact & m_parent;
unsigned m_idx;
el_proxy(relation_fact & parent, unsigned idx) : m_parent(parent), m_idx(idx) {}
public:
operator relation_element() const {
return m_parent.get(m_idx);
}
relation_element operator->() const {
return m_parent.get(m_idx);
}
relation_element operator=(const relation_element & val) const {
m_parent.set(m_idx, val);
return m_parent.get(m_idx);
}
relation_element operator=(const el_proxy & val) {
m_parent.set(m_idx, val);
return m_parent.get(m_idx);
}
};
typedef const relation_element * iterator;
relation_fact(ast_manager & m) : app_ref_vector(m) {}
relation_fact(ast_manager & m, unsigned sz) : app_ref_vector(m) { resize(sz); }
relation_fact(context & ctx);
iterator begin() const { return data(); }
iterator end() const { return data()+size(); }
relation_element operator[](unsigned i) const { return get(i); }
el_proxy operator[](unsigned i) { return el_proxy(*this, i); }
};
class rel_context_base : public engine_base {
public:
rel_context_base(ast_manager& m, char const* name): engine_base(m, name) {}
virtual relation_manager & get_rmanager() = 0;
virtual const relation_manager & get_rmanager() const = 0;
virtual relation_base & get_relation(func_decl * pred) = 0;
virtual relation_base * try_get_relation(func_decl * pred) const = 0;
virtual bool is_empty_relation(func_decl* pred) const = 0;
virtual expr_ref try_get_formula(func_decl * pred) const = 0;
virtual void display_output_facts(rule_set const& rules, std::ostream & out) const = 0;
virtual void display_facts(std::ostream & out) const = 0;
virtual void restrict_predicates(func_decl_set const& predicates) = 0;
virtual bool result_contains_fact(relation_fact const& f) = 0;
virtual void add_fact(func_decl* pred, relation_fact const& fact) = 0;
virtual void add_fact(func_decl* pred, table_fact const& fact) = 0;
virtual bool has_facts(func_decl * pred) const = 0;
virtual void store_relation(func_decl * pred, relation_base * rel) = 0;
virtual void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred) = 0;
virtual void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt,
symbol const * relation_names) = 0;
virtual bool output_profile() const = 0;
virtual void collect_non_empty_predicates(func_decl_set& preds) = 0;
virtual void transform_rules() = 0;
virtual bool try_get_size(func_decl* pred, unsigned& rel_sz) const = 0;
virtual lbool saturate() = 0;
};
class context {
public:
typedef unsigned finite_element;
enum sort_kind {
SK_UINT64,
SK_SYMBOL
};
class contains_pred : public i_expr_pred {
context const& ctx;
public:
contains_pred(context& ctx): ctx(ctx) {}
bool operator()(expr* e) override {
return ctx.is_predicate(e);
}
};
private:
class sort_domain;
class symbol_sort_domain;
class uint64_sort_domain;
class restore_rules;
typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
typedef map<symbol, func_decl*, symbol_hash_proc, symbol_eq_proc> sym2decl;
typedef obj_map<const func_decl, svector<symbol> > pred2syms;
typedef obj_map<const sort, sort_domain*> sort_domain_map;
ast_manager & m;
register_engine_base& m_register_engine;
smt_params & m_fparams;
params_ref m_params_ref;
fp_params* m_params;
bool m_generate_proof_trace; bool m_unbound_compressor; symbol m_default_relation; dl_decl_util m_decl_util;
th_rewriter m_rewriter;
var_subst m_var_subst;
rule_manager m_rule_manager;
contains_pred m_contains_p;
rule_properties m_rule_properties;
rule_transformer m_transf;
trail_stack m_trail;
ast_ref_vector m_pinned;
bind_variables m_bind_variables;
sort_domain_map m_sorts;
func_decl_set m_preds;
sym2decl m_preds_by_name;
pred2syms m_argument_var_names;
rule_set m_rule_set;
rule_set m_transformed_rule_set;
expr_free_vars m_free_vars;
unsigned m_rule_fmls_head;
expr_ref_vector m_rule_fmls;
svector<symbol> m_rule_names;
vector<unsigned> m_rule_bounds;
expr_ref_vector m_background;
model_converter_ref m_mc;
proof_converter_ref m_pc;
rel_context_base* m_rel;
scoped_ptr<engine_base> m_engine;
bool m_closed;
bool m_saturation_was_run;
bool m_enable_bind_variables;
execution_result m_last_status;
expr_ref m_last_answer;
expr_ref m_last_ground_answer;
DL_ENGINE m_engine_type;
bool is_fact(app * head) const;
bool has_sort_domain(relation_sort s) const;
sort_domain & get_sort_domain(relation_sort s);
const sort_domain & get_sort_domain(relation_sort s) const;
class engine_type_proc;
public:
context(ast_manager & m, register_engine_base& re, smt_params& fp, params_ref const& p = params_ref());
~context();
void reset();
void push();
void pop();
bool saturation_was_run() const { return m_saturation_was_run; }
void notify_saturation_was_run() { m_saturation_was_run = true; }
void configure_engine(expr* e);
ast_manager & get_manager() const { return m; }
rule_manager & get_rule_manager() { return m_rule_manager; }
smt_params & get_fparams() const { return m_fparams; }
fp_params const& get_params() const { return *m_params; }
DL_ENGINE get_engine(expr* e = nullptr) { configure_engine(e); return m_engine_type; }
register_engine_base& get_register_engine() { return m_register_engine; }
th_rewriter& get_rewriter() { return m_rewriter; }
var_subst & get_var_subst() { return m_var_subst; }
dl_decl_util & get_decl_util() { return m_decl_util; }
bool generate_proof_trace() const;
bool output_profile() const;
bool output_tuples() const;
bool use_map_names() const;
bool fix_unbound_vars() const;
symbol default_table() const;
symbol default_relation() const;
void set_default_relation(symbol const& s);
symbol default_table_checker() const;
symbol check_relation() const;
bool default_table_checked() const;
bool dbg_fpr_nonempty_relation_signature() const;
unsigned dl_profile_milliseconds_threshold() const;
bool all_or_nothing_deltas() const;
bool compile_with_widening() const;
bool unbound_compressor() const;
void set_unbound_compressor(bool f);
bool similarity_compressor() const;
symbol print_aig() const;
symbol tab_selection() const;
unsigned similarity_compressor_threshold() const;
unsigned soft_timeout() const;
unsigned initial_restart_timeout() const;
bool generate_explanations() const;
bool explanations_on_relation_level() const;
bool magic_sets_for_queries() const;
bool karr() const;
bool scale() const;
bool magic() const;
bool compress_unbound() const;
bool quantify_arrays() const;
bool instantiate_quantifiers() const;
bool xform_bit_blast() const;
bool xform_slice() const;
bool xform_coi() const;
bool array_blast() const;
bool array_blast_full() const;
bool elim_term_ite() const;
unsigned blast_term_ite_inflation() const;
void register_finite_sort(sort * s, sort_kind k);
void register_variable(func_decl* var);
expr_ref bind_vars(expr* fml, bool is_forall);
bool& bind_vars_enabled() { return m_enable_bind_variables; }
void register_predicate(func_decl * pred, bool named);
void restrict_predicates(func_decl_set const& preds);
func_decl_set const& get_predicates() const { return m_preds; }
ast_ref_vector const &get_pinned() const {return m_pinned; }
bool is_predicate(func_decl* pred) const { return m_preds.contains(pred); }
bool is_predicate(expr * e) const { return is_app(e) && is_predicate(to_app(e)->get_decl()); }
func_decl * try_get_predicate_decl(symbol const& pred_name) const {
func_decl * res = nullptr;
m_preds_by_name.find(pred_name, res);
return res;
}
func_decl * mk_fresh_head_predicate(symbol const & prefix, symbol const & suffix,
unsigned arity, sort * const * domain, func_decl* orig_pred=nullptr);
finite_element get_constant_number(relation_sort sort, symbol s);
finite_element get_constant_number(relation_sort srt, uint64_t el);
void print_constant_name(relation_sort sort, uint64_t num, std::ostream & out);
bool try_get_sort_constant_count(relation_sort srt, uint64_t & constant_count);
uint64_t get_sort_size_estimate(relation_sort srt);
void set_argument_names(const func_decl * pred, const svector<symbol> & var_names);
symbol get_argument_name(const func_decl * pred, unsigned arg_index);
void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt,
symbol const * relation_names);
void set_output_predicate(func_decl * pred) { m_rule_set.set_output_predicate(pred); }
rule_set & get_rules() { flush_add_rules(); return m_rule_set; }
void get_rules_as_formulas(expr_ref_vector& fmls, expr_ref_vector& qs, svector<symbol>& names);
void get_raw_rule_formulas(expr_ref_vector& fmls, svector<symbol>& names, unsigned_vector &bounds);
void add_fact(app * head);
void add_fact(func_decl * pred, const relation_fact & fact);
bool has_facts(func_decl * pred) const;
void add_rule(rule_ref& r);
void assert_expr(expr* e);
expr_ref get_background_assertion();
unsigned get_num_assertions() { return m_background.size(); }
expr* get_assertion(unsigned i) const { return m_background[i]; }
void add_rule(expr* rl, symbol const& name, unsigned bound = UINT_MAX);
void update_rule(expr* rl, symbol const& name);
unsigned get_num_levels(func_decl* pred);
expr_ref get_reachable(func_decl *pred);
expr_ref get_cover_delta(int level, func_decl* pred);
void add_cover(int level, func_decl* pred, expr* property);
void add_invariant (func_decl *pred, expr *property);
bool check_subsumes(rule const& stronger_rule, rule const& weaker_rule);
void check_rules(rule_set& r);
void add_table_fact(func_decl * pred, const table_fact & fact);
void add_table_fact(func_decl * pred, unsigned num_args, unsigned args[]);
void close();
void ensure_closed();
bool is_closed() { return m_closed; }
void reopen();
void ensure_opened();
model_converter_ref& get_model_converter() { return m_mc; }
void add_model_converter(model_converter* mc) { m_mc = concat(m_mc.get(), mc); }
proof_converter_ref& get_proof_converter() { return m_pc; }
void add_proof_converter(proof_converter* pc) { m_pc = concat(m_pc.get(), pc); }
void transform_rules(rule_transformer& transf);
void transform_rules(rule_transformer::plugin* plugin);
void replace_rules(rule_set const& rs);
void record_transformed_rules();
void apply_default_transformation();
void collect_params(param_descrs& r);
void updt_params(params_ref const& p);
void display_rules(std::ostream & out) const {
m_rule_set.display(out);
}
void display(std::ostream & out) const;
void display_smt2(unsigned num_queries, expr* const* qs, std::ostream& out);
void display_profile(std::ostream& out) const;
bool canceled() {
return !m.inc() && (m_last_status = CANCELED, true);
}
void cleanup();
lbool query(expr* q);
lbool query_from_lvl (expr* q, unsigned lvl);
model_ref get_model();
bool is_monotone();
proof_ref get_proof();
lbool rel_query(unsigned num_rels, func_decl * const* rels);
execution_result get_status();
void set_status(execution_result r) { m_last_status = r; }
expr* get_answer_as_formula();
expr* get_ground_sat_answer ();
void get_rules_along_trace (rule_ref_vector& rules);
void get_rules_along_trace_as_formulas (expr_ref_vector& rules, svector<symbol>& names);
void collect_statistics(statistics& st) const;
void reset_statistics();
std::ostream& display_certificate(std::ostream& out);
bool result_contains_fact(relation_fact const& f);
rel_context_base* get_rel_context() { ensure_engine(); return m_rel; }
void add_callback(void *state,
const datalog::t_new_lemma_eh new_lemma_eh,
const datalog::t_predecessor_eh predecessor_eh,
const datalog::t_unfold_eh unfold_eh) {
ensure_engine();
m_engine->add_callback(state, new_lemma_eh, predecessor_eh, unfold_eh);
}
void add_constraint (expr *c, unsigned lvl){
ensure_engine();
m_engine->add_constraint(c, lvl);
}
private:
void reset_tables();
void flush_add_rules();
void ensure_engine(expr* e = nullptr);
void declare_vars(expr_ref_vector& rules, mk_fresh_name& mk_fresh, std::ostream& out);
context(const context&);
context& operator=(const context&);
bool is_query(expr* e);
void display_rel_decl(std::ostream& out, func_decl* f);
};
};