mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
Add initial value setting for variables in Z3 API, solver, and optimize modules
This commit is contained in:
parent
0ba306e7b3
commit
48712b4f60
31 changed files with 297 additions and 9 deletions
|
@ -2914,6 +2914,44 @@ namespace smt {
|
|||
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 {
|
||||
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_detail", m_asserted_formulas.display(tout););
|
||||
init_search();
|
||||
for (auto const& [var, value] : m_values)
|
||||
initialize_value(var, value);
|
||||
|
||||
flet<bool> l(m_searching, true);
|
||||
TRACE("after_init_search", display(tout););
|
||||
IF_VERBOSE(2, verbose_stream() << "(smt.searching)\n";);
|
||||
|
|
|
@ -123,6 +123,7 @@ namespace smt {
|
|||
unsigned m_par_index = 0;
|
||||
bool m_internalizing_assertions = false;
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Equality & Uninterpreted functions
|
||||
|
@ -246,6 +247,16 @@ namespace smt {
|
|||
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
|
||||
|
||||
|
||||
// ----------------------------------
|
||||
//
|
||||
// Value initialization
|
||||
//
|
||||
// ----------------------------------
|
||||
vector<std::pair<expr_ref, expr_ref>> m_values;
|
||||
void initialize_value(expr* var, expr* value);
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
// Accessors
|
||||
|
@ -1777,6 +1788,8 @@ namespace smt {
|
|||
m_user_propagator->register_decide(r);
|
||||
}
|
||||
|
||||
void user_propagate_initialize_value(expr* var, expr* value);
|
||||
|
||||
bool watches_fixed(enode* n) const;
|
||||
|
||||
bool has_split_candidate(bool_var& var, bool& is_pos);
|
||||
|
|
|
@ -305,5 +305,9 @@ namespace smt {
|
|||
void kernel::user_propagate_register_decide(user_propagator::decide_eh_t& 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);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -322,6 +322,8 @@ namespace smt {
|
|||
|
||||
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.
|
||||
This breaks abstractions.
|
||||
|
|
|
@ -252,6 +252,10 @@ namespace {
|
|||
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 {
|
||||
smt_solver& s;
|
||||
expr_ref_vector m_assumptions;
|
||||
|
|
|
@ -549,6 +549,10 @@ namespace smt {
|
|||
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_preferred_eq(expr* a, expr* b);
|
||||
|
|
|
@ -41,6 +41,7 @@ class smt_tactic : public tactic {
|
|||
smt_params m_params;
|
||||
params_ref m_params_ref;
|
||||
expr_ref_vector m_vars;
|
||||
vector<std::pair<expr_ref, expr_ref>> m_values;
|
||||
statistics m_stats;
|
||||
smt::kernel* m_ctx = nullptr;
|
||||
symbol m_logic;
|
||||
|
@ -344,6 +345,8 @@ public:
|
|||
|
||||
for (expr* v : m_vars)
|
||||
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 {
|
||||
|
@ -403,6 +406,10 @@ public:
|
|||
void user_propagate_register_decide(user_propagator::decide_eh_t& decide_eh) override {
|
||||
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) {
|
||||
|
|
|
@ -662,6 +662,7 @@ namespace smt {
|
|||
|
||||
void restart_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
|
||||
check. assume_eqs, check_int_feasibility,
|
||||
|
|
|
@ -2249,6 +2249,21 @@ namespace smt {
|
|||
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
|
||||
/**
|
||||
|
|
|
@ -154,6 +154,7 @@ class theory_lra::imp {
|
|||
svector<delayed_atom> m_asserted_atoms;
|
||||
ptr_vector<expr> m_not_handled;
|
||||
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.
|
||||
|
||||
// attributes for incremental version:
|
||||
|
@ -991,6 +992,16 @@ public:
|
|||
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) {
|
||||
TRACE("arith", tout << "eq " << v1 << " == " << v2 << "\n";);
|
||||
if (!is_int(v1) && !is_real(v1))
|
||||
|
@ -1409,6 +1420,9 @@ public:
|
|||
void init_search_eh() {
|
||||
m_arith_eq_adapter.init_search_eh();
|
||||
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 {
|
||||
|
@ -3878,6 +3892,9 @@ void theory_lra::assign_eh(bool_var v, bool is_true) {
|
|||
lbool theory_lra::get_phase(bool_var 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) {
|
||||
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 {
|
||||
return m_imp->is_shared(v);
|
||||
}
|
||||
}
|
||||
bool theory_lra::can_propagate() {
|
||||
return m_imp->can_propagate();
|
||||
}
|
||||
|
|
|
@ -80,6 +80,8 @@ namespace smt {
|
|||
void apply_sort_cnstr(enode * n, sort * s) 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;
|
||||
void validate_model(proto_model& mdl) override;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue