#pragma once
#include "ast/ast.h"
#include "ast/substitution/substitution.h"
#include "ast/rewriter/bool_rewriter.h"
#include "ast/rewriter/th_rewriter.h"
#include "util/obj_hashtable.h"
#include "util/obj_pair_hashtable.h"
#include "util/array_map.h"
class demodulator_util {
ast_manager& m;
int is_subset(expr*, expr*) const;
int is_smaller(expr*, expr*) const;
public:
demodulator_util(ast_manager& m):m(m) {}
bool is_demodulator(expr* e, app_ref& large, expr_ref & small) const;
unsigned max_var_id(expr* e);
unsigned max_var_id(expr_ref_vector const& e);
};
class demodulator_match_subst {
typedef std::pair<expr *, expr *> expr_pair;
typedef obj_pair_hashtable<expr, expr> cache;
substitution m_subst;
cache m_cache;
svector<expr_pair> m_todo;
bool m_all_args_eq;
bool match_args(app * t, expr * const * args);
public:
demodulator_match_subst(ast_manager & m);
void reserve(unsigned max_vid) { m_subst.reserve(2, max_vid+1); }
bool operator()(app * lhs, expr * rhs, expr * const * args, expr_ref & new_rhs);
bool operator()(expr * t, expr * i);
bool can_rewrite(expr* n, expr* lhs);
bool get_binding(unsigned var_idx, expr_ref& r) const {
expr_offset eo;
if (!m_subst.find(var_idx, 0, eo))
return false;
r = eo.get_expr();
return true;
}
};
class demodulator_rewriter_util {
ast_manager& m;
std::function<bool(func_decl*, expr_ref_vector const&, expr_ref&, proof_ref&)> m_rewrite1;
typedef std::pair<expr *, bool> expr_bool_pair;
class plugin {
ast_manager& m;
public:
plugin(ast_manager& m): m(m) { }
void ins_eh(expr* k, expr_bool_pair v) { m.inc_ref(k); m.inc_ref(v.first); }
void del_eh(expr* k, expr_bool_pair v) { m.dec_ref(k); m.dec_ref(v.first); }
static unsigned to_int(expr const * k) { return k->get_id(); }
};
typedef array_map<expr*, expr_bool_pair, plugin> expr_map;
typedef expr_map rewrite_cache_map;
th_rewriter m_th_rewriter;
expr_ref_buffer m_rewrite_todo;
rewrite_cache_map m_rewrite_cache;
expr_ref_buffer m_new_exprs;
expr_ref_vector m_new_args;
obj_map<expr, proof*> m_proof_cache;
proof_ref_vector m_proof_trail;
bool rewrite_visit_children(app * a);
void rewrite_cache(expr * e, expr * new_e, bool done);
proof* get_step_proof(expr* e) const;
void update(expr* e, expr* new_e, bool done, proof* step_pr);
public:
demodulator_rewriter_util(ast_manager& m);
void set_rewrite1(std::function<bool(func_decl*, expr_ref_vector const&, expr_ref&, proof_ref&)>& fn) { m_rewrite1 = fn; }
expr_ref rewrite(expr * n, proof_ref& pr);
};
class demodulator_rewriter final {
class rewrite_proc;
class add_back_idx_proc;
class remove_back_idx_proc;
class can_rewrite_proc;
typedef std::pair<expr *, bool> expr_bool_pair;
class plugin {
ast_manager& m;
public:
plugin(ast_manager& m): m(m) { }
void ins_eh(expr* k, expr_bool_pair v) { m.inc_ref(k); m.inc_ref(v.first); }
void del_eh(expr* k, expr_bool_pair v) { m.dec_ref(k); m.dec_ref(v.first); }
static unsigned to_int(expr const * k) { return k->get_id(); }
};
typedef array_map<expr*, expr_bool_pair, plugin> expr_map;
typedef std::pair<expr *, expr *> expr_pair;
typedef std::pair<app *, expr* > app_expr_pair;
typedef obj_hashtable<expr> expr_set;
typedef obj_map<func_decl, expr_set *> back_idx_map;
typedef obj_hashtable<quantifier> quantifier_set;
typedef obj_map<func_decl, quantifier_set *> fwd_idx_map;
typedef obj_map<quantifier, app_expr_pair> demodulator2lhs_rhs;
typedef expr_map rewrite_cache_map;
ast_manager & m;
demodulator_match_subst m_match_subst;
demodulator_util m_util;
bool_rewriter m_bsimp;
fwd_idx_map m_fwd_idx;
back_idx_map m_back_idx;
demodulator2lhs_rhs m_demodulator2lhs_rhs;
expr_ref_buffer m_todo;
obj_hashtable<expr> m_processed;
expr_ref_vector m_in_processed;
expr_ref_vector m_new_args;
expr_ref_buffer m_rewrite_todo;
rewrite_cache_map m_rewrite_cache;
expr_ref_buffer m_new_exprs;
void insert_fwd_idx(app * large, expr * small, quantifier * demodulator);
void remove_fwd_idx(func_decl * f, quantifier * demodulator);
void insert_bwd_idx(expr* q);
void remove_bwd_idx(expr* q);
bool check_fwd_idx_consistency();
void show_fwd_idx(std::ostream & out);
expr * rewrite(expr * n);
bool rewrite1(func_decl * f, expr_ref_vector const & args, expr_ref & np);
bool rewrite_visit_children(app * a);
void rewrite_cache(expr * e, expr * new_e, bool done);
void reschedule_processed(func_decl * f);
void reschedule_demodulators(func_decl * f, expr * np);
public:
demodulator_rewriter(ast_manager & m);
~demodulator_rewriter();
void operator()(expr_ref_vector const& exprs, expr_ref_vector & new_exprs);
};