3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-06 09:34:08 +00:00

Add initial value setting for variables in Z3 API, solver, and optimize modules

This commit is contained in:
Nikolaj Bjorner 2024-09-18 16:13:15 +03:00
parent 0ba306e7b3
commit 48712b4f60
31 changed files with 297 additions and 9 deletions

View file

@ -459,6 +459,21 @@ extern "C" {
Z3_CATCH; Z3_CATCH;
} }
void Z3_API Z3_optimize_set_initial_value(Z3_context c, Z3_optimize o, Z3_ast var, Z3_ast value) {
Z3_TRY;
LOG_Z3_optimize_set_initial_value(c, o, var, value);
RESET_ERROR_CODE();
if (to_expr(var)->get_sort() != to_expr(value)->get_sort()) {
SET_ERROR_CODE(Z3_INVALID_USAGE, "variable and value should have same sort");
return;
}
ast_manager& m = mk_c(c)->m();
if (!m.is_value(to_expr(value))) {
SET_ERROR_CODE(Z3_INVALID_USAGE, "a proper value was not supplied");
return;
}
to_optimize_ptr(o)->initialize_value(to_expr(var), to_expr(value));
Z3_CATCH;
}
}; };

View file

@ -1143,5 +1143,23 @@ extern "C" {
Z3_CATCH_RETURN(nullptr); Z3_CATCH_RETURN(nullptr);
} }
void Z3_API Z3_solver_set_initial_value(Z3_context c, Z3_solver s, Z3_ast var, Z3_ast value) {
Z3_TRY;
LOG_Z3_solver_set_initial_value(c, s, var, value);
RESET_ERROR_CODE();
if (to_expr(var)->get_sort() != to_expr(value)->get_sort()) {
SET_ERROR_CODE(Z3_INVALID_USAGE, "variable and value should have same sort");
return;
}
ast_manager& m = mk_c(c)->m();
if (!m.is_value(to_expr(value))) {
SET_ERROR_CODE(Z3_INVALID_USAGE, "a proper value was not supplied");
return;
}
to_solver_ref(s)->user_propagate_initialize_value(to_expr(var), to_expr(value));
Z3_CATCH;
}
}; };

View file

