/*++ Copyright (c) 2025 Microsoft Corporation Module Name: preferred_value_propagator.h Abstract: Specialized propagator for preferred values Author: Nikolaj Bjorner (nbjorner) 10-2-2025 Notes: --*/ #pragma once #include "tactic/user_propagator_base.h" #include "util/trail.h" class preferred_value_propagator { ast_manager &m; expr_ref_vector m_preferred; unsigned m_qhead = 0; trail_stack m_trail; bool decide(user_propagator::callback& cb) { if (m_qhead >= m_preferred.size()) return false; m_trail.push(value_trail(m_qhead)); while (m_qhead < m_preferred.size()) { expr *e = m_preferred.get(m_qhead); bool is_not = m.is_not(e, e); m_qhead++; if (cb.next_split_cb(e, 0, is_not ? l_false : l_true)) return true; } return false; } public: preferred_value_propagator(ast_manager &m) : m(m), m_preferred(m) { push_eh = [](void * ctx, user_propagator::callback* cb) { auto &p = *static_cast(ctx); p.m_trail.push_scope(); }; pop_eh = [](void * ctx, user_propagator::callback* cb, unsigned n) -> void { auto &p = *static_cast(ctx); p.m_trail.pop_scope(n); }; fresh_eh = [](void* ctx, ast_manager& dst, user_propagator::context_obj*& co) -> void* { auto &p = *static_cast(ctx); ast_translation tr(p.m, dst); auto r = alloc(preferred_value_propagator, dst); for (auto e : p.m_preferred) r->set_preferred(tr(e)); return r; }; decide_eh = [](void * ctx, user_propagator::callback * cb, expr *, unsigned, bool) -> bool { auto &p = *static_cast(ctx); return p.decide(*cb); }; } ~preferred_value_propagator() = default; void set_preferred(expr *e) { m_preferred.push_back(e); if (m_trail.get_num_scopes() > 0) m_trail.push(push_back_vector(m_preferred)); } void reset_preferred() { if (m_trail.get_num_scopes() != 0) throw default_exception("cannot reset preferred values in scoped context"); m_preferred.reset(); SASSERT(m_qhead == 0); } user_propagator::push_eh_t push_eh; user_propagator::pop_eh_t pop_eh; user_propagator::fresh_eh_t fresh_eh; user_propagator::decide_eh_t decide_eh; };