diff --git a/src/ast/sls/sls_array_plugin.cpp b/src/ast/sls/sls_array_plugin.cpp index 913e6bdcf5..70e6335fb0 100644 --- a/src/ast/sls/sls_array_plugin.cpp +++ b/src/ast/sls/sls_array_plugin.cpp @@ -166,6 +166,7 @@ namespace sls { args.push_back(nsel->get_expr()); } expr_ref f_map(m.mk_app(f, args), m); + ctx.add_new_term(f_map); auto nsel = mk_select(g, n, sel); auto nmap = g.find(f_map); if (!nmap) @@ -193,6 +194,7 @@ namespace sls { args.push_back(idx->get_expr()); } expr_ref esel(a.mk_select(args), m); + ctx.add_new_term(esel); auto n = g.find(esel); return n ? n : g.mk(esel, 0, eargs.size(), eargs.data()); } @@ -373,6 +375,11 @@ namespace sls { continue; if (p->get_arg(0)->get_root() != n->get_root()) continue; +#if 1 + bool is_relevant = any_of(euf::enode_class(p), [&](euf::enode* k) { return ctx.is_relevant(k->get_expr()); }); + if (!is_relevant) + continue; +#endif auto val = p->get_root(); kv[n].insert(select_args(p), val); } diff --git a/src/ast/sls/sls_context.cpp b/src/ast/sls/sls_context.cpp index 8ed3619e87..f0acdf4260 100644 --- a/src/ast/sls/sls_context.cpp +++ b/src/ast/sls/sls_context.cpp @@ -143,6 +143,7 @@ namespace sls { return l_undef; if (all_of(m_plugins, [&](auto* p) { return !p || p->is_sat(); })) { + VERIFY(unsat().empty() || !m_new_constraint); values2model(); return l_true; } @@ -184,11 +185,29 @@ namespace sls { throw default_exception("conflicting assignment"); } } + + validate_model(*mdl); s.on_model(mdl); // verbose_stream() << *mdl << "\n"; TRACE("sls", display(tout)); } + + void context::validate_model(model& mdl) { + model_evaluator ev(mdl); + for (sat::literal lit : root_literals()) { + auto a = atom(lit.var()); + if (!a) + continue; + auto eval_a = ev(a); + bool bad_model = (m.is_true(eval_a) && lit.sign()) || (m.is_false(eval_a) && !lit.sign()); + + if (bad_model) { + IF_VERBOSE(0, verbose_stream() << lit << " " << a->get_id() << " " << mk_bounded_pp(a, m) << " " << eval_a << "\n"); + throw default_exception("failed to create a well-formed model"); + } + } + } void context::propagate_boolean_assignment() { start_propagation: @@ -286,7 +305,7 @@ namespace sls { bool context::is_true(expr* e) { SASSERT(m.is_bool(e)); - auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var); + auto v = m_atom2bool_var.get(e->get_id(), sat::null_bool_var); if (v != sat::null_bool_var) return is_true(v); if (m.is_and(e)) @@ -342,8 +361,10 @@ namespace sls { if (m_visited.contains(id)) return false; m_visited.insert(id); - if (m_parents.size() <= id) - verbose_stream() << "not in map " << mk_bounded_pp(e, m) << "\n"; + if (m_parents.size() <= id) // expressions can be temporary created in E-graph but not registered + { + return false; + } for (auto p : m_parents[id]) { if (is_relevant(p)) { m_relevant.insert(id); @@ -353,18 +374,20 @@ namespace sls { return false; } - void context::add_constraint(expr* e) { + bool context::add_constraint(expr* e) { if (m_constraint_ids.contains(e->get_id())) - return; + return false; m_constraint_ids.insert(e->get_id()); m_constraint_trail.push_back(e); add_assertion(e, false); m_new_constraint = true; IF_VERBOSE(3, verbose_stream() << "add constraint " << mk_bounded_pp(e, m) << "\n"); ++m_stats.m_num_constraints; + return true; } void context::add_assertion(expr* f, bool is_input) { + m_new_constraint = true; expr_ref _e(f, m); expr* g, * h, * k; sat::literal_vector clause; @@ -676,7 +699,7 @@ namespace sls { has_relevant = true; break; } - if (m_rand() % ++n == 0) + if (m_rand(++n) == 0) selected_lit = lit; } if (!has_relevant && selected_lit != sat::null_literal) { diff --git a/src/ast/sls/sls_context.h b/src/ast/sls/sls_context.h index 96958ab0fa..73959e4571 100644 --- a/src/ast/sls/sls_context.h +++ b/src/ast/sls/sls_context.h @@ -159,6 +159,8 @@ namespace sls { sat::literal mk_literal(); + + void validate_model(model& mdl); public: context(ast_manager& m, sat_solver_context& s); @@ -221,7 +223,7 @@ namespace sls { bool is_true(expr* e); bool is_fixed(expr* e); bool is_relevant(expr* e); - void add_constraint(expr* e); + bool add_constraint(expr* e); ptr_vector const& subterms(); ast_manager& get_manager() { return m; } std::ostream& display(std::ostream& out) const; diff --git a/src/ast/sls/sls_euf_plugin.cpp b/src/ast/sls/sls_euf_plugin.cpp index b7c2195f08..e4745d02e6 100644 --- a/src/ast/sls/sls_euf_plugin.cpp +++ b/src/ast/sls/sls_euf_plugin.cpp @@ -52,11 +52,18 @@ namespace sls { void euf_plugin::register_term(expr* e) { if (!is_app(e)) return; - if (!is_uninterp(e)) - return; app* a = to_app(e); if (a->get_num_args() == 0) return; + if (!is_uninterp(e)) { + return; + family_id fid = a->get_family_id(); + if (fid == basic_family_id) + return; + if (all_of(*a, [&](expr* arg) { return !is_app(arg) || fid == to_app(arg)->get_family_id(); })) + return; + } + auto f = a->get_decl(); if (!m_app.contains(f)) m_app.insert(f, ptr_vector()); @@ -341,8 +348,8 @@ namespace sls { verbose_stream() << ctx.get_value(t->get_arg(i)) << " == " << ctx.get_value(u->get_arg(i)) << "\n"; #endif expr_ref fml(m.mk_or(ors), m); - ctx.add_constraint(fml); - new_constraint = true; + if (ctx.add_constraint(fml)) + new_constraint = true; } else @@ -368,8 +375,8 @@ namespace sls { } // distinct(a, b, c) or a = b or a = c or b = c eqs.push_back(e); - ctx.add_constraint(m.mk_or(eqs)); - new_constraint = true; + if (ctx.add_constraint(m.mk_or(eqs))) + new_constraint = true; done_distinct: ; }