1 /*++ 2 Copyright (c) 2006 Microsoft Corporation 3 4 Module Name: 5 6 smt_model_finder.cpp 7 8 Abstract: 9 10 Model finding goodies for universally quantified formulas. 11 12 Author: 13 14 Leonardo de Moura (leonardo) 2010-12-17. 15 16 Revision History: 17 18 --*/ 19 #include "util/backtrackable_set.h" 20 #include "ast/ast_util.h" 21 #include "ast/macros/macro_util.h" 22 #include "ast/arith_decl_plugin.h" 23 #include "ast/bv_decl_plugin.h" 24 #include "ast/array_decl_plugin.h" 25 #include "ast/normal_forms/pull_quant.h" 26 #include "ast/rewriter/var_subst.h" 27 #include "ast/macros/cond_macro.h" 28 #include "ast/macros/quantifier_macro_info.h" 29 #include "ast/for_each_expr.h" 30 #include "ast/ast_pp.h" 31 #include "ast/ast_ll_pp.h" 32 #include "ast/well_sorted.h" 33 #include "ast/ast_smt2_pp.h" 34 #include "model/model_pp.h" 35 #include "model/model_macro_solver.h" 36 #include "smt/smt_model_finder.h" 37 #include "smt/smt_context.h" 38 #include "tactic/tactic_exception.h" 39 40 namespace smt { 41 42 namespace mf { 43 44 // ----------------------------------- 45 // 46 // Auxiliary stuff 47 // 48 // ----------------------------------- 49 50 51 class evaluator { 52 public: 53 virtual expr* eval(expr* n, bool model_completion) = 0; 54 }; 55 56 // ----------------------------------- 57 // 58 // Instantiation sets 59 // 60 // ----------------------------------- 61 62 /** 63 \brief Instantiation sets are the S_{k,j} sets in the Complete quantifier instantiation paper. 64 */ 65 class instantiation_set { 66 ast_manager& m; 67 obj_map<expr, unsigned> m_elems; // and the associated generation 68 obj_map<expr, expr*> m_inv; 69 expr_mark m_visited; 70 public: instantiation_set(ast_manager & m)71 instantiation_set(ast_manager& m) :m(m) {} 72 ~instantiation_set()73 ~instantiation_set() { 74 for (auto const& kv : m_elems) { 75 m.dec_ref(kv.m_key); 76 } 77 m_elems.reset(); 78 } 79 get_elems() const80 obj_map<expr, unsigned> const& get_elems() const { return m_elems; } 81 insert(expr * n,unsigned generation)82 void insert(expr* n, unsigned generation) { 83 if (m_elems.contains(n) || contains_model_value(n)) { 84 return; 85 } 86 TRACE("model_finder", tout << mk_pp(n, m) << "\n";); 87 m.inc_ref(n); 88 m_elems.insert(n, generation); 89 SASSERT(!m.is_model_value(n)); 90 } 91 remove(expr * n)92 void remove(expr* n) { 93 // We can only remove n if it is in m_elems, AND m_inv was not initialized yet. 94 SASSERT(m_elems.contains(n)); 95 SASSERT(m_inv.empty()); 96 m_elems.erase(n); 97 TRACE("model_finder", tout << mk_pp(n, m) << "\n";); 98 m.dec_ref(n); 99 } 100 display(std::ostream & out) const101 void display(std::ostream& out) const { 102 for (auto const& kv : m_elems) { 103 out << mk_bounded_pp(kv.m_key, m) << " [" << kv.m_value << "]\n"; 104 } 105 out << "inverse:\n"; 106 for (auto const& kv : m_inv) { 107 out << mk_bounded_pp(kv.m_key, m) << " -> " << mk_bounded_pp(kv.m_value, m) << "\n"; 108 } 109 } 110 get_inv(expr * v) const111 expr* get_inv(expr* v) const { 112 expr* t = nullptr; 113 m_inv.find(v, t); 114 return t; 115 } 116 get_generation(expr * t) const117 unsigned get_generation(expr* t) const { 118 unsigned gen = 0; 119 m_elems.find(t, gen); 120 return gen; 121 } 122 mk_inverse(evaluator & ev)123 void mk_inverse(evaluator& ev) { 124 for (auto const& kv : m_elems) { 125 expr* t = kv.m_key; 126 SASSERT(!contains_model_value(t)); 127 unsigned gen = kv.m_value; 128 expr* t_val = ev.eval(t, true); 129 if (!t_val) break; 130 TRACE("model_finder", tout << mk_pp(t, m) << " " << mk_pp(t_val, m) << "\n";); 131 132 expr* old_t = nullptr; 133 if (m_inv.find(t_val, old_t)) { 134 unsigned old_t_gen = 0; 135 SASSERT(m_elems.contains(old_t)); 136 m_elems.find(old_t, old_t_gen); 137 if (gen < old_t_gen) { 138 m_inv.insert(t_val, t); 139 } 140 } 141 else { 142 m_inv.insert(t_val, t); 143 } 144 } 145 } 146 get_inv_map() const147 obj_map<expr, expr*> const& get_inv_map() const { 148 return m_inv; 149 } 150 151 struct is_model_value {}; operator ()(expr * n)152 void operator()(expr* n) { 153 if (m.is_model_value(n)) { 154 throw is_model_value(); 155 } 156 } 157 contains_model_value(expr * n)158 bool contains_model_value(expr* n) { 159 if (m.is_model_value(n)) { 160 return true; 161 } 162 if (is_app(n) && to_app(n)->get_num_args() == 0) { 163 return false; 164 } 165 m_visited.reset(); 166 try { 167 for_each_expr(*this, m_visited, n); 168 } 169 catch (const is_model_value&) { 170 return true; 171 } 172 return false; 173 } 174 }; 175 176 177 /** 178 During model construction time, 179 we solve several constraints that impose restrictions 180 on how the model for the ground formulas may be extended to 181 a model to the relevant universal quantifiers. 182 183 The class node and its subclasses are used to solve 184 these constraints. 185 */ 186 187 /** 188 \brief Base class used to solve model construction constraints. 189 */ 190 class node { 191 unsigned m_id; 192 node* m_find{ nullptr }; 193 unsigned m_eqc_size{ 1 }; 194 195 sort* m_sort; // sort of the elements in the instantiation set. 196 197 bool m_mono_proj{ false }; // relevant for integers & reals & bit-vectors 198 bool m_signed_proj{ false }; // relevant for bit-vectors. 199 ptr_vector<node> m_avoid_set; 200 ptr_vector<expr> m_exceptions; 201 202 scoped_ptr<instantiation_set> m_set; 203 expr* m_else{ nullptr }; 204 func_decl* m_proj{ nullptr }; 205 206 // Append the new elements of v2 into v1. v2 should not be used after this operation, since it may suffer destructive updates. 207 template<typename T> dappend(ptr_vector<T> & v1,ptr_vector<T> & v2)208 void dappend(ptr_vector<T>& v1, ptr_vector<T>& v2) { 209 if (v2.empty()) 210 return; 211 if (v1.empty()) { 212 v1.swap(v2); 213 return; 214 } 215 for (T* t : v2) { 216 if (!v1.contains(t)) 217 v1.push_back(t); 218 } 219 v2.finalize(); 220 } 221 public: node(unsigned id,sort * s)222 node(unsigned id, sort* s) : 223 m_id(id), 224 m_sort(s) { 225 } 226 ~node()227 ~node() {} 228 get_id() const229 unsigned get_id() const { return m_id; } 230 get_sort() const231 sort* get_sort() const { return m_sort; } 232 is_root() const233 bool is_root() const { return m_find == nullptr; } 234 get_root() const235 node* get_root() const { 236 node* curr = const_cast<node*>(this); 237 while (!curr->is_root()) { 238 curr = curr->m_find; 239 } 240 SASSERT(curr->is_root()); 241 return curr; 242 } 243 merge(node * other)244 void merge(node* other) { 245 node* r1 = get_root(); 246 node* r2 = other->get_root(); 247 SASSERT(!r1->m_set); 248 SASSERT(!r2->m_set); 249 SASSERT(r1->get_sort() == r2->get_sort()); 250 if (r1 == r2) 251 return; 252 if (r1->m_eqc_size > r2->m_eqc_size) 253 std::swap(r1, r2); 254 r1->m_find = r2; 255 r2->m_eqc_size += r1->m_eqc_size; 256 r2->m_mono_proj |= r1->m_mono_proj; 257 r2->m_signed_proj |= r1->m_signed_proj; 258 dappend(r2->m_avoid_set, r1->m_avoid_set); 259 dappend(r2->m_exceptions, r1->m_exceptions); 260 } 261 insert_avoid(node * n)262 void insert_avoid(node* n) { 263 ptr_vector<node>& as = get_root()->m_avoid_set; 264 if (!as.contains(n)) 265 as.push_back(n); 266 } 267 insert_exception(expr * n)268 void insert_exception(expr* n) { 269 ptr_vector<expr>& ex = get_root()->m_exceptions; 270 if (!ex.contains(n)) 271 ex.push_back(n); 272 } 273 set_mono_proj()274 void set_mono_proj() { 275 get_root()->m_mono_proj = true; 276 } 277 is_mono_proj() const278 bool is_mono_proj() const { 279 return get_root()->m_mono_proj; 280 } 281 set_signed_proj()282 void set_signed_proj() { 283 get_root()->m_signed_proj = true; 284 } 285 is_signed_proj() const286 bool is_signed_proj() const { 287 return get_root()->m_signed_proj; 288 } 289 mk_instantiation_set(ast_manager & m)290 void mk_instantiation_set(ast_manager& m) { 291 SASSERT(is_root()); 292 SASSERT(!m_set); 293 m_set = alloc(instantiation_set, m); 294 } 295 insert(expr * n,unsigned generation)296 void insert(expr* n, unsigned generation) { 297 SASSERT(is_ground(n)); 298 get_root()->m_set->insert(n, generation); 299 } 300 display(std::ostream & out,ast_manager & m) const301 void display(std::ostream& out, ast_manager& m) const { 302 if (is_root()) { 303 out << "root node ------\n"; 304 out << "@" << m_id << " mono: " << m_mono_proj << " signed: " << m_signed_proj << ", sort: " << mk_pp(m_sort, m) << "\n"; 305 out << "avoid-set: "; 306 for (node* n : m_avoid_set) { 307 out << "@" << n->get_root()->get_id() << " "; 308 } 309 out << "\n"; 310 out << "exceptions: "; 311 for (expr* e : m_exceptions) { 312 out << mk_bounded_pp(e, m) << " "; 313 } 314 out << "\n"; 315 if (m_else) 316 out << "else: " << mk_pp(m_else, m, 6) << "\n"; 317 if (m_proj) 318 out << "projection: " << m_proj->get_name() << "\n"; 319 if (m_set) { 320 out << "instantiation-set:\n"; 321 m_set->display(out); 322 } 323 out << "----------------\n"; 324 } 325 else { 326 out << "@" << m_id << " -> @" << get_root()->get_id() << "\n"; 327 } 328 } 329 get_instantiation_set() const330 instantiation_set const* get_instantiation_set() const { return get_root()->m_set.get(); } 331 get_instantiation_set()332 instantiation_set* get_instantiation_set() { return get_root()->m_set.get(); } 333 get_exceptions() const334 ptr_vector<expr> const& get_exceptions() const { return get_root()->m_exceptions; } 335 get_avoid_set() const336 ptr_vector<node> const& get_avoid_set() const { return get_root()->m_avoid_set; } 337 338 // return true if m_avoid_set.contains(this) must_avoid_itself() const339 bool must_avoid_itself() const { 340 node* r = get_root(); 341 for (node* n : m_avoid_set) { 342 if (r == n->get_root()) 343 return true; 344 } 345 return false; 346 } 347 set_else(expr * e)348 void set_else(expr* e) { 349 SASSERT(!is_mono_proj()); 350 SASSERT(get_root()->m_else == nullptr); 351 get_root()->m_else = e; 352 } 353 get_else() const354 expr* get_else() const { 355 return get_root()->m_else; 356 } 357 set_proj(func_decl * f)358 void set_proj(func_decl* f) { 359 SASSERT(get_root()->m_proj == nullptr); 360 get_root()->m_proj = f; 361 } 362 get_proj() const363 func_decl* get_proj() const { 364 return get_root()->m_proj; 365 } 366 }; 367 368 369 typedef std::pair<ast*, unsigned> ast_idx_pair; 370 typedef pair_hash<obj_ptr_hash<ast>, unsigned_hash> ast_idx_pair_hash; 371 typedef map<ast_idx_pair, node*, ast_idx_pair_hash, default_eq<ast_idx_pair> > key2node; 372 373 374 /** 375 \brief Auxiliary class for processing the "Almost uninterpreted fragment" described in the paper: 376 Complete instantiation for quantified SMT formulas 377 378 The idea is to create node objects based on the information produced by the quantifier_analyzer. 379 */ 380 class auf_solver : public evaluator { 381 ast_manager& m; 382 arith_util m_arith; 383 bv_util m_bv; 384 array_util m_array; 385 ptr_vector<node> m_nodes; 386 unsigned m_next_node_id{ 0 }; 387 key2node m_uvars; 388 key2node m_A_f_is; 389 390 // Mapping from sort to auxiliary constant. 391 // This auxiliary constant is used as a "witness" that is asserted as different from a 392 // finite number of terms. 393 // It is only safe to use this constant for infinite sorts. 394 obj_map<sort, app*> m_sort2k; 395 expr_ref_vector m_ks; // range of m_sort2k 396 397 // Support for evaluating expressions in the current model. 398 proto_model* m_model{ nullptr }; 399 obj_map<expr, expr*> m_eval_cache[2]; 400 expr_ref_vector m_eval_cache_range; 401 402 ptr_vector<node> m_root_nodes; 403 404 expr_ref_vector* m_new_constraints{ nullptr }; 405 random_gen m_rand; 406 407 reset_sort2k()408 void reset_sort2k() { 409 m_sort2k.reset(); 410 m_ks.reset(); 411 } 412 reset_eval_cache()413 void reset_eval_cache() { 414 m_eval_cache[0].reset(); 415 m_eval_cache[1].reset(); 416 m_eval_cache_range.reset(); 417 } 418 mk_node(key2node & map,ast * n,unsigned i,sort * s)419 node* mk_node(key2node& map, ast* n, unsigned i, sort* s) { 420 node* r = nullptr; 421 ast_idx_pair k(n, i); 422 if (map.find(k, r)) { 423 SASSERT(r->get_sort() == s); 424 return r; 425 } 426 r = alloc(node, m_next_node_id, s); 427 m_next_node_id++; 428 map.insert(k, r); 429 m_nodes.push_back(r); 430 return r; 431 } 432 display_key2node(std::ostream & out,key2node const & m) const433 void display_key2node(std::ostream& out, key2node const& m) const { 434 for (auto const& kv : m) { 435 ast* a = kv.m_key.first; 436 unsigned i = kv.m_key.second; 437 node* n = kv.m_value; 438 out << "#" << a->get_id() << ":" << i << " -> @" << n->get_id() << "\n"; 439 } 440 } 441 display_A_f_is(std::ostream & out) const442 void display_A_f_is(std::ostream& out) const { 443 for (auto const& kv : m_A_f_is) { 444 func_decl* f = static_cast<func_decl*>(kv.m_key.first); 445 unsigned i = kv.m_key.second; 446 node* n = kv.m_value; 447 out << f->get_name() << ":" << i << " -> @" << n->get_id() << "\n"; 448 } 449 } 450 flush_nodes()451 void flush_nodes() { 452 std::for_each(m_nodes.begin(), m_nodes.end(), delete_proc<node>()); 453 } 454 455 public: auf_solver(ast_manager & m)456 auf_solver(ast_manager& m) : 457 m(m), 458 m_arith(m), 459 m_bv(m), 460 m_array(m), 461 m_ks(m), 462 m_eval_cache_range(m), 463 m_rand(static_cast<unsigned>(m.limit().count())) { 464 m.limit().inc(); 465 } 466 ~auf_solver()467 virtual ~auf_solver() { 468 flush_nodes(); 469 reset_eval_cache(); 470 } 471 get_manager() const472 ast_manager& get_manager() const { return m; } 473 reset()474 void reset() { 475 flush_nodes(); 476 m_nodes.reset(); 477 m_next_node_id = 0; 478 m_uvars.reset(); 479 m_A_f_is.reset(); 480 m_root_nodes.reset(); 481 reset_sort2k(); 482 } 483 set_model(proto_model * m)484 void set_model(proto_model* m) { 485 reset_eval_cache(); 486 m_model = m; 487 } 488 get_model() const489 proto_model* get_model() const { 490 SASSERT(m_model); 491 return m_model; 492 } 493 get_uvar(quantifier * q,unsigned i)494 node* get_uvar(quantifier* q, unsigned i) { 495 SASSERT(i < q->get_num_decls()); 496 sort* s = q->get_decl_sort(q->get_num_decls() - i - 1); 497 return mk_node(m_uvars, q, i, s); 498 } 499 get_A_f_i(func_decl * f,unsigned i)500 node* get_A_f_i(func_decl* f, unsigned i) { 501 SASSERT(i < f->get_arity()); 502 sort* s = f->get_domain(i); 503 return mk_node(m_A_f_is, f, i, s); 504 } 505 get_uvar_inst_set(quantifier * q,unsigned i) const506 instantiation_set const* get_uvar_inst_set(quantifier* q, unsigned i) const { 507 ast_idx_pair k(q, i); 508 node* r = nullptr; 509 if (m_uvars.find(k, r)) 510 return r->get_instantiation_set(); 511 return nullptr; 512 } 513 mk_instantiation_sets()514 void mk_instantiation_sets() { 515 for (node* curr : m_nodes) { 516 if (curr->is_root()) { 517 curr->mk_instantiation_set(m); 518 } 519 } 520 } 521 522 // For each instantiation_set, remove entries that do not evaluate to values. 523 ptr_vector<expr> to_delete; 524 cleanup_instantiation_sets()525 void cleanup_instantiation_sets() { 526 for (node* curr : m_nodes) { 527 if (curr->is_root()) { 528 instantiation_set* s = curr->get_instantiation_set(); 529 to_delete.reset(); 530 obj_map<expr, unsigned> const& elems = s->get_elems(); 531 for (auto const& kv : elems) { 532 expr* n = kv.m_key; 533 expr* n_val = eval(n, true); 534 if (!n_val || (!m.is_value(n_val) && !m_array.is_array(n_val))) { 535 to_delete.push_back(n); 536 } 537 } 538 for (expr* e : to_delete) { 539 s->remove(e); 540 } 541 } 542 } 543 } 544 display_nodes(std::ostream & out) const545 void display_nodes(std::ostream& out) const { 546 display_key2node(out, m_uvars); 547 display_A_f_is(out); 548 for (node* n : m_nodes) { 549 n->display(out, m); 550 } 551 } 552 eval(expr * n,bool model_completion)553 expr* eval(expr* n, bool model_completion) override { 554 expr* r = nullptr; 555 if (m_eval_cache[model_completion].find(n, r)) { 556 return r; 557 } 558 expr_ref tmp(m); 559 if (!m_model->eval(n, tmp, model_completion)) { 560 r = nullptr; 561 TRACE("model_finder", tout << "eval\n" << mk_pp(n, m) << "\n-----> null\n";); 562 } 563 else { 564 r = tmp; 565 TRACE("model_finder", tout << "eval\n" << mk_pp(n, m) << "\n----->\n" << mk_pp(r, m) << "\n";); 566 } 567 m_eval_cache[model_completion].insert(n, r); 568 m_eval_cache_range.push_back(r); 569 return r; 570 } 571 private: 572 573 /** 574 \brief Collect the interpretations of n->get_exceptions() 575 and the interpretations of the m_else of nodes in n->get_avoid_set() 576 */ collect_exceptions_values(node * n,ptr_buffer<expr> & r)577 void collect_exceptions_values(node* n, ptr_buffer<expr>& r) { 578 579 for (expr* e : n->get_exceptions()) { 580 expr* val = eval(e, true); 581 if (val) 582 r.push_back(val); 583 } 584 585 for (node* a : n->get_avoid_set()) { 586 node* p = a->get_root(); 587 if (!p->is_mono_proj() && p->get_else() != nullptr) { 588 expr* val = eval(p->get_else(), true); 589 if (val) 590 r.push_back(val); 591 } 592 } 593 } 594 595 /** 596 \brief Return an expr t from the instantiation set of \c n s.t. forall e in n.get_exceptions() 597 eval(t) != eval(e) and forall m in n.get_avoid_set() eval(t) != eval(m.get_else()) 598 If there t1 and t2 satisfying this condition, break ties using the generation of them. 599 600 Return 0 if such t does not exist. 601 */ pick_instance_diff_exceptions(node * n,ptr_buffer<expr> const & ex_vals)602 expr* pick_instance_diff_exceptions(node* n, ptr_buffer<expr> const& ex_vals) { 603 instantiation_set const* s = n->get_instantiation_set(); 604 obj_map<expr, unsigned> const& elems = s->get_elems(); 605 606 expr* t_result = nullptr; 607 unsigned gen_result = UINT_MAX; 608 for (auto const& kv : elems) { 609 expr* t = kv.m_key; 610 unsigned gen = kv.m_value; 611 expr* t_val = eval(t, true); 612 if (!t_val) 613 return t_result; 614 bool found = false; 615 for (expr* v : ex_vals) { 616 if (!m.are_distinct(t_val, v)) { 617 found = true; 618 break; 619 } 620 } 621 if (!found && (t_result == nullptr || gen < gen_result)) { 622 t_result = t; 623 gen_result = gen; 624 } 625 } 626 return t_result; 627 } 628 629 // we should not assume that uninterpreted sorts are infinite in benchmarks with quantifiers. is_infinite(sort * s) const630 bool is_infinite(sort* s) const { return !m.is_uninterp(s) && s->is_infinite(); } 631 632 /** 633 \brief Return a fresh constant k that is used as a witness for elements that must be different from 634 a set of values. 635 */ get_k_for(sort * s)636 app* get_k_for(sort* s) { 637 SASSERT(is_infinite(s)); 638 app* r = nullptr; 639 if (m_sort2k.find(s, r)) 640 return r; 641 r = m.mk_fresh_const("k", s); 642 m_model->register_aux_decl(r->get_decl()); 643 m_sort2k.insert(s, r); 644 m_ks.push_back(r); 645 TRACE("model_finder", tout << sort_ref(s, m) << " := " << "\n";); 646 return r; 647 } 648 649 /** 650 \brief Get the interpretation for k in m_model. 651 If m_model does not provide an interpretation for k, then 652 create a fresh one. 653 654 Remark: this method uses get_fresh_value, so it may fail. 655 */ get_k_interp(app * k)656 expr* get_k_interp(app* k) { 657 sort* s = m.get_sort(k); 658 SASSERT(is_infinite(s)); 659 func_decl* k_decl = k->get_decl(); 660 expr* r = m_model->get_const_interp(k_decl); 661 if (r != nullptr) 662 return r; 663 r = m_model->get_fresh_value(s); 664 if (r == nullptr) 665 return nullptr; 666 m_model->register_decl(k_decl, r); 667 SASSERT(m_model->get_const_interp(k_decl) == r); 668 TRACE("model_finder", tout << mk_pp(r, m) << "\n";); 669 return r; 670 } 671 672 /** 673 \brief Assert k to be different from the set of exceptions. 674 675 It invokes get_k_interp that may fail. 676 */ assert_k_diseq_exceptions(app * k,ptr_vector<expr> const & exceptions)677 bool assert_k_diseq_exceptions(app* k, ptr_vector<expr> const& exceptions) { 678 TRACE("assert_k_diseq_exceptions", tout << "assert_k_diseq_exceptions, " << "k: " << mk_pp(k, m) << "\nexceptions:\n"; 679 for (expr* e : exceptions) tout << mk_pp(e, m) << "\n";); 680 expr* k_interp = get_k_interp(k); 681 if (k_interp == nullptr) 682 return false; 683 for (expr* ex : exceptions) { 684 expr* ex_val = eval(ex, true); 685 if (ex_val && !m.are_distinct(k_interp, ex_val)) { 686 SASSERT(m_new_constraints); 687 // This constraint cannot be asserted into m_context during model construction. 688 // We must save it, and assert it during a restart. 689 m_new_constraints->push_back(m.mk_not(m.mk_eq(k, ex))); 690 } 691 } 692 return true; 693 } 694 set_projection_else(node * n)695 void set_projection_else(node* n) { 696 TRACE("model_finder", n->display(tout, m);); 697 SASSERT(n->is_root()); 698 SASSERT(!n->is_mono_proj()); 699 instantiation_set const* s = n->get_instantiation_set(); 700 ptr_vector<expr> const& exceptions = n->get_exceptions(); 701 ptr_vector<node> const& avoid_set = n->get_avoid_set(); 702 obj_map<expr, unsigned> const& elems = s->get_elems(); 703 if (elems.empty()) return; 704 if (!exceptions.empty() || !avoid_set.empty()) { 705 ptr_buffer<expr> ex_vals; 706 collect_exceptions_values(n, ex_vals); 707 expr* e = pick_instance_diff_exceptions(n, ex_vals); 708 if (e != nullptr) { 709 n->set_else(e); 710 return; 711 } 712 sort* s = n->get_sort(); 713 TRACE("model_finder", tout << "trying to create k for " << mk_pp(s, m) << ", is_infinite: " << is_infinite(s) << "\n";); 714 if (is_infinite(s)) { 715 app* k = get_k_for(s); 716 if (assert_k_diseq_exceptions(k, exceptions)) { 717 n->insert(k, 0); // add k to the instantiation set 718 n->set_else(k); 719 return; 720 } 721 } 722 // TBD: add support for the else of bitvectors. 723 // Idea: get the term t with the minimal interpretation and use t - 1. 724 } 725 n->set_else((*(elems.begin())).m_key); 726 } 727 728 /** 729 \brief If m_mono_proj is true and n is int or bv, then for each e in n->get_exceptions(), 730 we must add e-1 and e+1 to the instantiation set. 731 If sort->get_sort() is real, then we do nothing and hope for the best. 732 */ add_mono_exceptions(node * n)733 void add_mono_exceptions(node* n) { 734 SASSERT(n->is_mono_proj()); 735 sort* s = n->get_sort(); 736 arith_rewriter arw(m); 737 bv_rewriter brw(m); 738 ptr_vector<expr> const& exceptions = n->get_exceptions(); 739 expr_ref e_minus_1(m), e_plus_1(m); 740 if (m_arith.is_int(s)) { 741 expr_ref one(m_arith.mk_int(1), m); 742 arith_rewriter arith_rw(m); 743 for (expr* e : exceptions) { 744 arith_rw.mk_sub(e, one, e_minus_1); 745 arith_rw.mk_add(e, one, e_plus_1); 746 TRACE("mf_simp_bug", tout << "e:\n" << mk_ismt2_pp(e, m) << "\none:\n" << mk_ismt2_pp(one, m) << "\n";); 747 // Note: exceptions come from quantifiers bodies. So, they have generation 0. 748 n->insert(e_plus_1, 0); 749 n->insert(e_minus_1, 0); 750 } 751 } 752 else if (m_bv.is_bv_sort(s)) { 753 expr_ref one(m_bv.mk_numeral(rational(1), s), m); 754 bv_rewriter bv_rw(m); 755 for (expr* e : exceptions) { 756 bv_rw.mk_add(e, one, e_plus_1); 757 bv_rw.mk_sub(e, one, e_minus_1); 758 TRACE("mf_simp_bug", tout << "e:\n" << mk_ismt2_pp(e, m) << "\none:\n" << mk_ismt2_pp(one, m) << "\n";); 759 // Note: exceptions come from quantifiers bodies. So, they have generation 0. 760 n->insert(e_plus_1, 0); 761 n->insert(e_minus_1, 0); 762 } 763 } 764 else { 765 return; 766 } 767 } 768 get_instantiation_set_values(node * n,ptr_buffer<expr> & values)769 void get_instantiation_set_values(node* n, ptr_buffer<expr>& values) { 770 instantiation_set const* s = n->get_instantiation_set(); 771 obj_hashtable<expr> already_found; 772 obj_map<expr, unsigned> const& elems = s->get_elems(); 773 for (auto const& kv : elems) { 774 expr* t = kv.m_key; 775 expr* t_val = eval(t, true); 776 if (t_val && !already_found.contains(t_val)) { 777 values.push_back(t_val); 778 already_found.insert(t_val); 779 } 780 } 781 TRACE("model_finder_bug", tout << "values for the instantiation_set of @" << n->get_id() << "\n"; 782 for (expr* v : values) { 783 tout << mk_pp(v, m) << "\n"; 784 }); 785 } 786 787 template<class T> 788 struct numeral_lt { 789 T& m_util; numeral_ltsmt::mf::auf_solver::numeral_lt790 numeral_lt(T& a) : m_util(a) {} operator ()smt::mf::auf_solver::numeral_lt791 bool operator()(expr* e1, expr* e2) { 792 rational v1, v2; 793 if (m_util.is_numeral(e1, v1) && m_util.is_numeral(e2, v2)) { 794 return v1 < v2; 795 } 796 else { 797 return e1->get_id() < e2->get_id(); 798 } 799 } 800 }; 801 802 803 struct signed_bv_lt { 804 bv_util& m_bv; 805 unsigned m_bv_size; signed_bv_ltsmt::mf::auf_solver::signed_bv_lt806 signed_bv_lt(bv_util& bv, unsigned sz) :m_bv(bv), m_bv_size(sz) {} operator ()smt::mf::auf_solver::signed_bv_lt807 bool operator()(expr* e1, expr* e2) { 808 rational v1, v2; 809 if (m_bv.is_numeral(e1, v1) && m_bv.is_numeral(e2, v2)) { 810 v1 = m_bv.norm(v1, m_bv_size, true); 811 v2 = m_bv.norm(v2, m_bv_size, true); 812 return v1 < v2; 813 } 814 else { 815 return e1->get_id() < e2->get_id(); 816 } 817 } 818 }; 819 sort_values(node * n,ptr_buffer<expr> & values)820 void sort_values(node* n, ptr_buffer<expr>& values) { 821 sort* s = n->get_sort(); 822 if (m_arith.is_int(s) || m_arith.is_real(s)) { 823 std::sort(values.begin(), values.end(), numeral_lt<arith_util>(m_arith)); 824 } 825 else if (!n->is_signed_proj()) { 826 std::sort(values.begin(), values.end(), numeral_lt<bv_util>(m_bv)); 827 } 828 else { 829 std::sort(values.begin(), values.end(), signed_bv_lt(m_bv, m_bv.get_bv_size(s))); 830 } 831 } 832 mk_mono_proj(node * n)833 void mk_mono_proj(node* n) { 834 add_mono_exceptions(n); 835 ptr_buffer<expr> values; 836 get_instantiation_set_values(n, values); 837 if (values.empty()) return; 838 sort_values(n, values); 839 sort* s = n->get_sort(); 840 bool is_arith = m_arith.is_int(s) || m_arith.is_real(s); 841 bool is_signed = n->is_signed_proj(); 842 unsigned sz = values.size(); 843 SASSERT(sz > 0); 844 expr* pi = values[sz - 1]; 845 expr_ref var(m); 846 var = m.mk_var(0, s); 847 for (unsigned i = sz - 1; i >= 1; i--) { 848 expr_ref c(m); 849 if (is_arith) 850 c = m_arith.mk_lt(var, values[i]); 851 else if (!is_signed) 852 c = m.mk_not(m_bv.mk_ule(values[i], var)); 853 else 854 c = m.mk_not(m_bv.mk_sle(values[i], var)); 855 pi = m.mk_ite(c, values[i - 1], pi); 856 } 857 func_interp* rpi = alloc(func_interp, m, 1); 858 rpi->set_else(pi); 859 func_decl* p = m.mk_fresh_func_decl(1, &s, s); 860 m_model->register_aux_decl(p, rpi); 861 n->set_proj(p); 862 TRACE("model_finder", n->display(tout << p->get_name() << "\n", m);); 863 } 864 mk_simple_proj(node * n)865 void mk_simple_proj(node* n) { 866 set_projection_else(n); 867 ptr_buffer<expr> values; 868 get_instantiation_set_values(n, values); 869 sort* s = n->get_sort(); 870 func_decl* p = m.mk_fresh_func_decl(1, &s, s); 871 func_interp* pi = alloc(func_interp, m, 1); 872 m_model->register_aux_decl(p, pi); 873 if (n->get_else()) { 874 expr* else_val = eval(n->get_else(), true); 875 if (else_val) 876 pi->set_else(else_val); 877 } 878 for (expr* v : values) { 879 pi->insert_new_entry(&v, v); 880 } 881 n->set_proj(p); 882 TRACE("model_finder", n->display(tout << p->get_name() << "\n", m);); 883 } 884 mk_projections()885 void mk_projections() { 886 for (node* n : m_root_nodes) { 887 SASSERT(n->is_root()); 888 if (n->is_mono_proj()) 889 mk_mono_proj(n); 890 else 891 mk_simple_proj(n); 892 } 893 } 894 895 /** 896 \brief Store in r the partial functions that have A_f_i nodes. 897 */ collect_partial_funcs(func_decl_set & r)898 void collect_partial_funcs(func_decl_set& r) { 899 for (auto const& kv : m_A_f_is) { 900 func_decl* f = to_func_decl(kv.m_key.first); 901 if (!r.contains(f)) { 902 func_interp* fi = m_model->get_func_interp(f); 903 if (fi == nullptr) { 904 fi = alloc(func_interp, m, f->get_arity()); 905 TRACE("model_finder", tout << "register " << f->get_name() << "\n";); 906 m_model->register_decl(f, fi); 907 SASSERT(fi->is_partial()); 908 } 909 if (fi->is_partial()) { 910 r.insert(f); 911 } 912 } 913 } 914 } 915 916 /** 917 \brief Make sorts associated with nodes that must avoid themselves finite. 918 Only uninterpreted sorts are considered. 919 This is a trick to be able to handle atoms of the form X = Y 920 where X and Y are variables. See paper "Complete Quantifier Instantiation" 921 for more details. 922 */ mk_sorts_finite()923 void mk_sorts_finite() { 924 for (node* n : m_root_nodes) { 925 SASSERT(n->is_root()); 926 sort* s = n->get_sort(); 927 if (m.is_uninterp(s) && 928 // Making all uninterpreted sorts finite. 929 // n->must_avoid_itself() && 930 !m_model->is_finite(s)) { 931 m_model->freeze_universe(s); 932 } 933 } 934 } 935 add_elem_to_empty_inst_sets()936 void add_elem_to_empty_inst_sets() { 937 obj_map<sort, expr*> sort2elems; 938 ptr_vector<node> need_fresh; 939 for (node* n : m_root_nodes) { 940 SASSERT(n->is_root()); 941 instantiation_set const* s = n->get_instantiation_set(); 942 TRACE("model_finder", s->display(tout);); 943 obj_map<expr, unsigned> const& elems = s->get_elems(); 944 if (elems.empty()) { 945 // The method get_some_value cannot be used if n->get_sort() is an uninterpreted sort or is a sort built using uninterpreted sorts 946 // (e.g., (Array S S) where S is uninterpreted). The problem is that these sorts do not have a fixed interpretation. 947 // Moreover, a model assigns an arbitrary interpretation to these sorts using "model_values" a model value. 948 // If these module values "leak" inside the logical context, they may affect satisfiability. 949 // 950 sort* ns = n->get_sort(); 951 if (m.is_fully_interp(ns)) { 952 n->insert(m_model->get_some_value(ns), 0); 953 } 954 else { 955 need_fresh.push_back(n); 956 } 957 } 958 else { 959 sort2elems.insert(n->get_sort(), elems.begin()->m_key); 960 } 961 } 962 expr_ref_vector trail(m); 963 for (node* n : need_fresh) { 964 expr* e; 965 sort* s = n->get_sort(); 966 if (!sort2elems.find(s, e)) { 967 e = m.mk_fresh_const("elem", s); 968 trail.push_back(e); 969 sort2elems.insert(s, e); 970 } 971 n->insert(e, 0); 972 TRACE("model_finder", tout << "fresh constant: " << mk_pp(e, m) << "\n";); 973 } 974 } 975 976 /** 977 \brief Store in m_root_nodes the roots from m_nodes. 978 */ collect_root_nodes()979 void collect_root_nodes() { 980 m_root_nodes.reset(); 981 for (node* n : m_nodes) { 982 if (n->is_root()) 983 m_root_nodes.push_back(n); 984 } 985 } 986 987 /** 988 \brief Return the projection function for f at argument i. 989 Return 0, if there is none. 990 991 \remark This method assumes that mk_projections was already 992 invoked. 993 994 \remark f may have a non partial interpretation on m_model. 995 This may happen because the evaluator uses model_completion. 996 In the beginning of fix_model() we collected all f with 997 partial interpretations. During the process of computing the 998 projections we used the evaluator with model_completion, 999 and it may have fixed the "else" case of some partial interpretations. 1000 This is ok, because in the "limit" the "else" of the interpretation 1001 is irrelevant after the projections are applied. 1002 */ get_f_i_proj(func_decl * f,unsigned i)1003 func_decl* get_f_i_proj(func_decl* f, unsigned i) { 1004 node* r = nullptr; 1005 ast_idx_pair k(f, i); 1006 if (!m_A_f_is.find(k, r)) 1007 return nullptr; 1008 return r->get_proj(); 1009 } 1010 1011 /** 1012 \brief Complete the interpretation of the functions that were 1013 collected in the beginning of fix_model(). 1014 */ complete_partial_funcs(func_decl_set const & partial_funcs)1015 void complete_partial_funcs(func_decl_set const& partial_funcs) { 1016 for (func_decl* f : partial_funcs) { 1017 // Complete the current interpretation 1018 m_model->complete_partial_func(f, true); 1019 1020 unsigned arity = f->get_arity(); 1021 func_interp* fi = m_model->get_func_interp(f); 1022 if (fi->is_constant()) 1023 continue; // there is no point in using the projection for fi, since fi is the constant function. 1024 1025 expr_ref_vector args(m); 1026 bool has_proj = false; 1027 for (unsigned i = 0; i < arity; i++) { 1028 var* v = m.mk_var(i, f->get_domain(i)); 1029 func_decl* pi = get_f_i_proj(f, i); 1030 if (pi != nullptr) { 1031 args.push_back(m.mk_app(pi, v)); 1032 has_proj = true; 1033 } 1034 else { 1035 args.push_back(v); 1036 } 1037 } 1038 if (has_proj) { 1039 // f_aux will be assigned to the old interpretation of f. 1040 func_decl* f_aux = m.mk_fresh_func_decl(f->get_name(), symbol::null, arity, f->get_domain(), f->get_range()); 1041 func_interp* new_fi = alloc(func_interp, m, arity); 1042 new_fi->set_else(m.mk_app(f_aux, args.size(), args.c_ptr())); 1043 TRACE("model_finder", tout << "Setting new interpretation for " << f->get_name() << "\n" << 1044 mk_pp(new_fi->get_else(), m) << "\n"; 1045 tout << "old interpretation: " << mk_pp(fi->get_interp(), m) << "\n";); 1046 m_model->reregister_decl(f, new_fi, f_aux); 1047 } 1048 } 1049 } 1050 mk_inverse(node * n)1051 void mk_inverse(node* n) { 1052 SASSERT(n->is_root()); 1053 instantiation_set* s = n->get_instantiation_set(); 1054 s->mk_inverse(*this); 1055 } 1056 mk_inverses()1057 void mk_inverses() { 1058 unsigned offset = m_rand(); 1059 for (unsigned i = m_root_nodes.size(); i-- > 0; ) { 1060 node* n = m_root_nodes[(i + offset) % m_root_nodes.size()]; 1061 SASSERT(n->is_root()); 1062 mk_inverse(n); 1063 } 1064 } 1065 1066 public: fix_model(expr_ref_vector & new_constraints)1067 void fix_model(expr_ref_vector& new_constraints) { 1068 cleanup_instantiation_sets(); 1069 m_new_constraints = &new_constraints; 1070 func_decl_set partial_funcs; 1071 collect_partial_funcs(partial_funcs); 1072 reset_eval_cache(); // will start using model_completion 1073 collect_root_nodes(); 1074 add_elem_to_empty_inst_sets(); 1075 mk_sorts_finite(); 1076 mk_projections(); 1077 mk_inverses(); 1078 complete_partial_funcs(partial_funcs); 1079 TRACE("model_finder", tout << "after auf_solver fixing the model\n"; 1080 display_nodes(tout); 1081 tout << "NEW MODEL:\n"; 1082 model_pp(tout, *m_model);); 1083 } 1084 }; 1085 1086 1087 // ----------------------------------- 1088 // 1089 // qinfo class & subclasses 1090 // 1091 // ----------------------------------- 1092 1093 /* 1094 During quantifier internalizations time, we collect bits of 1095 information about the quantifier structure. These bits are 1096 instances of subclasses of qinfo. 1097 */ 1098 1099 /** 1100 \brief Generic bit of information collected when analyzing quantifiers. 1101 The subclasses are defined in the .cpp file. 1102 */ 1103 class qinfo { 1104 protected: 1105 ast_manager& m; 1106 public: qinfo(ast_manager & m)1107 qinfo(ast_manager& m) :m(m) {} ~qinfo()1108 virtual ~qinfo() {} 1109 virtual char const* get_kind() const = 0; 1110 virtual bool is_equal(qinfo const* qi) const = 0; display(std::ostream & out) const1111 virtual void display(std::ostream& out) const { out << "[" << get_kind() << "]"; } 1112 1113 // AUF fragment solver 1114 virtual void process_auf(quantifier* q, auf_solver& s, context* ctx) = 0; 1115 virtual void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) = 0; 1116 // second pass... actually we may need to reach a fixpoint, but if it cannot be found 1117 // in two passes, the fixpoint is not finite. populate_inst_sets2(quantifier * q,auf_solver & s,context * ctx)1118 virtual void populate_inst_sets2(quantifier* q, auf_solver& s, context* ctx) {} 1119 1120 // Macro/Hint support populate_inst_sets(quantifier * q,func_decl * mhead,ptr_vector<instantiation_set> & uvar_inst_sets,context * ctx)1121 virtual void populate_inst_sets(quantifier* q, func_decl* mhead, ptr_vector<instantiation_set>& uvar_inst_sets, context* ctx) {} 1122 }; 1123 1124 class f_var : public qinfo { 1125 protected: 1126 func_decl* m_f; 1127 unsigned m_arg_i; 1128 unsigned m_var_j; 1129 public: f_var(ast_manager & m,func_decl * f,unsigned i,unsigned j)1130 f_var(ast_manager& m, func_decl* f, unsigned i, unsigned j) : qinfo(m), m_f(f), m_arg_i(i), m_var_j(j) {} ~f_var()1131 ~f_var() override {} 1132 get_kind() const1133 char const* get_kind() const override { 1134 return "f_var"; 1135 } 1136 is_equal(qinfo const * qi) const1137 bool is_equal(qinfo const* qi) const override { 1138 if (qi->get_kind() != get_kind()) 1139 return false; 1140 f_var const* other = static_cast<f_var const*>(qi); 1141 return m_f == other->m_f && m_arg_i == other->m_arg_i && m_var_j == other->m_var_j; 1142 } 1143 display(std::ostream & out) const1144 void display(std::ostream& out) const override { 1145 out << "(" << m_f->get_name() << ":" << m_arg_i << " -> v!" << m_var_j << ")"; 1146 } 1147 process_auf(quantifier * q,auf_solver & s,context * ctx)1148 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1149 node* n1 = s.get_A_f_i(m_f, m_arg_i); 1150 node* n2 = s.get_uvar(q, m_var_j); 1151 CTRACE("model_finder", n1->get_sort() != n2->get_sort(), 1152 tout << "sort bug:\n" << mk_ismt2_pp(q->get_expr(), m) << "\n" << mk_ismt2_pp(q, m) << "\n"; 1153 tout << "decl(0): " << q->get_decl_name(0) << "\n"; 1154 tout << "f: " << m_f->get_name() << " i: " << m_arg_i << "\n"; 1155 tout << "v: " << m_var_j << "\n"; 1156 n1->get_root()->display(tout, m); 1157 n2->get_root()->display(tout, m); 1158 tout << "f signature: "; 1159 for (unsigned i = 0; i < m_f->get_arity(); i++) tout << mk_pp(m_f->get_domain(i), m) << " "; 1160 tout << "-> " << mk_pp(m_f->get_range(), m) << "\n"; 1161 ); 1162 1163 n1->merge(n2); 1164 } 1165 populate_inst_sets(quantifier * q,auf_solver & s,context * ctx)1166 void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) override { 1167 node* A_f_i = s.get_A_f_i(m_f, m_arg_i); 1168 for (enode* n : ctx->enodes_of(m_f)) { 1169 if (ctx->is_relevant(n)) { 1170 // Remark: it is incorrect to use 1171 // n->get_arg(m_arg_i)->get_root() 1172 // instead of 1173 // n->get_arg(m_arg_i) 1174 // 1175 // Due to model based quantifier instantiation, some equivalence 1176 // classes are merged by accident. 1177 // So, using n->get_arg(m_arg_i)->get_root(), we may miss 1178 // a necessary instantiation. 1179 enode* e_arg = n->get_arg(m_arg_i); 1180 expr* arg = e_arg->get_owner(); 1181 A_f_i->insert(arg, e_arg->get_generation()); 1182 } 1183 } 1184 } 1185 populate_inst_sets(quantifier * q,func_decl * mhead,ptr_vector<instantiation_set> & uvar_inst_sets,context * ctx)1186 void populate_inst_sets(quantifier* q, func_decl* mhead, ptr_vector<instantiation_set>& uvar_inst_sets, context* ctx) override { 1187 if (m_f != mhead) 1188 return; 1189 uvar_inst_sets.reserve(m_var_j + 1, 0); 1190 if (uvar_inst_sets[m_var_j] == 0) 1191 uvar_inst_sets[m_var_j] = alloc(instantiation_set, ctx->get_manager()); 1192 instantiation_set* s = uvar_inst_sets[m_var_j]; 1193 SASSERT(s != nullptr); 1194 1195 for (enode* n : ctx->enodes_of(m_f)) { 1196 if (ctx->is_relevant(n)) { 1197 enode* e_arg = n->get_arg(m_arg_i); 1198 expr* arg = e_arg->get_owner(); 1199 s->insert(arg, e_arg->get_generation()); 1200 } 1201 } 1202 } 1203 }; 1204 1205 class f_var_plus_offset : public f_var { 1206 expr_ref m_offset; 1207 public: f_var_plus_offset(ast_manager & m,func_decl * f,unsigned i,unsigned j,expr * offset)1208 f_var_plus_offset(ast_manager& m, func_decl* f, unsigned i, unsigned j, expr* offset) : 1209 f_var(m, f, i, j), 1210 m_offset(offset, m) { 1211 } ~f_var_plus_offset()1212 ~f_var_plus_offset() override {} 1213 get_kind() const1214 char const* get_kind() const override { 1215 return "f_var_plus_offset"; 1216 } 1217 is_equal(qinfo const * qi) const1218 bool is_equal(qinfo const* qi) const override { 1219 if (qi->get_kind() != get_kind()) 1220 return false; 1221 f_var_plus_offset const* other = static_cast<f_var_plus_offset const*>(qi); 1222 return m_f == other->m_f && m_arg_i == other->m_arg_i && m_var_j == other->m_var_j && m_offset.get() == other->m_offset.get(); 1223 } 1224 display(std::ostream & out) const1225 void display(std::ostream& out) const override { 1226 out << "(" << m_f->get_name() << ":" << m_arg_i << " - " << 1227 mk_bounded_pp(m_offset.get(), m_offset.get_manager()) << " -> v!" << m_var_j << ")"; 1228 } 1229 process_auf(quantifier * q,auf_solver & s,context * ctx)1230 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1231 // just create the nodes 1232 /* node * A_f_i = */ s.get_A_f_i(m_f, m_arg_i); 1233 /* node * S_j = */ s.get_uvar(q, m_var_j); 1234 } 1235 populate_inst_sets(quantifier * q,auf_solver & s,context * ctx)1236 void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) override { 1237 // S_j is not necessary equal to A_f_i. 1238 node* A_f_i = s.get_A_f_i(m_f, m_arg_i)->get_root(); 1239 node* S_j = s.get_uvar(q, m_var_j)->get_root(); 1240 if (A_f_i == S_j) { 1241 // there is no finite fixpoint... we just copy the i-th arguments of A_f_i - m_offset 1242 // hope for the best... 1243 node* S_j = s.get_uvar(q, m_var_j); 1244 for (enode* n : ctx->enodes_of(m_f)) { 1245 if (ctx->is_relevant(n)) { 1246 arith_rewriter arith_rw(m); 1247 bv_util bv(m); 1248 bv_rewriter bv_rw(m); 1249 enode* e_arg = n->get_arg(m_arg_i); 1250 expr* arg = e_arg->get_owner(); 1251 expr_ref arg_minus_k(m); 1252 if (bv.is_bv(arg)) 1253 bv_rw.mk_sub(arg, m_offset, arg_minus_k); 1254 else 1255 arith_rw.mk_sub(arg, m_offset, arg_minus_k); 1256 S_j->insert(arg_minus_k, e_arg->get_generation()); 1257 } 1258 } 1259 } 1260 else { 1261 // A_f_i != S_j, there is hope for a finite fixpoint. 1262 // So, we just populate A_f_i 1263 f_var::populate_inst_sets(q, s, ctx); 1264 // I must also propagate the monotonicity flag since A_f_i and S_j are not in the 1265 // same equivalence class. 1266 if (A_f_i->is_mono_proj()) 1267 S_j->set_mono_proj(); 1268 if (S_j->is_mono_proj()) 1269 A_f_i->set_mono_proj(); 1270 } 1271 } 1272 1273 template<bool PLUS> copy_instances(node * from,node * to,auf_solver & s)1274 void copy_instances(node* from, node* to, auf_solver& s) { 1275 instantiation_set const* from_s = from->get_instantiation_set(); 1276 obj_map<expr, unsigned> const& elems_s = from_s->get_elems(); 1277 1278 arith_rewriter arith_rw(m_offset.get_manager()); 1279 bv_rewriter bv_rw(m_offset.get_manager()); 1280 bool is_bv = bv_util(m_offset.get_manager()).is_bv_sort(from->get_sort()); 1281 1282 for (auto const& kv : elems_s) { 1283 expr* n = kv.m_key; 1284 expr_ref n_k(m_offset.get_manager()); 1285 if (PLUS) { 1286 if (is_bv) { 1287 bv_rw.mk_add(n, m_offset, n_k); 1288 } 1289 else { 1290 arith_rw.mk_add(n, m_offset, n_k); 1291 } 1292 } 1293 else { 1294 if (is_bv) { 1295 bv_rw.mk_sub(n, m_offset, n_k); 1296 } 1297 else { 1298 arith_rw.mk_sub(n, m_offset, n_k); 1299 } 1300 } 1301 to->insert(n_k, kv.m_value); 1302 } 1303 } 1304 populate_inst_sets2(quantifier * q,auf_solver & s,context * ctx)1305 void populate_inst_sets2(quantifier* q, auf_solver& s, context* ctx) override { 1306 node* A_f_i = s.get_A_f_i(m_f, m_arg_i)->get_root(); 1307 node* S_j = s.get_uvar(q, m_var_j)->get_root(); 1308 // If A_f_i == S_j, then there is no finite fixpoint, so we do nothing here. 1309 if (A_f_i != S_j) { 1310 // enforce 1311 // A_f_i - k \subset S_j 1312 // S_j + k \subset A_f_i 1313 copy_instances<false>(A_f_i, S_j, s); 1314 copy_instances<true>(S_j, A_f_i, s); 1315 } 1316 } 1317 populate_inst_sets(quantifier * q,func_decl * mhead,ptr_vector<instantiation_set> & uvar_inst_sets,context * ctx)1318 void populate_inst_sets(quantifier* q, func_decl* mhead, ptr_vector<instantiation_set>& uvar_inst_sets, context* ctx) override { 1319 // ignored when in macro 1320 } 1321 1322 }; 1323 1324 1325 /** 1326 \brief auf_arr is a term (pattern) of the form: 1327 1328 FORM := GROUND-TERM 1329 | (select FORM VAR) 1330 1331 Store in arrays, all enodes that match the pattern 1332 */ get_auf_arrays(app * auf_arr,context * ctx,ptr_buffer<enode> & arrays)1333 void get_auf_arrays(app* auf_arr, context* ctx, ptr_buffer<enode>& arrays) { 1334 if (is_ground(auf_arr)) { 1335 if (ctx->e_internalized(auf_arr)) { 1336 enode* e = ctx->get_enode(auf_arr); 1337 if (ctx->is_relevant(e)) { 1338 arrays.push_back(e); 1339 } 1340 } 1341 } 1342 else { 1343 app* nested_array = to_app(auf_arr->get_arg(0)); 1344 ptr_buffer<enode> nested_arrays; 1345 get_auf_arrays(nested_array, ctx, nested_arrays); 1346 for (enode* curr : nested_arrays) { 1347 enode_vector::iterator it2 = curr->begin_parents(); 1348 enode_vector::iterator end2 = curr->end_parents(); 1349 for (; it2 != end2; ++it2) { 1350 enode* p = *it2; 1351 if (ctx->is_relevant(p) && p->get_owner()->get_decl() == auf_arr->get_decl()) { 1352 arrays.push_back(p); 1353 } 1354 } 1355 } 1356 } 1357 } 1358 1359 class select_var : public qinfo { 1360 protected: 1361 array_util m_array; 1362 app* m_select; // It must satisfy is_auf_select... see bool is_auf_select(expr * t) const 1363 unsigned m_arg_i; 1364 unsigned m_var_j; 1365 get_array() const1366 app* get_array() const { return to_app(m_select->get_arg(0)); } 1367 get_array_func_decl(app * ground_array,auf_solver & s)1368 func_decl* get_array_func_decl(app* ground_array, auf_solver& s) { 1369 TRACE("model_evaluator", tout << expr_ref(ground_array, m) << "\n";); 1370 expr* ground_array_interp = s.eval(ground_array, false); 1371 if (ground_array_interp && m_array.is_as_array(ground_array_interp)) 1372 return m_array.get_as_array_func_decl(ground_array_interp); 1373 return nullptr; 1374 } 1375 1376 public: select_var(ast_manager & m,app * s,unsigned i,unsigned j)1377 select_var(ast_manager& m, app* s, unsigned i, unsigned j) :qinfo(m), m_array(m), m_select(s), m_arg_i(i), m_var_j(j) {} ~select_var()1378 ~select_var() override {} 1379 get_kind() const1380 char const* get_kind() const override { 1381 return "select_var"; 1382 } 1383 is_equal(qinfo const * qi) const1384 bool is_equal(qinfo const* qi) const override { 1385 if (qi->get_kind() != get_kind()) 1386 return false; 1387 select_var const* other = static_cast<select_var const*>(qi); 1388 return m_select == other->m_select && m_arg_i == other->m_arg_i && m_var_j == other->m_var_j; 1389 } 1390 display(std::ostream & out) const1391 void display(std::ostream& out) const override { 1392 out << "(" << mk_bounded_pp(m_select, m) << ":" << m_arg_i << " -> v!" << m_var_j << ")"; 1393 } 1394 process_auf(quantifier * q,auf_solver & s,context * ctx)1395 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1396 ptr_buffer<enode> arrays; 1397 get_auf_arrays(get_array(), ctx, arrays); 1398 TRACE("select_var", 1399 tout << "enodes matching: "; display(tout); tout << "\n"; 1400 for (enode* n : arrays) { 1401 tout << "#" << n->get_owner()->get_id() << "\n" << mk_pp(n->get_owner(), m) << "\n"; 1402 }); 1403 node* n1 = s.get_uvar(q, m_var_j); 1404 for (enode* n : arrays) { 1405 app* ground_array = n->get_owner(); 1406 func_decl* f = get_array_func_decl(ground_array, s); 1407 if (f) { 1408 SASSERT(m_arg_i >= 1); 1409 node* n2 = s.get_A_f_i(f, m_arg_i - 1); 1410 n1->merge(n2); 1411 } 1412 } 1413 } 1414 populate_inst_sets(quantifier * q,auf_solver & s,context * ctx)1415 void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) override { 1416 ptr_buffer<enode> arrays; 1417 get_auf_arrays(get_array(), ctx, arrays); 1418 for (enode* curr : arrays) { 1419 app* ground_array = curr->get_owner(); 1420 func_decl* f = get_array_func_decl(ground_array, s); 1421 if (f) { 1422 node* A_f_i = s.get_A_f_i(f, m_arg_i - 1); 1423 enode_vector::iterator it2 = curr->begin_parents(); 1424 enode_vector::iterator end2 = curr->end_parents(); 1425 for (; it2 != end2; ++it2) { 1426 enode* p = *it2; 1427 if (ctx->is_relevant(p) && p->get_owner()->get_decl() == m_select->get_decl()) { 1428 SASSERT(m_arg_i < p->get_owner()->get_num_args()); 1429 enode* e_arg = p->get_arg(m_arg_i); 1430 A_f_i->insert(e_arg->get_owner(), e_arg->get_generation()); 1431 } 1432 } 1433 } 1434 } 1435 } 1436 }; 1437 1438 class var_pair : public qinfo { 1439 protected: 1440 unsigned m_var_i; 1441 unsigned m_var_j; 1442 public: var_pair(ast_manager & m,unsigned i,unsigned j)1443 var_pair(ast_manager& m, unsigned i, unsigned j) : qinfo(m), m_var_i(i), m_var_j(j) { 1444 if (m_var_i > m_var_j) 1445 std::swap(m_var_i, m_var_j); 1446 } 1447 ~var_pair()1448 ~var_pair() override {} 1449 is_equal(qinfo const * qi) const1450 bool is_equal(qinfo const* qi) const override { 1451 if (qi->get_kind() != get_kind()) 1452 return false; 1453 var_pair const* other = static_cast<var_pair const*>(qi); 1454 return m_var_i == other->m_var_i && m_var_j == other->m_var_j; 1455 } 1456 display(std::ostream & out) const1457 void display(std::ostream& out) const override { 1458 out << "(" << get_kind() << ":v!" << m_var_i << ":v!" << m_var_j << ")"; 1459 } 1460 populate_inst_sets(quantifier * q,auf_solver & s,context * ctx)1461 void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) override { 1462 // do nothing 1463 } 1464 }; 1465 1466 class x_eq_y : public var_pair { 1467 public: x_eq_y(ast_manager & m,unsigned i,unsigned j)1468 x_eq_y(ast_manager& m, unsigned i, unsigned j) :var_pair(m, i, j) {} get_kind() const1469 char const* get_kind() const override { return "x_eq_y"; } 1470 process_auf(quantifier * q,auf_solver & s,context * ctx)1471 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1472 node* n1 = s.get_uvar(q, m_var_i); 1473 node* n2 = s.get_uvar(q, m_var_j); 1474 n1->insert_avoid(n2); 1475 if (n1 != n2) 1476 n2->insert_avoid(n1); 1477 } 1478 }; 1479 1480 class x_neq_y : public var_pair { 1481 public: x_neq_y(ast_manager & m,unsigned i,unsigned j)1482 x_neq_y(ast_manager& m, unsigned i, unsigned j) :var_pair(m, i, j) {} get_kind() const1483 char const* get_kind() const override { return "x_neq_y"; } 1484 process_auf(quantifier * q,auf_solver & s,context * ctx)1485 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1486 node* n1 = s.get_uvar(q, m_var_i); 1487 node* n2 = s.get_uvar(q, m_var_j); 1488 n1->merge(n2); 1489 } 1490 }; 1491 1492 class x_leq_y : public var_pair { 1493 public: x_leq_y(ast_manager & m,unsigned i,unsigned j)1494 x_leq_y(ast_manager& m, unsigned i, unsigned j) :var_pair(m, i, j) {} get_kind() const1495 char const* get_kind() const override { return "x_leq_y"; } 1496 process_auf(quantifier * q,auf_solver & s,context * ctx)1497 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1498 node* n1 = s.get_uvar(q, m_var_i); 1499 node* n2 = s.get_uvar(q, m_var_j); 1500 n1->merge(n2); 1501 n1->set_mono_proj(); 1502 } 1503 }; 1504 1505 // signed bit-vector comparison 1506 class x_sleq_y : public x_leq_y { 1507 public: x_sleq_y(ast_manager & m,unsigned i,unsigned j)1508 x_sleq_y(ast_manager& m, unsigned i, unsigned j) :x_leq_y(m, i, j) {} get_kind() const1509 char const* get_kind() const override { return "x_sleq_y"; } 1510 process_auf(quantifier * q,auf_solver & s,context * ctx)1511 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1512 node* n1 = s.get_uvar(q, m_var_i); 1513 node* n2 = s.get_uvar(q, m_var_j); 1514 n1->merge(n2); 1515 n1->set_mono_proj(); 1516 n1->set_signed_proj(); 1517 } 1518 }; 1519 1520 class var_expr_pair : public qinfo { 1521 protected: 1522 unsigned m_var_i; 1523 expr_ref m_t; 1524 public: var_expr_pair(ast_manager & m,unsigned i,expr * t)1525 var_expr_pair(ast_manager& m, unsigned i, expr* t) : 1526 qinfo(m), 1527 m_var_i(i), m_t(t, m) {} ~var_expr_pair()1528 ~var_expr_pair() override {} 1529 is_equal(qinfo const * qi) const1530 bool is_equal(qinfo const* qi) const override { 1531 if (qi->get_kind() != get_kind()) 1532 return false; 1533 var_expr_pair const* other = static_cast<var_expr_pair const*>(qi); 1534 return m_var_i == other->m_var_i && m_t.get() == other->m_t.get(); 1535 } 1536 display(std::ostream & out) const1537 void display(std::ostream& out) const override { 1538 out << "(" << get_kind() << ":v!" << m_var_i << ":" << mk_bounded_pp(m_t.get(), m) << ")"; 1539 } 1540 }; 1541 1542 class x_eq_t : public var_expr_pair { 1543 public: x_eq_t(ast_manager & m,unsigned i,expr * t)1544 x_eq_t(ast_manager& m, unsigned i, expr* t) : 1545 var_expr_pair(m, i, t) {} get_kind() const1546 char const* get_kind() const override { return "x_eq_t"; } 1547 process_auf(quantifier * q,auf_solver & s,context * ctx)1548 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1549 node* n1 = s.get_uvar(q, m_var_i); 1550 n1->insert_exception(m_t); 1551 } 1552 populate_inst_sets(quantifier * q,auf_solver & slv,context * ctx)1553 void populate_inst_sets(quantifier* q, auf_solver& slv, context* ctx) override { 1554 unsigned num_vars = q->get_num_decls(); 1555 sort* s = q->get_decl_sort(num_vars - m_var_i - 1); 1556 if (m.is_uninterp(s)) { 1557 // For uninterpreted sorts, we add all terms in the context. 1558 // See Section 4.1 in the paper "Complete Quantifier Instantiation" 1559 node* S_q_i = slv.get_uvar(q, m_var_i); 1560 for (enode* n : ctx->enodes()) { 1561 if (ctx->is_relevant(n) && get_sort(n->get_owner()) == s) { 1562 S_q_i->insert(n->get_owner(), n->get_generation()); 1563 } 1564 } 1565 } 1566 } 1567 }; 1568 1569 class x_neq_t : public var_expr_pair { 1570 public: x_neq_t(ast_manager & m,unsigned i,expr * t)1571 x_neq_t(ast_manager& m, unsigned i, expr* t) : 1572 var_expr_pair(m, i, t) {} get_kind() const1573 char const* get_kind() const override { return "x_neq_t"; } 1574 process_auf(quantifier * q,auf_solver & s,context * ctx)1575 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1576 // make sure that S_q_i is create. 1577 s.get_uvar(q, m_var_i); 1578 } 1579 populate_inst_sets(quantifier * q,auf_solver & s,context * ctx)1580 void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) override { 1581 node* S_q_i = s.get_uvar(q, m_var_i); 1582 S_q_i->insert(m_t, 0); 1583 } 1584 }; 1585 1586 class x_gle_t : public var_expr_pair { 1587 public: x_gle_t(ast_manager & m,unsigned i,expr * t)1588 x_gle_t(ast_manager& m, unsigned i, expr* t) : 1589 var_expr_pair(m, i, t) {} get_kind() const1590 char const* get_kind() const override { return "x_gle_t"; } 1591 process_auf(quantifier * q,auf_solver & s,context * ctx)1592 void process_auf(quantifier* q, auf_solver& s, context* ctx) override { 1593 // make sure that S_q_i is create. 1594 node* n1 = s.get_uvar(q, m_var_i); 1595 n1->set_mono_proj(); 1596 } 1597 populate_inst_sets(quantifier * q,auf_solver & s,context * ctx)1598 void populate_inst_sets(quantifier* q, auf_solver& s, context* ctx) override { 1599 node* S_q_i = s.get_uvar(q, m_var_i); 1600 S_q_i->insert(m_t, 0); 1601 } 1602 }; 1603 1604 1605 // ----------------------------------- 1606 // 1607 // quantifier_info & quantifier_analyzer 1608 // 1609 // ----------------------------------- 1610 1611 class quantifier_analyzer; 1612 1613 /** 1614 \brief Store relevant information regarding a particular universal quantifier. 1615 This information is populated by quantifier_analyzer. 1616 The information is used to (try to) build a model that satisfy the universal quantifier 1617 (when it is marked as relevant in the end of the search). 1618 */ 1619 class quantifier_info : public quantifier_macro_info { 1620 model_finder& m_mf; 1621 quantifier_ref m_q; // original quantifier 1622 1623 ptr_vector<qinfo> m_qinfo_vect; 1624 ptr_vector<instantiation_set>* m_uvar_inst_sets; 1625 1626 friend class quantifier_analyzer; 1627 checkpoint()1628 void checkpoint() { 1629 m_mf.checkpoint("quantifier_info"); 1630 } 1631 insert_qinfo(qinfo * qi)1632 void insert_qinfo(qinfo* qi) { 1633 // I'm assuming the number of qinfo's per quantifier is small. So, the linear search is not a big deal. 1634 scoped_ptr<qinfo> q(qi); 1635 for (qinfo* qi2 : m_qinfo_vect) { 1636 checkpoint(); 1637 if (qi->is_equal(qi2)) { 1638 return; 1639 } 1640 } 1641 m_qinfo_vect.push_back(q.detach()); 1642 TRACE("model_finder", tout << "new quantifier qinfo: "; qi->display(tout); tout << "\n";); 1643 } 1644 1645 public: 1646 typedef ptr_vector<cond_macro>::const_iterator macro_iterator; 1647 mk_flat(ast_manager & m,quantifier * q)1648 static quantifier_ref mk_flat(ast_manager& m, quantifier* q) { 1649 if (has_quantifiers(q->get_expr()) && !m.is_lambda_def(q)) { 1650 proof_ref pr(m); 1651 expr_ref new_q(m); 1652 pull_quant pull(m); 1653 pull(q, new_q, pr); 1654 SASSERT(is_well_sorted(m, new_q)); 1655 return quantifier_ref(to_quantifier(new_q), m); 1656 } 1657 else 1658 return quantifier_ref(q, m); 1659 } 1660 quantifier_info(model_finder & mf,ast_manager & m,quantifier * q)1661 quantifier_info(model_finder& mf, ast_manager& m, quantifier* q) : 1662 quantifier_macro_info(m, mk_flat(m, q)), 1663 m_mf(mf), 1664 m_q(q, m), 1665 m_uvar_inst_sets(nullptr) { 1666 CTRACE("model_finder_bug", has_quantifiers(m_flat_q->get_expr()), 1667 tout << mk_pp(q, m) << "\n" << mk_pp(m_flat_q, m) << "\n";); 1668 } 1669 ~quantifier_info()1670 ~quantifier_info() override { 1671 std::for_each(m_qinfo_vect.begin(), m_qinfo_vect.end(), delete_proc<qinfo>()); 1672 reset_the_one(); 1673 } 1674 display(std::ostream & out) const1675 std::ostream& display(std::ostream& out) const override { 1676 quantifier_macro_info::display(out); 1677 out << "\ninfo bits:\n"; 1678 for (qinfo* qi : m_qinfo_vect) { 1679 out << " "; qi->display(out); out << "\n"; 1680 } 1681 return out; 1682 } 1683 process_auf(auf_solver & s,context * ctx)1684 void process_auf(auf_solver& s, context* ctx) { 1685 for (unsigned i = 0; i < m_flat_q->get_num_decls(); i++) { 1686 // make sure a node exists for each variable. 1687 s.get_uvar(m_flat_q, i); 1688 } 1689 for (qinfo* qi : m_qinfo_vect) { 1690 qi->process_auf(m_flat_q, s, ctx); 1691 } 1692 } 1693 populate_inst_sets(auf_solver & s,context * ctx)1694 void populate_inst_sets(auf_solver& s, context* ctx) { 1695 for (qinfo* qi : m_qinfo_vect) { 1696 qi->populate_inst_sets(m_flat_q, s, ctx); 1697 } 1698 // second pass 1699 for (qinfo* qi : m_qinfo_vect) { 1700 checkpoint(); 1701 qi->populate_inst_sets2(m_flat_q, s, ctx); 1702 } 1703 } 1704 1705 populate_macro_based_inst_sets(context * ctx,evaluator & ev)1706 void populate_macro_based_inst_sets(context* ctx, evaluator& ev) { 1707 SASSERT(m_the_one != 0); 1708 if (m_uvar_inst_sets != nullptr) 1709 return; 1710 m_uvar_inst_sets = alloc(ptr_vector<instantiation_set>); 1711 for (qinfo* qi : m_qinfo_vect) 1712 qi->populate_inst_sets(m_flat_q, m_the_one, *m_uvar_inst_sets, ctx); 1713 for (instantiation_set* s : *m_uvar_inst_sets) { 1714 if (s != nullptr) 1715 s->mk_inverse(ev); 1716 } 1717 } 1718 get_macro_based_inst_set(unsigned vidx,context * ctx,evaluator & ev)1719 instantiation_set* get_macro_based_inst_set(unsigned vidx, context* ctx, evaluator& ev) { 1720 if (m_the_one == nullptr) 1721 return nullptr; 1722 populate_macro_based_inst_sets(ctx, ev); 1723 return m_uvar_inst_sets->get(vidx, 0); 1724 } 1725 reset_the_one()1726 void reset_the_one() override { 1727 quantifier_macro_info::reset_the_one(); 1728 if (m_uvar_inst_sets) { 1729 std::for_each(m_uvar_inst_sets->begin(), m_uvar_inst_sets->end(), delete_proc<instantiation_set>()); 1730 dealloc(m_uvar_inst_sets); 1731 m_uvar_inst_sets = nullptr; 1732 } 1733 } 1734 }; 1735 1736 /** 1737 \brief Functor used to traverse/analyze a quantifier and 1738 fill the structure quantifier_info. 1739 */ 1740 class quantifier_analyzer { 1741 model_finder& m_mf; 1742 ast_manager& m; 1743 macro_util m_mutil; 1744 array_util m_array_util; 1745 arith_util m_arith_util; 1746 bv_util m_bv_util; 1747 1748 quantifier_info* m_info; 1749 1750 typedef enum { POS, NEG } polarity; 1751 neg(polarity p)1752 polarity neg(polarity p) { return p == POS ? NEG : POS; } 1753 1754 obj_hashtable<expr> m_pos_cache; 1755 obj_hashtable<expr> m_neg_cache; 1756 typedef std::pair<expr*, polarity> entry; 1757 svector<entry> m_ftodo; 1758 ptr_vector<expr> m_ttodo; 1759 insert_qinfo(qinfo * qi)1760 void insert_qinfo(qinfo* qi) { 1761 SASSERT(m_info); 1762 m_info->insert_qinfo(qi); 1763 } 1764 is_var_plus_ground(expr * n,bool & inv,var * & v,expr_ref & t)1765 bool is_var_plus_ground(expr* n, bool& inv, var*& v, expr_ref& t) { 1766 return m_mutil.is_var_plus_ground(n, inv, v, t); 1767 } 1768 is_var_plus_ground(expr * n,var * & v,expr_ref & t)1769 bool is_var_plus_ground(expr* n, var*& v, expr_ref& t) { 1770 bool inv; 1771 TRACE("is_var_plus_ground", tout << mk_pp(n, m) << "\n"; 1772 tout << "is_var_plus_ground: " << is_var_plus_ground(n, inv, v, t) << "\n"; 1773 tout << "inv: " << inv << "\n";); 1774 return is_var_plus_ground(n, inv, v, t) && !inv; 1775 } 1776 is_add(expr * n) const1777 bool is_add(expr* n) const { 1778 return m_mutil.is_add(n); 1779 } 1780 is_zero(expr * n) const1781 bool is_zero(expr* n) const { 1782 return m_mutil.is_zero_safe(n); 1783 } 1784 is_times_minus_one(expr * n,expr * & arg) const1785 bool is_times_minus_one(expr* n, expr*& arg) const { 1786 return m_mutil.is_times_minus_one(n, arg); 1787 } 1788 is_le(expr * n) const1789 bool is_le(expr* n) const { 1790 return m_mutil.is_le(n); 1791 } 1792 is_le_ge(expr * n) const1793 bool is_le_ge(expr* n) const { 1794 return m_mutil.is_le_ge(n); 1795 } 1796 is_signed_le(expr * n) const1797 bool is_signed_le(expr* n) const { 1798 return m_bv_util.is_bv_sle(n); 1799 } 1800 mk_one(sort * s)1801 expr* mk_one(sort* s) { 1802 return m_bv_util.is_bv_sort(s) ? m_bv_util.mk_numeral(rational(1), s) : m_arith_util.mk_numeral(rational(1), s); 1803 } 1804 mk_sub(expr * t1,expr * t2,expr_ref & r) const1805 void mk_sub(expr* t1, expr* t2, expr_ref& r) const { 1806 m_mutil.mk_sub(t1, t2, r); 1807 } 1808 mk_add(expr * t1,expr * t2,expr_ref & r) const1809 void mk_add(expr* t1, expr* t2, expr_ref& r) const { 1810 m_mutil.mk_add(t1, t2, r); 1811 } 1812 is_var_and_ground(expr * lhs,expr * rhs,var * & v,expr_ref & t,bool & inv)1813 bool is_var_and_ground(expr* lhs, expr* rhs, var*& v, expr_ref& t, bool& inv) { 1814 inv = false; // true if invert the sign 1815 TRACE("is_var_and_ground", tout << "is_var_and_ground: " << mk_ismt2_pp(lhs, m) << " " << mk_ismt2_pp(rhs, m) << "\n";); 1816 if (is_var(lhs) && is_ground(rhs)) { 1817 v = to_var(lhs); 1818 t = rhs; 1819 TRACE("is_var_and_ground", tout << "var and ground\n";); 1820 return true; 1821 } 1822 else if (is_var(rhs) && is_ground(lhs)) { 1823 v = to_var(rhs); 1824 t = lhs; 1825 TRACE("is_var_and_ground", tout << "ground and var\n";); 1826 return true; 1827 } 1828 else { 1829 expr_ref tmp(m); 1830 if (is_var_plus_ground(lhs, inv, v, tmp) && is_ground(rhs)) { 1831 if (inv) 1832 mk_sub(tmp, rhs, t); 1833 else 1834 mk_sub(rhs, tmp, t); 1835 return true; 1836 } 1837 if (is_var_plus_ground(rhs, inv, v, tmp) && is_ground(lhs)) { 1838 if (inv) 1839 mk_sub(tmp, lhs, t); 1840 else 1841 mk_sub(lhs, tmp, t); 1842 return true; 1843 } 1844 } 1845 return false; 1846 } 1847 is_var_and_ground(expr * lhs,expr * rhs,var * & v,expr_ref & t)1848 bool is_var_and_ground(expr* lhs, expr* rhs, var*& v, expr_ref& t) { 1849 bool inv; 1850 return is_var_and_ground(lhs, rhs, v, t, inv); 1851 } 1852 is_x_eq_t_atom(expr * n,var * & v,expr_ref & t)1853 bool is_x_eq_t_atom(expr* n, var*& v, expr_ref& t) { 1854 if (!is_app(n)) 1855 return false; 1856 if (m.is_eq(n)) 1857 return is_var_and_ground(to_app(n)->get_arg(0), to_app(n)->get_arg(1), v, t); 1858 return false; 1859 } 1860 is_var_minus_var(expr * n,var * & v1,var * & v2)1861 bool is_var_minus_var(expr* n, var*& v1, var*& v2) { 1862 if (!is_add(n)) 1863 return false; 1864 expr* arg1 = to_app(n)->get_arg(0); 1865 expr* arg2 = to_app(n)->get_arg(1); 1866 if (!is_var(arg1)) 1867 std::swap(arg1, arg2); 1868 if (!is_var(arg1)) 1869 return false; 1870 expr* arg2_2; 1871 if (!is_times_minus_one(arg2, arg2_2)) 1872 return false; 1873 if (!is_var(arg2_2)) 1874 return false; 1875 v1 = to_var(arg1); 1876 v2 = to_var(arg2_2); 1877 return true; 1878 } 1879 is_var_and_var(expr * lhs,expr * rhs,var * & v1,var * & v2)1880 bool is_var_and_var(expr* lhs, expr* rhs, var*& v1, var*& v2) { 1881 if (is_var(lhs) && is_var(rhs)) { 1882 v1 = to_var(lhs); 1883 v2 = to_var(rhs); 1884 return true; 1885 } 1886 return 1887 (is_var_minus_var(lhs, v1, v2) && is_zero(rhs)) || 1888 (is_var_minus_var(rhs, v1, v2) && is_zero(lhs)); 1889 } 1890 is_x_eq_y_atom(expr * n,var * & v1,var * & v2)1891 bool is_x_eq_y_atom(expr* n, var*& v1, var*& v2) { 1892 return m.is_eq(n) && is_var_and_var(to_app(n)->get_arg(0), to_app(n)->get_arg(1), v1, v2); 1893 } 1894 is_x_gle_y_atom(expr * n,var * & v1,var * & v2)1895 bool is_x_gle_y_atom(expr* n, var*& v1, var*& v2) { 1896 return is_le_ge(n) && is_var_and_var(to_app(n)->get_arg(0), to_app(n)->get_arg(1), v1, v2); 1897 } 1898 is_x_gle_t_atom(expr * atom,bool sign,var * & v,expr_ref & t)1899 bool is_x_gle_t_atom(expr* atom, bool sign, var*& v, expr_ref& t) { 1900 if (!is_app(atom)) 1901 return false; 1902 if (sign) { 1903 bool r = is_le_ge(atom) && is_var_and_ground(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1), v, t); 1904 CTRACE("is_x_gle_t", r, tout << "is_x_gle_t: " << mk_ismt2_pp(atom, m) << "\n--->\n" 1905 << mk_ismt2_pp(v, m) << " " << mk_ismt2_pp(t, m) << "\n"; 1906 tout << "sign: " << sign << "\n";); 1907 return r; 1908 } 1909 else { 1910 if (is_le_ge(atom)) { 1911 expr_ref tmp(m); 1912 bool le = is_le(atom); 1913 bool inv = false; 1914 if (is_var_and_ground(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1), v, tmp, inv)) { 1915 if (inv) 1916 le = !le; 1917 sort* s = m.get_sort(tmp); 1918 expr_ref one(m); 1919 one = mk_one(s); 1920 if (le) 1921 mk_add(tmp, one, t); 1922 else 1923 mk_sub(tmp, one, t); 1924 TRACE("is_x_gle_t", tout << "is_x_gle_t: " << mk_ismt2_pp(atom, m) << "\n--->\n" 1925 << mk_ismt2_pp(v, m) << " " << mk_ismt2_pp(t, m) << "\n"; 1926 tout << "sign: " << sign << "\n";); 1927 return true; 1928 } 1929 } 1930 return false; 1931 } 1932 } 1933 reset_cache()1934 void reset_cache() { 1935 m_pos_cache.reset(); 1936 m_neg_cache.reset(); 1937 } 1938 get_cache(polarity pol)1939 obj_hashtable<expr>& get_cache(polarity pol) { 1940 return pol == POS ? m_pos_cache : m_neg_cache; 1941 } 1942 visit_formula(expr * n,polarity pol)1943 void visit_formula(expr* n, polarity pol) { 1944 if (is_ground(n)) 1945 return; // ground terms do not need to be visited. 1946 obj_hashtable<expr>& c = get_cache(pol); 1947 if (!c.contains(n)) { 1948 m_ftodo.push_back(entry(n, pol)); 1949 c.insert(n); 1950 } 1951 } 1952 visit_term(expr * n)1953 void visit_term(expr* n) { 1954 // ground terms do not need to be visited. 1955 if (!is_ground(n) && !m_pos_cache.contains(n)) { 1956 m_ttodo.push_back(n); 1957 m_pos_cache.insert(n); 1958 } 1959 } 1960 1961 /** 1962 \brief Process uninterpreted applications. 1963 */ process_u_app(app * t)1964 void process_u_app(app* t) { 1965 unsigned num_args = t->get_num_args(); 1966 for (unsigned i = 0; i < num_args; i++) { 1967 expr* arg = t->get_arg(i); 1968 if (is_var(arg)) { 1969 SASSERT(t->get_decl()->get_domain(i) == to_var(arg)->get_sort()); 1970 insert_qinfo(alloc(f_var, m, t->get_decl(), i, to_var(arg)->get_idx())); 1971 continue; 1972 } 1973 1974 var* v; 1975 expr_ref k(m); 1976 if (is_var_plus_ground(arg, v, k)) { 1977 insert_qinfo(alloc(f_var_plus_offset, m, t->get_decl(), i, v->get_idx(), k.get())); 1978 continue; 1979 } 1980 1981 visit_term(arg); 1982 } 1983 } 1984 1985 1986 /** 1987 \brief A term \c t is said to be a auf_select if 1988 it is of the form 1989 1990 (select a i) Where: 1991 1992 where a is ground or is_auf_select(a) == true 1993 and the indices are ground terms or variables. 1994 */ is_auf_select(expr * t) const1995 bool is_auf_select(expr* t) const { 1996 if (!m_array_util.is_select(t)) 1997 return false; 1998 expr* a = to_app(t)->get_arg(0); 1999 if (!is_ground(a) && !is_auf_select(a)) 2000 return false; 2001 for (expr* arg : *to_app(t)) { 2002 if (!is_ground(arg) && !is_var(arg)) 2003 return false; 2004 } 2005 return true; 2006 } 2007 2008 /** 2009 \brief Process interpreted applications. 2010 */ process_i_app(app * t)2011 void process_i_app(app* t) { 2012 if (is_auf_select(t)) { 2013 unsigned num_args = t->get_num_args(); 2014 app* array = to_app(t->get_arg(0)); 2015 visit_term(array); // array may be a nested array. 2016 for (unsigned i = 1; i < num_args; i++) { 2017 expr* arg = t->get_arg(i); 2018 if (is_var(arg)) { 2019 insert_qinfo(alloc(select_var, m, t, i, to_var(arg)->get_idx())); 2020 } 2021 else { 2022 SASSERT(is_ground(arg)); 2023 } 2024 } 2025 } 2026 else { 2027 for (expr* arg : *t) { 2028 visit_term(arg); 2029 } 2030 } 2031 } 2032 process_app(app * t)2033 void process_app(app* t) { 2034 SASSERT(!is_ground(t)); 2035 2036 if (t->get_family_id() != m.get_basic_family_id()) { 2037 m_info->m_ng_decls.insert(t->get_decl()); 2038 } 2039 2040 if (is_uninterp(t)) { 2041 process_u_app(t); 2042 } 2043 else { 2044 process_i_app(t); 2045 } 2046 } 2047 process_terms_on_stack()2048 void process_terms_on_stack() { 2049 while (!m_ttodo.empty()) { 2050 expr* curr = m_ttodo.back(); 2051 m_ttodo.pop_back(); 2052 2053 if (m.is_bool(curr)) { 2054 // formula nested in a term. 2055 visit_formula(curr, POS); 2056 visit_formula(curr, NEG); 2057 continue; 2058 } 2059 2060 if (is_app(curr)) { 2061 process_app(to_app(curr)); 2062 } 2063 else if (is_var(curr)) { 2064 m_info->m_is_auf = false; // unexpected occurrence of variable. 2065 } 2066 else { 2067 SASSERT(is_lambda(curr)); 2068 } 2069 } 2070 } 2071 process_literal(expr * atom,bool sign)2072 void process_literal(expr* atom, bool sign) { 2073 CTRACE("model_finder_bug", is_ground(atom), tout << mk_pp(atom, m) << "\n";); 2074 SASSERT(!is_ground(atom)); 2075 SASSERT(m.is_bool(atom)); 2076 2077 if (is_var(atom)) { 2078 if (sign) { 2079 // atom (not X) can be viewed as X != true 2080 insert_qinfo(alloc(x_neq_t, m, to_var(atom)->get_idx(), m.mk_true())); 2081 } 2082 else { 2083 // atom X can be viewed as X != false 2084 insert_qinfo(alloc(x_neq_t, m, to_var(atom)->get_idx(), m.mk_false())); 2085 } 2086 return; 2087 } 2088 2089 if (is_app(atom)) { 2090 var* v, * v1, * v2; 2091 expr_ref t(m); 2092 if (is_x_eq_t_atom(atom, v, t)) { 2093 if (sign) 2094 insert_qinfo(alloc(x_neq_t, m, v->get_idx(), t)); 2095 else 2096 insert_qinfo(alloc(x_eq_t, m, v->get_idx(), t)); 2097 } 2098 else if (is_x_eq_y_atom(atom, v1, v2)) { 2099 if (sign) 2100 insert_qinfo(alloc(x_neq_y, m, v1->get_idx(), v2->get_idx())); 2101 else { 2102 m_info->m_has_x_eq_y = true; // this atom is in the fringe of AUF 2103 insert_qinfo(alloc(x_eq_y, m, v1->get_idx(), v2->get_idx())); 2104 } 2105 } 2106 else if (sign && is_x_gle_y_atom(atom, v1, v2)) { 2107 if (is_signed_le(atom)) 2108 insert_qinfo(alloc(x_sleq_y, m, v1->get_idx(), v2->get_idx())); 2109 else 2110 insert_qinfo(alloc(x_leq_y, m, v1->get_idx(), v2->get_idx())); 2111 } 2112 else if (is_x_gle_t_atom(atom, sign, v, t)) { 2113 insert_qinfo(alloc(x_gle_t, m, v->get_idx(), t)); 2114 } 2115 else { 2116 process_app(to_app(atom)); 2117 } 2118 return; 2119 } 2120 2121 SASSERT(is_quantifier(atom)); 2122 UNREACHABLE(); 2123 } 2124 process_literal(expr * atom,polarity pol)2125 void process_literal(expr* atom, polarity pol) { 2126 process_literal(atom, pol == NEG); 2127 } 2128 process_and_or(app * n,polarity p)2129 void process_and_or(app* n, polarity p) { 2130 for (expr* arg : *n) 2131 visit_formula(arg, p); 2132 } 2133 process_ite(app * n,polarity p)2134 void process_ite(app* n, polarity p) { 2135 visit_formula(n->get_arg(0), p); 2136 visit_formula(n->get_arg(0), neg(p)); 2137 visit_formula(n->get_arg(1), p); 2138 visit_formula(n->get_arg(2), p); 2139 } 2140 process_iff(app * n)2141 void process_iff(app* n) { 2142 visit_formula(n->get_arg(0), POS); 2143 visit_formula(n->get_arg(0), NEG); 2144 visit_formula(n->get_arg(1), POS); 2145 visit_formula(n->get_arg(1), NEG); 2146 } 2147 checkpoint()2148 void checkpoint() { 2149 m_mf.checkpoint("quantifier_analyzer"); 2150 } 2151 process_formulas_on_stack()2152 void process_formulas_on_stack() { 2153 while (!m_ftodo.empty()) { 2154 checkpoint(); 2155 entry& e = m_ftodo.back(); 2156 expr* curr = e.first; 2157 polarity pol = e.second; 2158 m_ftodo.pop_back(); 2159 if (is_app(curr)) { 2160 if (to_app(curr)->get_family_id() == m.get_basic_family_id() && m.is_bool(curr)) { 2161 switch (static_cast<basic_op_kind>(to_app(curr)->get_decl_kind())) { 2162 case OP_IMPLIES: 2163 case OP_XOR: 2164 UNREACHABLE(); // simplifier eliminated ANDs, IMPLIEs, and XORs 2165 break; 2166 case OP_OR: 2167 case OP_AND: 2168 process_and_or(to_app(curr), pol); 2169 break; 2170 case OP_NOT: 2171 visit_formula(to_app(curr)->get_arg(0), neg(pol)); 2172 break; 2173 case OP_ITE: 2174 process_ite(to_app(curr), pol); 2175 break; 2176 case OP_EQ: 2177 if (m.is_bool(to_app(curr)->get_arg(0))) { 2178 process_iff(to_app(curr)); 2179 } 2180 else { 2181 process_literal(curr, pol); 2182 } 2183 break; 2184 default: 2185 process_literal(curr, pol); 2186 break; 2187 } 2188 } 2189 else { 2190 process_literal(curr, pol); 2191 } 2192 } 2193 else if (is_var(curr)) { 2194 SASSERT(m.is_bool(curr)); 2195 process_literal(curr, pol); 2196 } 2197 else { 2198 SASSERT(is_quantifier(curr)); 2199 } 2200 } 2201 } 2202 process_formula(expr * n)2203 void process_formula(expr* n) { 2204 SASSERT(m.is_bool(n)); 2205 visit_formula(n, POS); 2206 } 2207 process_clause(expr * cls)2208 void process_clause(expr* cls) { 2209 SASSERT(is_clause(m, cls)); 2210 unsigned num_lits = get_clause_num_literals(m, cls); 2211 for (unsigned i = 0; i < num_lits; i++) { 2212 expr* lit = get_clause_literal(m, cls, i); 2213 SASSERT(is_literal(m, lit)); 2214 expr* atom; 2215 bool sign; 2216 get_literal_atom_sign(m, lit, atom, sign); 2217 if (!is_ground(atom)) 2218 process_literal(atom, sign); 2219 } 2220 } 2221 2222 2223 public: quantifier_analyzer(model_finder & mf,ast_manager & m)2224 quantifier_analyzer(model_finder& mf, ast_manager& m) : 2225 m_mf(mf), 2226 m(m), 2227 m_mutil(m), 2228 m_array_util(m), 2229 m_arith_util(m), 2230 m_bv_util(m), 2231 m_info(nullptr) { 2232 } 2233 2234 operator ()(quantifier_info * d)2235 void operator()(quantifier_info* d) { 2236 m_info = d; 2237 quantifier* q = d->get_flat_q(); 2238 if (m.is_lambda_def(q)) return; 2239 expr* e = q->get_expr(); 2240 reset_cache(); 2241 if (!m.inc()) return; 2242 m_ttodo.reset(); 2243 m_ftodo.reset(); 2244 2245 if (is_clause(m, e)) { 2246 process_clause(e); 2247 } 2248 else { 2249 process_formula(e); 2250 } 2251 2252 while (!m_ftodo.empty() || !m_ttodo.empty()) { 2253 process_formulas_on_stack(); 2254 process_terms_on_stack(); 2255 } 2256 2257 m_info = nullptr; 2258 } 2259 2260 }; 2261 } 2262 2263 2264 // ----------------------------------- 2265 // 2266 // model finder 2267 // 2268 // ----------------------------------- 2269 model_finder(ast_manager & m)2270 model_finder::model_finder(ast_manager& m) : 2271 m(m), 2272 m_context(nullptr), 2273 m_analyzer(alloc(quantifier_analyzer, *this, m)), 2274 m_auf_solver(alloc(auf_solver, m)), 2275 m_dependencies(m), 2276 m_new_constraints(m) { 2277 } 2278 ~model_finder()2279 model_finder::~model_finder() { 2280 reset(); 2281 } 2282 checkpoint()2283 void model_finder::checkpoint() { 2284 checkpoint("model_finder"); 2285 } 2286 checkpoint(char const * msg)2287 void model_finder::checkpoint(char const* msg) { 2288 if (m_context && m_context->get_cancel_flag()) 2289 throw tactic_exception(m_context->get_manager().limit().get_cancel_msg()); 2290 } 2291 get_quantifier_info(quantifier * q)2292 mf::quantifier_info* model_finder::get_quantifier_info(quantifier* q) { 2293 mf::quantifier_info* qi = nullptr; 2294 if (!m_q2info.find(q, qi)) { 2295 register_quantifier(q); 2296 qi = m_q2info[q]; 2297 } 2298 return qi; 2299 } 2300 set_context(context * ctx)2301 void model_finder::set_context(context* ctx) { 2302 SASSERT(m_context == nullptr); 2303 m_context = ctx; 2304 } 2305 register_quantifier(quantifier * q)2306 void model_finder::register_quantifier(quantifier* q) { 2307 TRACE("model_finder", tout << "registering:\n" << q->get_id() << ": " << q << " " << &m_q2info << " " << mk_pp(q, m) << "\n";); 2308 quantifier_info* new_info = alloc(quantifier_info, *this, m, q); 2309 m_q2info.insert(q, new_info); 2310 m_quantifiers.push_back(q); 2311 m_analyzer->operator()(new_info); 2312 TRACE("model_finder", tout << "after analyzer:\n"; new_info->display(tout);); 2313 } 2314 push_scope()2315 void model_finder::push_scope() { 2316 m_scopes.push_back(scope()); 2317 scope& s = m_scopes.back(); 2318 s.m_quantifiers_lim = m_quantifiers.size(); 2319 } 2320 restore_quantifiers(unsigned old_size)2321 void model_finder::restore_quantifiers(unsigned old_size) { 2322 unsigned curr_size = m_quantifiers.size(); 2323 SASSERT(old_size <= curr_size); 2324 for (unsigned i = old_size; i < curr_size; i++) { 2325 quantifier* q = m_quantifiers[i]; 2326 SASSERT(m_q2info.contains(q)); 2327 quantifier_info* info = get_quantifier_info(q); 2328 m_q2info.erase(q); 2329 dealloc(info); 2330 } 2331 m_quantifiers.shrink(old_size); 2332 } 2333 pop_scope(unsigned num_scopes)2334 void model_finder::pop_scope(unsigned num_scopes) { 2335 unsigned lvl = m_scopes.size(); 2336 SASSERT(num_scopes <= lvl); 2337 unsigned new_lvl = lvl - num_scopes; 2338 scope& s = m_scopes[new_lvl]; 2339 restore_quantifiers(s.m_quantifiers_lim); 2340 m_scopes.shrink(new_lvl); 2341 } 2342 reset()2343 void model_finder::reset() { 2344 m_scopes.reset(); 2345 m_dependencies.reset(); 2346 restore_quantifiers(0); 2347 SASSERT(m_q2info.empty()); 2348 SASSERT(m_quantifiers.empty()); 2349 } 2350 init_search_eh()2351 void model_finder::init_search_eh() { 2352 // do nothing in the current version 2353 } 2354 collect_relevant_quantifiers(ptr_vector<quantifier> & qs) const2355 void model_finder::collect_relevant_quantifiers(ptr_vector<quantifier>& qs) const { 2356 for (quantifier* q : m_quantifiers) { 2357 if (m_context->is_relevant(q) && m_context->get_assignment(q) == l_true) 2358 qs.push_back(q); 2359 } 2360 } 2361 process_auf(ptr_vector<quantifier> const & qs,proto_model * mdl)2362 void model_finder::process_auf(ptr_vector<quantifier> const& qs, proto_model* mdl) { 2363 m_auf_solver->reset(); 2364 m_auf_solver->set_model(mdl); 2365 2366 for (quantifier* q : qs) { 2367 quantifier_info* qi = get_quantifier_info(q); 2368 qi->process_auf(*(m_auf_solver.get()), m_context); 2369 } 2370 m_auf_solver->mk_instantiation_sets(); 2371 2372 for (quantifier* q : qs) { 2373 quantifier_info* qi = get_quantifier_info(q); 2374 qi->populate_inst_sets(*(m_auf_solver.get()), m_context); 2375 } 2376 m_auf_solver->fix_model(m_new_constraints); 2377 TRACE("model_finder", 2378 for (quantifier* q : qs) { 2379 quantifier_info* qi = get_quantifier_info(q); 2380 quantifier* fq = qi->get_flat_q(); 2381 tout << "#" << fq->get_id() << " ->\n" << mk_pp(fq, m) << "\n"; 2382 } 2383 m_auf_solver->display_nodes(tout);); 2384 } 2385 operator ()(quantifier * q)2386 quantifier_macro_info* model_finder::operator()(quantifier* q) { 2387 return m_q2info[q]; 2388 } 2389 process_simple_macros(ptr_vector<quantifier> & qs,ptr_vector<quantifier> & residue,proto_model * mdl)2390 void model_finder::process_simple_macros(ptr_vector<quantifier>& qs, ptr_vector<quantifier>& residue, proto_model* mdl) { 2391 simple_macro_solver sms(m, *this); 2392 sms(*mdl, qs, residue); 2393 TRACE("model_finder", tout << "model after processing simple macros:\n"; model_pp(tout, *mdl);); 2394 } 2395 process_hint_macros(ptr_vector<quantifier> & qs,ptr_vector<quantifier> & residue,proto_model * mdl)2396 void model_finder::process_hint_macros(ptr_vector<quantifier>& qs, ptr_vector<quantifier>& residue, proto_model* mdl) { 2397 hint_macro_solver hms(m, *this); 2398 hms(*mdl, qs, residue); 2399 TRACE("model_finder", tout << "model after processing simple macros:\n"; model_pp(tout, *mdl);); 2400 } 2401 process_non_auf_macros(ptr_vector<quantifier> & qs,ptr_vector<quantifier> & residue,proto_model * mdl)2402 void model_finder::process_non_auf_macros(ptr_vector<quantifier>& qs, ptr_vector<quantifier>& residue, proto_model* mdl) { 2403 non_auf_macro_solver nas(m, *this, m_dependencies); 2404 nas.set_mbqi_force_template(m_context->get_fparams().m_mbqi_force_template); 2405 nas(*mdl, qs, residue); 2406 TRACE("model_finder", tout << "model after processing non auf macros:\n"; model_pp(tout, *mdl);); 2407 } 2408 2409 /** 2410 \brief Clean leftovers from previous invocations to fix_model. 2411 */ cleanup_quantifier_infos(ptr_vector<quantifier> const & qs)2412 void model_finder::cleanup_quantifier_infos(ptr_vector<quantifier> const& qs) { 2413 for (quantifier* q : qs) { 2414 get_quantifier_info(q)->reset_the_one(); 2415 } 2416 } 2417 2418 /** 2419 \brief Try to satisfy quantifiers by modifying the model while preserving the satisfiability 2420 of all ground formulas asserted into the logical context. 2421 */ fix_model(proto_model * m)2422 void model_finder::fix_model(proto_model* m) { 2423 if (m_quantifiers.empty()) 2424 return; 2425 ptr_vector<quantifier> qs; 2426 ptr_vector<quantifier> residue; 2427 collect_relevant_quantifiers(qs); 2428 if (qs.empty()) 2429 return; 2430 TRACE("model_finder", tout << "trying to satisfy quantifiers, given model:\n"; model_pp(tout, *m);); 2431 cleanup_quantifier_infos(qs); 2432 m_dependencies.reset(); 2433 2434 process_simple_macros(qs, residue, m); 2435 process_hint_macros(qs, residue, m); 2436 process_non_auf_macros(qs, residue, m); 2437 qs.append(residue); 2438 process_auf(qs, m); 2439 } 2440 get_flat_quantifier(quantifier * q)2441 quantifier* model_finder::get_flat_quantifier(quantifier* q) { 2442 quantifier_info* qinfo = get_quantifier_info(q); 2443 return qinfo->get_flat_q(); 2444 } 2445 2446 /** 2447 \brief Return the instantiation set associated with var i of q. 2448 2449 \remark q is the quantifier before flattening. 2450 */ get_uvar_inst_set(quantifier * q,unsigned i)2451 mf::instantiation_set const* model_finder::get_uvar_inst_set(quantifier* q, unsigned i) { 2452 quantifier* flat_q = get_flat_quantifier(q); 2453 SASSERT(flat_q->get_num_decls() >= q->get_num_decls()); 2454 mf::instantiation_set const* r = m_auf_solver->get_uvar_inst_set(flat_q, flat_q->get_num_decls() - q->get_num_decls() + i); 2455 TRACE("model_finder", tout << "q: #" << q->get_id() << "\n" << mk_pp(q, m) << "\nflat_q: " << mk_pp(flat_q, m) 2456 << "\ni: " << i << " " << flat_q->get_num_decls() - q->get_num_decls() + i << "\n";); 2457 if (r != nullptr) 2458 return r; 2459 // quantifier was not processed by AUF solver... 2460 // it must have been satisfied by "macro"/"hint". 2461 quantifier_info* qinfo = get_quantifier_info(q); 2462 SASSERT(qinfo); 2463 return qinfo->get_macro_based_inst_set(i, m_context, *(m_auf_solver.get())); 2464 } 2465 2466 /** 2467 \brief Return an expression in the instantiation-set of q:i that evaluates to val. 2468 2469 \remark q is the quantifier before flattening. 2470 2471 Store in generation the generation of the result 2472 */ get_inv(quantifier * q,unsigned i,expr * val,unsigned & generation)2473 expr* model_finder::get_inv(quantifier* q, unsigned i, expr* val, unsigned& generation) { 2474 instantiation_set const* s = get_uvar_inst_set(q, i); 2475 if (s == nullptr) 2476 return nullptr; 2477 expr* t = s->get_inv(val); 2478 if (t != nullptr) { 2479 generation = s->get_generation(t); 2480 } 2481 return t; 2482 } 2483 2484 /** 2485 \brief Assert constraints restricting the possible values of the skolem constants can be assigned to. 2486 The idea is to restrict them to the values in the instantiation sets. 2487 2488 \remark q is the quantifier before flattening. 2489 2490 Return true if something was asserted. 2491 */ restrict_sks_to_inst_set(context * aux_ctx,quantifier * q,expr_ref_vector const & sks)2492 bool model_finder::restrict_sks_to_inst_set(context* aux_ctx, quantifier* q, expr_ref_vector const& sks) { 2493 // Note: we currently add instances of q instead of flat_q. 2494 // If the user wants instances of flat_q, it should use PULL_NESTED_QUANTIFIERS=true. This option 2495 // will guarantee that q == flat_q. 2496 // 2497 // Since we only care about q (and its bindings), it only makes sense to restrict the variables of q. 2498 bool asserted_something = false; 2499 unsigned num_decls = q->get_num_decls(); 2500 // Remark: sks were created for the flat version of q. 2501 SASSERT(get_flat_quantifier(q)->get_num_decls() == sks.size()); 2502 SASSERT(sks.size() >= num_decls); 2503 for (unsigned i = 0; i < num_decls; i++) { 2504 expr* sk = sks.get(num_decls - i - 1); 2505 instantiation_set const* s = get_uvar_inst_set(q, i); 2506 if (s == nullptr) 2507 continue; // nothing to do 2508 obj_map<expr, expr*> const& inv = s->get_inv_map(); 2509 if (inv.empty()) 2510 continue; // nothing to do 2511 ptr_buffer<expr> eqs; 2512 for (auto const& kv : inv) { 2513 expr* val = kv.m_key; 2514 eqs.push_back(m.mk_eq(sk, val)); 2515 } 2516 expr_ref new_cnstr(m); 2517 new_cnstr = m.mk_or(eqs.size(), eqs.c_ptr()); 2518 TRACE("model_finder", tout << "assert_restriction:\n" << mk_pp(new_cnstr, m) << "\n";); 2519 aux_ctx->assert_expr(new_cnstr); 2520 asserted_something = true; 2521 } 2522 return asserted_something; 2523 } 2524 restart_eh()2525 void model_finder::restart_eh() { 2526 unsigned sz = m_new_constraints.size(); 2527 if (sz > 0) { 2528 for (unsigned i = 0; i < sz; i++) { 2529 expr* c = m_new_constraints.get(i); 2530 TRACE("model_finder_bug_detail", tout << "asserting new constraint: " << mk_pp(c, m) << "\n";); 2531 m_context->internalize(c, true); 2532 literal l(m_context->get_literal(c)); 2533 m_context->mark_as_relevant(l); 2534 // asserting it as an AXIOM 2535 m_context->assign(l, b_justification()); 2536 } 2537 m_new_constraints.reset(); 2538 } 2539 } 2540 } 2541