@ -2865,6 +2865,17 @@ namespace z3 {
check_error(); check_error();
return result; return result;
} }
void set_initial_value(expr const& var, expr const& value) {
Z3_solver_set_initial_value(ctx(), m_solver, var, value);
check_error();
}
void set_initial_value(expr const& var, int i) {
set_initial_value(var, ctx().num_val(i, var.get_sort()));
}
void set_initial_value(expr const& var, bool b) {
set_initial_value(var, ctx().bool_val(b));
}
expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); } expr proof() const { Z3_ast r = Z3_solver_get_proof(ctx(), m_solver); check_error(); return expr(ctx(), r); }
friend std::ostream & operator<<(std::ostream & out, solver const & s); friend std::ostream & operator<<(std::ostream & out, solver const & s);
@ -3330,6 +3341,17 @@ namespace z3 {
handle add(expr const& e, unsigned weight) { handle add(expr const& e, unsigned weight) {
return add_soft(e, weight); return add_soft(e, weight);
} }
void set_initial_value(expr const& var, expr const& value) {
Z3_optimize_set_initial_value(ctx(), m_opt, var, value);
check_error();
}
void set_initial_value(expr const& var, int i) {
set_initial_value(var, ctx().num_val(i, var.get_sort()));
}
void set_initial_value(expr const& var, bool b) {
set_initial_value(var, ctx().bool_val(b));
}
handle maximize(expr const& e) { handle maximize(expr const& e) {
return handle(Z3_optimize_maximize(ctx(), m_opt, e)); return handle(Z3_optimize_maximize(ctx(), m_opt, e));
} }

View file

@ -7353,6 +7353,13 @@ class Solver(Z3PPObject):
Z3_solver_get_levels(self.ctx.ref(), self.solver, trail.vector, len(trail), levels) Z3_solver_get_levels(self.ctx.ref(), self.solver, trail.vector, len(trail), levels)
return trail, levels return trail, levels
def set_initial_value(self, var, value):
"""initialize the solver's state by setting the initial value of var to value
"""
s = var.sort()
value = s.cast(value)
Z3_solver_set_initial_value(self.ctx.ref(), self.solver, var.ast, value.ast)
def trail(self): def trail(self):
"""Return trail of the solver state after a check() call. """Return trail of the solver state after a check() call.
""" """
@ -8032,6 +8039,13 @@ class Optimize(Z3PPObject):
return [asoft(a) for a in arg] return [asoft(a) for a in arg]
return asoft(arg) return asoft(arg)
def set_initial_value(self, var, value):
"""initialize the solver's state by setting the initial value of var to value
"""
s = var.sort()
value = s.cast(value)
Z3_optimize_set_initial_value(self.ctx.ref(), self.optimize, var.ast, value.ast)
def maximize(self, arg): def maximize(self, arg):
"""Add objective function to maximize.""" """Add objective function to maximize."""
return OptimizeObjective( return OptimizeObjective(

View file

@ -7241,6 +7241,18 @@ extern "C" {
bool Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback cb, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq); bool Z3_API Z3_solver_propagate_consequence(Z3_context c, Z3_solver_callback cb, unsigned num_fixed, Z3_ast const* fixed, unsigned num_eqs, Z3_ast const* eq_lhs, Z3_ast const* eq_rhs, Z3_ast conseq);
/**
\brief provide an initialization hint to the solver. The initialization hint is used to calibrate an initial value of the expression that
represents a variable. If the variable is Boolean, the initial phase is set according to \c value. If the variable is an integer or real,
the initial Simplex tableau is recalibrated to attempt to follow the value assignment.
def_API('Z3_solver_set_initial_value', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST), _in(AST)))
*/
void Z3_API Z3_solver_set_initial_value(Z3_context c, Z3_solver s, Z3_ast var, Z3_ast value);
/** /**
\brief Check whether the assertions in a given solver are consistent or not. \brief Check whether the assertions in a given solver are consistent or not.

View file

@ -139,6 +139,18 @@ extern "C" {
*/ */
void Z3_API Z3_optimize_pop(Z3_context c, Z3_optimize d); void Z3_API Z3_optimize_pop(Z3_context c, Z3_optimize d);
/**
\brief provide an initialization hint to the solver.
The initialization hint is used to calibrate an initial value of the expression that
represents a variable. If the variable is Boolean, the initial phase is set
according to \c value. If the variable is an integer or real,
the initial Simplex tableau is recalibrated to attempt to follow the value assignment.
def_API('Z3_optimize_set_initial_value', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST), _in(AST)))
*/
void Z3_API Z3_optimize_set_initial_value(Z3_context c, Z3_optimize o, Z3_ast var, Z3_ast value);
/** /**
\brief Check consistency and produce optimal values. \brief Check consistency and produce optimal values.
\param c - context \param c - context

View file

@ -2081,6 +2081,24 @@ namespace lp {
lpvar lar_solver::to_column(unsigned ext_j) const { lpvar lar_solver::to_column(unsigned ext_j) const {
return m_var_register.external_to_local(ext_j); return m_var_register.external_to_local(ext_j);
} }
bool lar_solver::move_lpvar_to_value(lpvar j, mpq const& value) {
if (is_base(j))
return false;
impq ivalue(value);
auto& lcs = m_mpq_lar_core_solver;
auto& slv = m_mpq_lar_core_solver.m_r_solver;
if (slv.column_has_upper_bound(j) && lcs.m_r_upper_bounds()[j] < ivalue)
return false;
if (slv.column_has_lower_bound(j) && lcs.m_r_lower_bounds()[j] > ivalue)
return false;
set_value_for_nbasic_column(j, ivalue);
return true;
}
bool lar_solver::tighten_term_bounds_by_delta(lpvar j, const impq& delta) { bool lar_solver::tighten_term_bounds_by_delta(lpvar j, const impq& delta) {
SASSERT(column_has_term(j)); SASSERT(column_has_term(j));

View file

@ -623,6 +623,7 @@ public:
lp_status find_feasible_solution(); lp_status find_feasible_solution();
void move_non_basic_columns_to_bounds(); void move_non_basic_columns_to_bounds();
bool move_non_basic_column_to_bounds(unsigned j); bool move_non_basic_column_to_bounds(unsigned j);
bool move_lpvar_to_value(lpvar j, mpq const& value);
inline bool r_basis_has_inf_int() const { inline bool r_basis_has_inf_int() const {
for (unsigned j : r_basis()) { for (unsigned j : r_basis()) {
if (column_is_int(j) && !column_value_is_int(j)) if (column_is_int(j) && !column_value_is_int(j))

View file

@ -58,8 +58,9 @@ namespace opt {
} }
void context::scoped_state::pop() { void context::scoped_state::pop() {
m_hard.resize(m_hard_lim.back()); m_hard.shrink(m_hard_lim.back());
m_asms.resize(m_asms_lim.back()); m_asms.shrink(m_asms_lim.back());
m_values.shrink(m_values_lim.back());
unsigned k = m_objectives_term_trail_lim.back(); unsigned k = m_objectives_term_trail_lim.back();
while (m_objectives_term_trail.size() > k) { while (m_objectives_term_trail.size() > k) {
unsigned idx = m_objectives_term_trail.back(); unsigned idx = m_objectives_term_trail.back();
@ -79,6 +80,7 @@ namespace opt {
m_objectives_lim.pop_back(); m_objectives_lim.pop_back();
m_hard_lim.pop_back(); m_hard_lim.pop_back();
m_asms_lim.pop_back(); m_asms_lim.pop_back();
m_values_lim.pop_back();
} }
void context::scoped_state::add(expr* hard) { void context::scoped_state::add(expr* hard) {
@ -306,13 +308,11 @@ namespace opt {
if (contains_quantifiers()) { if (contains_quantifiers()) {
warning_msg("optimization with quantified constraints is not supported"); warning_msg("optimization with quantified constraints is not supported");
} }
#if 0
if (is_qsat_opt()) {
return run_qsat_opt();
}
#endif
solver& s = get_solver(); solver& s = get_solver();
s.assert_expr(m_hard_constraints); s.assert_expr(m_hard_constraints);
for (auto const& [var, value] : m_scoped_state.m_values) {
s.user_propagate_initialize_value(var, value);
}
opt_params optp(m_params); opt_params optp(m_params);
symbol pri = optp.priority(); symbol pri = optp.priority();
@ -697,6 +697,11 @@ namespace opt {
} }
} }
void context::initialize_value(expr* var, expr* value) {
m_scoped_state.m_values.push_back({expr_ref(var, m), expr_ref(value, m)});
}
/** /**
* Set the solver to the SAT core. * Set the solver to the SAT core.
* It requres: * It requres:

View file

@ -140,12 +140,14 @@ namespace opt {
unsigned_vector m_objectives_lim; unsigned_vector m_objectives_lim;
unsigned_vector m_objectives_term_trail; unsigned_vector m_objectives_term_trail;
unsigned_vector m_objectives_term_trail_lim; unsigned_vector m_objectives_term_trail_lim;
unsigned_vector m_values_lim;
map_id m_indices; map_id m_indices;
public: public:
expr_ref_vector m_hard; expr_ref_vector m_hard;
expr_ref_vector m_asms; expr_ref_vector m_asms;
vector<objective> m_objectives; vector<objective> m_objectives;
vector<std::pair<expr_ref, expr_ref>> m_values;
scoped_state(ast_manager& m): scoped_state(ast_manager& m):
m(m), m(m),
@ -275,6 +277,8 @@ namespace opt {
void add_offset(unsigned id, rational const& o) override; void add_offset(unsigned id, rational const& o) override;
void initialize_value(expr* var, expr* value);
void register_on_model(on_model_t& ctx, std::function<void(on_model_t&, model_ref&)>& on_model) { void register_on_model(on_model_t& ctx, std::function<void(on_model_t&, model_ref&)>& on_model) {
m_on_model_ctx = ctx; m_on_model_ctx = ctx;
m_on_model_eh = on_model; m_on_model_eh = on_model;

View file

@ -116,6 +116,7 @@ namespace opt {
phase* get_phase() override { return m_context.get_phase(); } phase* get_phase() override { return m_context.get_phase(); }
void set_phase(phase* p) override { m_context.set_phase(p); } void set_phase(phase* p) override { m_context.set_phase(p); }
void move_to_front(expr* e) override { m_context.move_to_front(e); } void move_to_front(expr* e) override { m_context.move_to_front(e); }
void user_propagate_initialize_value(expr* var, expr* value) override { m_context.user_propagate_initialize_value(var, value); }
void set_logic(symbol const& logic); void set_logic(symbol const& logic);

View file

@ -702,6 +702,10 @@ public:
ensure_euf()->user_propagate_register_decide(r); ensure_euf()->user_propagate_register_decide(r);
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
ensure_euf()->user_propagate_initialize_value(var, value);
}
private: private:

View file

@ -577,6 +577,11 @@ public:
ensure_euf()->user_propagate_register_decide(r); ensure_euf()->user_propagate_register_decide(r);
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
ensure_euf()->user_propagate_initialize_value(var, value);
}
private: private:
void add_assumption(expr* a) { void add_assumption(expr* a) {

View file

@ -1256,6 +1256,31 @@ namespace euf {
add_solver(m_user_propagator); add_solver(m_user_propagator);
} }
void solver::user_propagate_initialize_value(expr* var, expr* value) {
if (m.is_bool(var)) {
auto lit = expr2literal(var);
if (lit == sat::null_literal) {
IF_VERBOSE(5, verbose_stream() << "no literal associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
if (m.is_true(value))
s().set_phase(lit);
else if (m.is_false(value))
s().set_phase(~lit);
else
IF_VERBOSE(5, verbose_stream() << "malformed value " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
auto* th = m_id2solver.get(var->get_sort()->get_family_id(), nullptr);
if (!th) {
IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
// th->initialize_value(var, value);
IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
}
bool solver::watches_fixed(enode* n) const { bool solver::watches_fixed(enode* n) const {
return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_id()) != null_theory_var; return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_id()) != null_theory_var;
} }

View file

@ -564,6 +564,8 @@ namespace euf {
m_user_propagator->add_expr(e); m_user_propagator->add_expr(e);
} }
void user_propagate_initialize_value(expr* var, expr* value);
// solver factory // solver factory
::solver* mk_solver() { return m_mk_solver(); } ::solver* mk_solver() { return m_mk_solver(); }
void set_mk_solver(std::function<::solver*(void)>& mk) { m_mk_solver = mk; } void set_mk_solver(std::function<::solver*(void)>& mk) { m_mk_solver = mk; }

View file

@ -2914,6 +2914,44 @@ namespace smt {
register_plugin(m_user_propagator); register_plugin(m_user_propagator);
} }
void context::user_propagate_initialize_value(expr* var, expr* value) {
m_values.push_back({expr_ref(var, m), expr_ref(value, m)});
push_trail(push_back_vector(m_values));
}
void context::initialize_value(expr* var, expr* value) {
IF_VERBOSE(10, verbose_stream() << "context initialize " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
sort* s = var->get_sort();
ensure_internalized(var);
if (m.is_bool(s)) {
auto v = get_bool_var_of_id_option(var->get_id());
if (v == null_bool_var) {
IF_VERBOSE(5, verbose_stream() << "Boolean variable has no literal " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
m_bdata[v].m_phase_available = true;
if (m.is_true(value))
m_bdata[v].m_phase = true;
else if (m.is_false(value))
m_bdata[v].m_phase = false;
else
IF_VERBOSE(5, verbose_stream() << "Boolean value is not constant " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
if (!e_internalized(var))
return;
enode* n = get_enode(var);
theory* th = m_theories.get_plugin(s->get_family_id());
if (!th) {
IF_VERBOSE(5, verbose_stream() << "No theory is attached to variable " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
th->initialize_value(var, value);
}
bool context::watches_fixed(enode* n) const { bool context::watches_fixed(enode* n) const {
return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_family_id()) != null_theory_var; return m_user_propagator && m_user_propagator->has_fixed() && n->get_th_var(m_user_propagator->get_family_id()) != null_theory_var;
} }
@ -3756,6 +3794,9 @@ namespace smt {
TRACE("search", display(tout); display_enodes_lbls(tout);); TRACE("search", display(tout); display_enodes_lbls(tout););
TRACE("search_detail", m_asserted_formulas.display(tout);); TRACE("search_detail", m_asserted_formulas.display(tout););
init_search(); init_search();
for (auto const& [var, value] : m_values)
initialize_value(var, value);
flet<bool> l(m_searching, true); flet<bool> l(m_searching, true);
TRACE("after_init_search", display(tout);); TRACE("after_init_search", display(tout););
IF_VERBOSE(2, verbose_stream() << "(smt.searching)\n";); IF_VERBOSE(2, verbose_stream() << "(smt.searching)\n";);

View file

@ -123,6 +123,7 @@ namespace smt {
unsigned m_par_index = 0; unsigned m_par_index = 0;
bool m_internalizing_assertions = false; bool m_internalizing_assertions = false;
// ----------------------------------- // -----------------------------------
// //
// Equality & Uninterpreted functions // Equality & Uninterpreted functions
@ -246,6 +247,16 @@ namespace smt {
vector<literal_vector> m_th_case_split_sets; vector<literal_vector> m_th_case_split_sets;
u_map< vector<literal_vector> > m_literal2casesplitsets; // returns the case split literal sets that a literal participates in u_map< vector<literal_vector> > m_literal2casesplitsets; // returns the case split literal sets that a literal participates in
// ----------------------------------
//
// Value initialization
//
// ----------------------------------
vector<std::pair<expr_ref, expr_ref>> m_values;
void initialize_value(expr* var, expr* value);
// ----------------------------------- // -----------------------------------
// //
// Accessors // Accessors
@ -1777,6 +1788,8 @@ namespace smt {
m_user_propagator->register_decide(r); m_user_propagator->register_decide(r);
} }
void user_propagate_initialize_value(expr* var, expr* value);
bool watches_fixed(enode* n) const; bool watches_fixed(enode* n) const;
bool has_split_candidate(bool_var& var, bool& is_pos); bool has_split_candidate(bool_var& var, bool& is_pos);

View file

@ -305,5 +305,9 @@ namespace smt {
void kernel::user_propagate_register_decide(user_propagator::decide_eh_t& r) { void kernel::user_propagate_register_decide(user_propagator::decide_eh_t& r) {
m_imp->m_kernel.user_propagate_register_decide(r); m_imp->m_kernel.user_propagate_register_decide(r);
} }
void kernel::user_propagate_initialize_value(expr* var, expr* value) {
m_imp->m_kernel.user_propagate_initialize_value(var, value);
}
}; };

View file

@ -322,6 +322,8 @@ namespace smt {
void user_propagate_register_decide(user_propagator::decide_eh_t& r); void user_propagate_register_decide(user_propagator::decide_eh_t& r);
void user_propagate_initialize_value(expr* var, expr* value);
/** /**
\brief Return a reference to smt::context. \brief Return a reference to smt::context.
This breaks abstractions. This breaks abstractions.

View file

@ -252,6 +252,10 @@ namespace {
m_context.user_propagate_register_decide(c); m_context.user_propagate_register_decide(c);
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
m_context.user_propagate_initialize_value(var, value);
}
struct scoped_minimize_core { struct scoped_minimize_core {
smt_solver& s; smt_solver& s;
expr_ref_vector m_assumptions; expr_ref_vector m_assumptions;

View file

@ -549,6 +549,10 @@ namespace smt {
return get_manager().mk_eq(lhs, rhs); return get_manager().mk_eq(lhs, rhs);
} }
virtual void initialize_value(expr* var, expr* value) {
IF_VERBOSE(5, verbose_stream() << "no default initialization associated with " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
}
literal mk_eq(expr * a, expr * b, bool gate_ctx); literal mk_eq(expr * a, expr * b, bool gate_ctx);
literal mk_preferred_eq(expr* a, expr* b); literal mk_preferred_eq(expr* a, expr* b);

View file

@ -41,6 +41,7 @@ class smt_tactic : public tactic {
smt_params m_params; smt_params m_params;
params_ref m_params_ref; params_ref m_params_ref;
expr_ref_vector m_vars; expr_ref_vector m_vars;
vector<std::pair<expr_ref, expr_ref>> m_values;
statistics m_stats; statistics m_stats;
smt::kernel* m_ctx = nullptr; smt::kernel* m_ctx = nullptr;
symbol m_logic; symbol m_logic;
@ -344,6 +345,8 @@ public:
for (expr* v : m_vars) for (expr* v : m_vars)
m_ctx->user_propagate_register_expr(v); m_ctx->user_propagate_register_expr(v);
for (auto& [var, value] : m_values)
m_ctx->user_propagate_initialize_value(var, value);
} }
void user_propagate_clear() override { void user_propagate_clear() override {
@ -403,6 +406,10 @@ public:
void user_propagate_register_decide(user_propagator::decide_eh_t& decide_eh) override { void user_propagate_register_decide(user_propagator::decide_eh_t& decide_eh) override {
m_decide_eh = decide_eh; m_decide_eh = decide_eh;
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
m_values.push_back({expr_ref(var, m), expr_ref(value, m)});
}
}; };
static tactic * mk_seq_smt_tactic(ast_manager& m, params_ref const & p) { static tactic * mk_seq_smt_tactic(ast_manager& m, params_ref const & p) {

View file

@ -662,6 +662,7 @@ namespace smt {
void restart_eh() override; void restart_eh() override;
void init_search_eh() override; void init_search_eh() override;
void initialize_value(expr* var, expr* value) override;
/** /**
\brief True if the assignment may be changed during final \brief True if the assignment may be changed during final
check. assume_eqs, check_int_feasibility, check. assume_eqs, check_int_feasibility,

View file

@ -2249,6 +2249,21 @@ namespace smt {
return false; return false;
} }
template<typename Ext>
void theory_arith<Ext>::initialize_value(expr* var, expr* value) {
theory_var v = expr2var(var);
rational r;
if (!m_util.is_numeral(value, r)) {
IF_VERBOSE(5, verbose_stream() << "numeric constant expected in initialization " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
if (v == null_theory_var)
return;
if (is_base(v))
return;
update_value(v, inf_numeral(r));
}
#if 0 #if 0
/** /**

View file

@ -154,6 +154,7 @@ class theory_lra::imp {
svector<delayed_atom> m_asserted_atoms; svector<delayed_atom> m_asserted_atoms;
ptr_vector<expr> m_not_handled; ptr_vector<expr> m_not_handled;
ptr_vector<app> m_underspecified; ptr_vector<app> m_underspecified;
vector<std::pair<lpvar, rational>> m_values;
vector<ptr_vector<api_bound> > m_use_list; // bounds where variables are used. vector<ptr_vector<api_bound> > m_use_list; // bounds where variables are used.
// attributes for incremental version: // attributes for incremental version:
@ -991,6 +992,16 @@ public:
return lp().compare_values(vi, k, b->get_value()) ? l_true : l_false; return lp().compare_values(vi, k, b->get_value()) ? l_true : l_false;
} }
void initialize_value(expr* var, expr* value) {
rational r;
if (!a.is_numeral(value, r)) {
IF_VERBOSE(5, verbose_stream() << "numeric constant expected in initialization " << mk_pp(var, m) << " := " << mk_pp(value, m) << "\n");
return;
}
ctx().push_trail(push_back_vector(m_values));
m_values.push_back({get_lpvar(var), r});
}
void new_eq_eh(theory_var v1, theory_var v2) { void new_eq_eh(theory_var v1, theory_var v2) {
TRACE("arith", tout << "eq " << v1 << " == " << v2 << "\n";); TRACE("arith", tout << "eq " << v1 << " == " << v2 << "\n";);
if (!is_int(v1) && !is_real(v1)) if (!is_int(v1) && !is_real(v1))
@ -1409,6 +1420,9 @@ public:
void init_search_eh() { void init_search_eh() {
m_arith_eq_adapter.init_search_eh(); m_arith_eq_adapter.init_search_eh();
m_num_conflicts = 0; m_num_conflicts = 0;
for (auto const& [v, r] : m_values)
lp().move_lpvar_to_value(v, r);
display(verbose_stream() << "init search\n");
} }
bool can_get_value(theory_var v) const { bool can_get_value(theory_var v) const {
@ -3878,6 +3892,9 @@ void theory_lra::assign_eh(bool_var v, bool is_true) {
lbool theory_lra::get_phase(bool_var v) { lbool theory_lra::get_phase(bool_var v) {
return m_imp->get_phase(v); return m_imp->get_phase(v);
} }
void theory_lra::initialize_value(expr* var, expr* value) {
m_imp->initialize_value(var, value);
}
void theory_lra::new_eq_eh(theory_var v1, theory_var v2) { void theory_lra::new_eq_eh(theory_var v1, theory_var v2) {
m_imp->new_eq_eh(v1, v2); m_imp->new_eq_eh(v1, v2);
} }
@ -3912,7 +3929,7 @@ final_check_status theory_lra::final_check_eh() {
} }
bool theory_lra::is_shared(theory_var v) const { bool theory_lra::is_shared(theory_var v) const {
return m_imp->is_shared(v); return m_imp->is_shared(v);
} }
bool theory_lra::can_propagate() { bool theory_lra::can_propagate() {
return m_imp->can_propagate(); return m_imp->can_propagate();
} }

View file

@ -80,6 +80,8 @@ namespace smt {
void apply_sort_cnstr(enode * n, sort * s) override; void apply_sort_cnstr(enode * n, sort * s) override;
void init_model(model_generator & m) override; void init_model(model_generator & m) override;
void initialize_value(expr* var, expr* value) override;
model_value_proc * mk_value(enode * n, model_generator & mg) override; model_value_proc * mk_value(enode * n, model_generator & mg) override;
void validate_model(proto_model& mdl) override; void validate_model(proto_model& mdl) override;

View file

@ -394,6 +394,11 @@ public:
void user_propagate_clear() override { void user_propagate_clear() override {
m_solver2->user_propagate_clear(); m_solver2->user_propagate_clear();
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
m_solver2->user_propagate_initialize_value(var, value);
}
}; };

View file

@ -390,6 +390,8 @@ public:
void user_propagate_register_expr(expr* e) override { m_preprocess_state.freeze(e); s->user_propagate_register_expr(e); } void user_propagate_register_expr(expr* e) override { m_preprocess_state.freeze(e); s->user_propagate_register_expr(e); }
void user_propagate_register_created(user_propagator::created_eh_t& r) override { s->user_propagate_register_created(r); } void user_propagate_register_created(user_propagator::created_eh_t& r) override { s->user_propagate_register_created(r); }
void user_propagate_register_decide(user_propagator::decide_eh_t& r) override { s->user_propagate_register_decide(r); } void user_propagate_register_decide(user_propagator::decide_eh_t& r) override { s->user_propagate_register_decide(r); }
void user_propagate_initialize_value(expr* var, expr* value) override { m_preprocess_state.freeze(var); s->user_propagate_initialize_value(var, value); }
}; };

View file

@ -119,6 +119,10 @@ public:
void user_propagate_register_expr(expr* e) override { void user_propagate_register_expr(expr* e) override {
m_tactic->user_propagate_register_expr(e); m_tactic->user_propagate_register_expr(e);
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
m_tactic->user_propagate_initialize_value(var, value);
}
void user_propagate_register_created(user_propagator::created_eh_t& created_eh) override { void user_propagate_register_created(user_propagator::created_eh_t& created_eh) override {
m_tactic->user_propagate_register_created(created_eh); m_tactic->user_propagate_register_created(created_eh);

View file

@ -213,6 +213,10 @@ public:
m_t2->user_propagate_register_decide(decide_eh); m_t2->user_propagate_register_decide(decide_eh);
} }
void user_propagate_initialize_value(expr* var, expr* value) override {
m_t2->user_propagate_initialize_value(var, value);
}
}; };
tactic * and_then(tactic * t1, tactic * t2) { tactic * and_then(tactic * t1, tactic * t2) {
@ -884,6 +888,7 @@ public:
void set_progress_callback(progress_callback * callback) override { m_t->set_progress_callback(callback); } void set_progress_callback(progress_callback * callback) override { m_t->set_progress_callback(callback); }
void user_propagate_register_expr(expr* e) override { m_t->user_propagate_register_expr(e); } void user_propagate_register_expr(expr* e) override { m_t->user_propagate_register_expr(e); }
void user_propagate_clear() override { m_t->user_propagate_clear(); } void user_propagate_clear() override { m_t->user_propagate_clear(); }
void user_propagate_initialize_value(expr* var, expr* value) override { m_t->user_propagate_initialize_value(var, value); }
protected: protected:

View file

@ -99,6 +99,10 @@ namespace user_propagator {
throw default_exception("clause logging is only supported on the SMT solver"); throw default_exception("clause logging is only supported on the SMT solver");
} }
virtual void user_propagate_initialize_value(expr* var, expr* value) {
throw default_exception("value initialization is only supported on the SMT solver");
}
}; };