diff --git a/src/ast/special_relations_decl_plugin.cpp b/src/ast/special_relations_decl_plugin.cpp index b45778d2f..24a756bf7 100644 --- a/src/ast/special_relations_decl_plugin.cpp +++ b/src/ast/special_relations_decl_plugin.cpp @@ -47,6 +47,7 @@ func_decl * special_relations_decl_plugin::mk_func_decl( if (!m_manager->is_bool(range)) { m_manager->raise_exception("range type is expected to be Boolean for special relations"); } + m_has_special_relation = true; func_decl_info info(m_family_id, k, num_parameters, parameters); symbol name; switch(k) { diff --git a/src/ast/special_relations_decl_plugin.h b/src/ast/special_relations_decl_plugin.h index 0c4377864..c422cbcdc 100644 --- a/src/ast/special_relations_decl_plugin.h +++ b/src/ast/special_relations_decl_plugin.h @@ -37,6 +37,7 @@ class special_relations_decl_plugin : public decl_plugin { symbol m_plo; symbol m_to; symbol m_tc; + bool m_has_special_relation = false; public: special_relations_decl_plugin(); @@ -50,6 +51,8 @@ public: void get_op_names(svector & op_names, symbol const & logic) override; sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override { return nullptr; } + + bool has_special_relation() const { return m_has_special_relation; } }; enum sr_property { @@ -82,6 +85,8 @@ class special_relations_util { } public: special_relations_util(ast_manager& m) : m(m), m_fid(null_family_id) { } + + bool has_special_relation() const { return static_cast(m.get_plugin(m.mk_family_id("specrels")))->has_special_relation(); } bool is_special_relation(func_decl* f) const { return f->get_family_id() == fid(); } bool is_special_relation(app* e) const { return is_special_relation(e->get_decl()); } diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index e55508853..2d2350494 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -28,6 +28,7 @@ Revision History: #include "ast/rewriter/rewriter_def.h" #include "ast/ast_pp.h" #include "ast/array_decl_plugin.h" +#include "ast/special_relations_decl_plugin.h" #include "ast/ast_smt2_pp.h" #include "smt/smt_model_checker.h" #include "smt/smt_context.h" @@ -358,7 +359,7 @@ namespace smt { TRACE("model_checker", tout << "[complete] model-checker result: " << to_sat_str(r) << "\n";); if (r != l_true) { - return r == l_false; // quantifier is satisfied by m_curr_model + return is_safe_for_mbqi(q) && r == l_false; // quantifier is satisfied by m_curr_model } model_ref complete_cex; @@ -398,6 +399,26 @@ namespace smt { return false; } + bool model_checker::is_safe_for_mbqi(quantifier * q) const { + special_relations_util sp(m); + if (!sp.has_special_relation()) + return true; + ast_fast_mark1 visited; + struct proc { + special_relations_util& sp; + bool found = false; + proc(special_relations_util& sp):sp(sp) {} + void operator()(app* f) { + found |= sp.is_special_relation(f); + } + void operator()(expr* e) {} + }; + proc p(sp); + quick_for_each_expr(p, visited, q); + return !p.found; + } + + void model_checker::init_aux_context() { if (!m_fparams) { m_fparams = alloc(smt_params, m_context->get_fparams()); diff --git a/src/smt/smt_model_checker.h b/src/smt/smt_model_checker.h index 6332a890e..46d51f9a0 100644 --- a/src/smt/smt_model_checker.h +++ b/src/smt/smt_model_checker.h @@ -87,6 +87,7 @@ namespace smt { expr_mark m_visited; bool contains_model_value(expr * e); void add_instance(quantifier * q, expr_ref_vector const & bindings, unsigned max_generation, expr * def); + bool is_safe_for_mbqi(quantifier * q) const; public: model_checker(ast_manager & m, qi_params const & p, model_finder & mf);