#pragma once
#include "ast/ast.h"
#include "ast/quantifier_stat.h"
#include "util/statistics.h"
#include "util/params.h"
#include "smt/smt_types.h"
#include "tactic/user_propagator_base.h"
#include <tuple>
class proto_model;
struct smt_params;
namespace smt {
class quantifier_manager_plugin;
class quantifier_stat;
class context;
class quantifier_manager {
struct imp;
imp * m_imp;
unsigned m_lazy_scopes;
bool m_lazy;
void flush();
public:
quantifier_manager(context & ctx, smt_params & fp, params_ref const & p);
~quantifier_manager();
context & get_context() const;
void add(quantifier * q, unsigned generation);
void del(quantifier * q);
bool empty() const;
bool is_shared(enode * n) const;
q::quantifier_stat * get_stat(quantifier * q) const;
unsigned get_generation(quantifier * q) const;
static void log_justification_to_root(std::ostream & log, enode *en, obj_hashtable<enode> &already_visited, context &ctx, ast_manager &m);
bool add_instance(quantifier * q, app * pat,
unsigned num_bindings,
enode * const * bindings,
expr* def,
unsigned max_generation,
unsigned min_top_generation,
unsigned max_top_generation,
vector<std::tuple<enode *, enode *>> & used_enodes );
bool add_instance(quantifier * q, unsigned num_bindings, enode * const * bindings, expr* def, unsigned generation = 0);
void init_search_eh();
void assign_eh(quantifier * q);
void add_eq_eh(enode * n1, enode * n2);
void relevant_eh(enode * n);
final_check_status final_check_eh(bool full);
void restart_eh();
bool can_propagate() const;
void propagate();
enum check_model_result {
SAT, UNKNOWN, RESTART
};
bool model_based() const;
bool has_quantifiers() const;
bool mbqi_enabled(quantifier *q) const; void adjust_model(proto_model * m);
check_model_result check_model(proto_model * m, obj_map<enode, app *> const & root2value);
void push();
void pop(unsigned num_scopes);
void reset();
void display(std::ostream & out) const;
void display_stats(std::ostream & out, quantifier * q) const;
void collect_statistics(::statistics & st) const;
void reset_statistics();
void register_on_binding(std::function<bool(quantifier*, expr*)> & f);
ptr_vector<quantifier>::const_iterator begin_quantifiers() const;
ptr_vector<quantifier>::const_iterator end_quantifiers() const;
ptr_vector<quantifier>::const_iterator begin() const { return begin_quantifiers(); }
ptr_vector<quantifier>::const_iterator end() const { return end_quantifiers(); }
unsigned num_quantifiers() const;
};
class quantifier_manager_plugin {
public:
virtual ~quantifier_manager_plugin() = default;
virtual void set_manager(quantifier_manager & qm) = 0;
virtual quantifier_manager_plugin * mk_fresh() = 0;
virtual void add(quantifier * q) = 0;
virtual void del(quantifier * q) = 0;
virtual bool is_shared(enode * n) const = 0;
virtual void assign_eh(quantifier * q) = 0;
virtual void add_eq_eh(enode * n1, enode * n2) = 0;
virtual void relevant_eh(enode * n) = 0;
virtual void init_search_eh() = 0;
virtual final_check_status final_check_eh(bool full) = 0;
virtual void restart_eh() = 0;
virtual bool can_propagate() const = 0;
virtual void propagate() = 0;
virtual bool model_based() const = 0;
virtual bool mbqi_enabled(quantifier *q) const {return true;}
virtual void adjust_model(proto_model * m) = 0;
virtual quantifier_manager::check_model_result check_model(proto_model * m, obj_map<enode, app *> const & root2value) = 0;
virtual void push() = 0;
virtual void pop(unsigned num_scopes) = 0;
};
};