#pragma once
#include "sat/sat_solver.h"
#include "sat/smt/sat_th.h"
namespace euf {
class solver;
class relevancy {
euf::solver& ctx;
enum class update { relevant_var, add_queue, add_clause, set_root, set_qhead };
bool m_enabled = false;
svector<std::pair<update, unsigned>> m_trail;
unsigned_vector m_lim;
unsigned m_num_scopes = 0;
bool_vector m_relevant_var_ids; sat::clause_allocator m_alloc;
sat::clause_vector m_clauses; bool_vector m_roots; vector<unsigned_vector> m_occurs; unsigned m_qhead = 0; svector<std::pair<sat::literal, euf::enode*>> m_queue; euf::enode_vector m_stack, m_todo;
void push_core() { m_lim.push_back(m_trail.size()); }
void flush() { for (; m_num_scopes > 0; --m_num_scopes) push_core(); }
unsigned_vector& occurs(sat::literal lit) { m_occurs.reserve(lit.index() + 1); return m_occurs[lit.index()]; }
void propagate_relevant(sat::literal lit);
void add_to_propagation_queue(sat::literal lit);
void set_relevant(sat::literal lit);
void set_asserted(sat::literal lit);
void relevant_eh(sat::bool_var v);
void propagate_relevant(euf::enode* n);
public:
relevancy(euf::solver& ctx): ctx(ctx) {}
void push() { if (m_enabled) ++m_num_scopes; }
void pop(unsigned n);
void add_root(unsigned n, sat::literal const* lits);
void add_def(unsigned n, sat::literal const* lits);
void asserted(sat::literal lit);
void propagate();
bool can_propagate() const { return m_qhead < m_queue.size(); }
void mark_relevant(euf::enode* n);
void mark_relevant(sat::literal lit);
void merge(euf::enode* n1, euf::enode* n2);
bool is_relevant(sat::bool_var v) const { return !m_enabled || m_relevant_var_ids.get(v, false); }
bool is_relevant(sat::literal lit) const { return is_relevant(lit.var()); }
bool is_relevant(euf::enode* n) const { return !m_enabled || n->is_relevant(); }
bool enabled() const { return m_enabled; }
void set_enabled(bool e);
};
}