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