z3-src 416.0.2

Source distribution of the Z3 SMT solver, for use as a build dependency
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    dl_context.h

Abstract:

    <abstract>

Author:

    Leonardo de Moura (leonardo) 2010-05-18.

Revision History:

--*/
#pragma once

#include "ast/arith_decl_plugin.h"
#include "util/map.h"
#include "ast/rewriter/th_rewriter.h"
#include "util/str_hashtable.h"
#include "ast/rewriter/var_subst.h"
#include "muz/base/dl_costs.h"
#include "ast/dl_decl_plugin.h"
#include "muz/base/dl_rule_set.h"
#include "util/lbool.h"
#include "util/statistics.h"
#include "util/params.h"
#include "util/trail.h"
#include "ast/converters/model_converter.h"
#include "model/model2expr.h"
#include "params/smt_params.h"
#include "muz/base/dl_rule_transformer.h"
#include "ast/expr_functors.h"
#include "muz/base/dl_engine_base.h"
#include "muz/base/bind_variables.h"
#include "muz/base/rule_properties.h"

struct fp_params;

namespace datalog {

    enum execution_result {
        OK,
        TIMEOUT,
        MEMOUT,
        INPUT_ERROR,
        APPROX,
        BOUNDED,
        CANCELED
    };

    class relation_manager;

    typedef sort * relation_sort;
    typedef uint64_t table_element;
    typedef svector<table_element> table_fact;

    typedef app * relation_element;
    typedef app_ref relation_element_ref;

    class relation_fact : public app_ref_vector {
    public:
        class el_proxy {
            friend class relation_fact;

            relation_fact & m_parent;
            unsigned m_idx;

            el_proxy(relation_fact & parent, unsigned idx) : m_parent(parent), m_idx(idx) {}
        public:
            operator relation_element() const {
                return m_parent.get(m_idx);
            }
            relation_element operator->() const {
                return m_parent.get(m_idx);
            }
            relation_element operator=(const relation_element & val) const {
                m_parent.set(m_idx, val);
                return m_parent.get(m_idx);
            }
            relation_element operator=(const el_proxy & val) {
                m_parent.set(m_idx, val);
                return m_parent.get(m_idx);
            }
        };

        typedef const relation_element * iterator;

        relation_fact(ast_manager & m) : app_ref_vector(m) {}
        relation_fact(ast_manager & m, unsigned sz) : app_ref_vector(m) { resize(sz); }
        relation_fact(context & ctx);

        iterator begin() const { return data(); }
        iterator end() const { return data()+size(); }

        relation_element operator[](unsigned i) const { return get(i); }
        el_proxy operator[](unsigned i) { return el_proxy(*this, i); }
    };

    // attempt to modularize context code.
    class rel_context_base : public engine_base {
    public:
        rel_context_base(ast_manager& m, char const* name): engine_base(m, name) {}
        virtual relation_manager & get_rmanager() = 0;
        virtual const relation_manager & get_rmanager() const = 0;
        virtual relation_base & get_relation(func_decl * pred) = 0;
        virtual relation_base * try_get_relation(func_decl * pred) const = 0;
        virtual bool is_empty_relation(func_decl* pred) const = 0;
        virtual expr_ref try_get_formula(func_decl * pred) const = 0;
        virtual void display_output_facts(rule_set const& rules, std::ostream & out) const = 0;
        virtual void display_facts(std::ostream & out) const = 0;
        virtual void restrict_predicates(func_decl_set const& predicates) = 0;
        virtual bool result_contains_fact(relation_fact const& f) = 0;
        virtual void add_fact(func_decl* pred, relation_fact const& fact) = 0;
        virtual void add_fact(func_decl* pred, table_fact const& fact) = 0;
        virtual bool has_facts(func_decl * pred) const = 0;
        virtual void store_relation(func_decl * pred, relation_base * rel) = 0;
        virtual void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred) = 0;
        virtual void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt,
                                                  symbol const * relation_names) = 0;
        virtual bool output_profile() const = 0;
        virtual void collect_non_empty_predicates(func_decl_set& preds) = 0;
        virtual void transform_rules() = 0;
        virtual bool try_get_size(func_decl* pred, unsigned& rel_sz) const = 0;
        virtual lbool saturate() = 0;
    };

    class context {
    public:
        typedef unsigned finite_element;
        enum sort_kind {
            SK_UINT64,
            SK_SYMBOL
        };
        class contains_pred : public i_expr_pred {
            context const& ctx;
        public:
            contains_pred(context& ctx): ctx(ctx) {}

            bool operator()(expr* e) override {
                return ctx.is_predicate(e);
            }
        };


    private:
        class sort_domain;
        class symbol_sort_domain;
        class uint64_sort_domain;
        class restore_rules;

        typedef hashtable<symbol, symbol_hash_proc, symbol_eq_proc> symbol_set;
        typedef map<symbol, func_decl*, symbol_hash_proc, symbol_eq_proc> sym2decl;
        typedef obj_map<const func_decl, svector<symbol> > pred2syms;
        typedef obj_map<const sort, sort_domain*> sort_domain_map;


        ast_manager &      m;
        register_engine_base& m_register_engine;
        smt_params &       m_fparams;
        params_ref         m_params_ref;
        fp_params*         m_params;
        bool               m_generate_proof_trace;      // cached configuration parameter
        bool               m_unbound_compressor;        // cached configuration parameter
        symbol             m_default_relation;          // cached configuration parameter
        dl_decl_util       m_decl_util;
        th_rewriter        m_rewriter;
        var_subst          m_var_subst;
        rule_manager       m_rule_manager;
        contains_pred      m_contains_p;
        rule_properties    m_rule_properties;
        rule_transformer   m_transf;
        trail_stack        m_trail;
        ast_ref_vector     m_pinned;
        bind_variables     m_bind_variables;
        sort_domain_map    m_sorts;
        func_decl_set      m_preds;
        sym2decl           m_preds_by_name;
        pred2syms          m_argument_var_names;
        rule_set           m_rule_set;
        rule_set           m_transformed_rule_set;
        expr_free_vars     m_free_vars;
        unsigned           m_rule_fmls_head;
        expr_ref_vector    m_rule_fmls;
        svector<symbol>    m_rule_names;
        vector<unsigned>   m_rule_bounds;
        expr_ref_vector    m_background;
        model_converter_ref m_mc;
        proof_converter_ref m_pc;

        rel_context_base*               m_rel;
        scoped_ptr<engine_base>         m_engine;

        bool               m_closed;
        bool               m_saturation_was_run;
        bool               m_enable_bind_variables;
        execution_result   m_last_status;
        expr_ref           m_last_answer;
        expr_ref           m_last_ground_answer;
        DL_ENGINE          m_engine_type;



        bool is_fact(app * head) const;
        bool has_sort_domain(relation_sort s) const;
        sort_domain & get_sort_domain(relation_sort s);
        const sort_domain & get_sort_domain(relation_sort s) const;

        class engine_type_proc;


    public:
        context(ast_manager & m, register_engine_base& re, smt_params& fp, params_ref const& p = params_ref());
        ~context();
        void reset();

        void push();
        void pop();

        bool saturation_was_run() const { return m_saturation_was_run; }
        void notify_saturation_was_run() { m_saturation_was_run = true; }

        void configure_engine(expr* e);

        ast_manager & get_manager() const { return m; }
        rule_manager & get_rule_manager() { return m_rule_manager; }
        smt_params & get_fparams() const { return m_fparams; }
        fp_params const&  get_params() const { return *m_params; }
        DL_ENGINE get_engine(expr* e = nullptr) { configure_engine(e); return m_engine_type; }
        register_engine_base& get_register_engine() { return m_register_engine; }
        th_rewriter& get_rewriter() { return m_rewriter; }
        var_subst & get_var_subst() { return m_var_subst; }
        dl_decl_util & get_decl_util()  { return m_decl_util; }

        bool generate_proof_trace() const;
        bool output_profile() const;
        bool output_tuples() const;
        bool use_map_names() const;
        bool fix_unbound_vars() const;
        symbol default_table() const;
        symbol default_relation() const;
        void set_default_relation(symbol const& s);
        symbol default_table_checker() const;
        symbol check_relation() const;
        bool default_table_checked() const;
        bool dbg_fpr_nonempty_relation_signature() const;
        unsigned dl_profile_milliseconds_threshold() const;
        bool all_or_nothing_deltas() const;
        bool compile_with_widening() const;
        bool unbound_compressor() const;
        void set_unbound_compressor(bool f);
        bool similarity_compressor() const;
        symbol print_aig() const;
        symbol tab_selection() const;
        unsigned similarity_compressor_threshold() const;
        unsigned soft_timeout() const;
        unsigned initial_restart_timeout() const;
        bool generate_explanations() const;
        bool explanations_on_relation_level() const;
        bool magic_sets_for_queries() const;
        bool karr() const;
        bool scale() const;
        bool magic() const;
        bool compress_unbound() const;
        bool quantify_arrays() const;
        bool instantiate_quantifiers() const;
        bool xform_bit_blast() const;
        bool xform_slice() const;
        bool xform_coi() const;
        bool array_blast() const;
        bool array_blast_full() const;
        bool elim_term_ite() const;
        unsigned blast_term_ite_inflation() const;

        void register_finite_sort(sort * s, sort_kind k);

        /**
           Register uninterpreted constant to be used as an implicitly quantified variable.
           The variable gets quantified in the formula passed to rule::mk_rule_from_horn.
        */

        void register_variable(func_decl* var);

        /*
          Replace constants that have been registered as
          variables by de-Bruijn indices and corresponding
          universal (if is_forall is true) or existential
          quantifier.
         */
        expr_ref bind_vars(expr* fml, bool is_forall);

        bool& bind_vars_enabled() { return m_enable_bind_variables; }

        /**
           Register datalog relation.

           If named is true, we associate the predicate with its name, so that it can be
           retrieved by the try_get_predicate_decl() function. Auxiliary predicates introduced
           e.g. by rule transformations do not need to be named.
         */
        void register_predicate(func_decl * pred, bool named);

        /**
           Restrict relations to set of predicates.
         */
        void restrict_predicates(func_decl_set const& preds);

        /**
           \brief Retrieve predicates
        */
        func_decl_set const& get_predicates() const { return m_preds; }
        ast_ref_vector const &get_pinned() const {return m_pinned; }

        bool is_predicate(func_decl* pred) const { return m_preds.contains(pred); }
        bool is_predicate(expr * e) const { return is_app(e) && is_predicate(to_app(e)->get_decl()); }

        /**
           \brief If a predicate name has a \c func_decl object assigned, return pointer to it;
           otherwise return 0.

           Not all \c func_decl object used as relation identifiers need to be assigned to their
           names. Generally, the names coming from the parses are registered here.
        */
        func_decl * try_get_predicate_decl(symbol const& pred_name) const {
            func_decl * res = nullptr;
            m_preds_by_name.find(pred_name, res);
            return res;
        }

        /**
           \brief Create a fresh head predicate declaration.

        */
        func_decl * mk_fresh_head_predicate(symbol const & prefix, symbol const & suffix,
            unsigned arity, sort * const * domain, func_decl* orig_pred=nullptr);


        /**
           \brief Return number of a symbol in a DK_SYMBOL kind sort (\see register_sort() )
         */
        finite_element get_constant_number(relation_sort sort, symbol s);
        /**
           \brief Return number of a symbol in a DK_UINT64 kind sort (\see register_sort() )
         */
        finite_element get_constant_number(relation_sort srt, uint64_t el);

        /**
           \brief Output name of constant with number \c num in sort \c sort.
        */
        void print_constant_name(relation_sort sort, uint64_t num, std::ostream & out);

        bool try_get_sort_constant_count(relation_sort srt, uint64_t & constant_count);

        uint64_t get_sort_size_estimate(relation_sort srt);

        /**
           \brief Assign names of variables used in the declaration of a predicate.

           These names are used when printing out the relations to make the output conform
           to the one of bddbddb.
        */
        void set_argument_names(const func_decl * pred, const svector<symbol> & var_names);
        symbol get_argument_name(const func_decl * pred, unsigned arg_index);

        void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt,
            symbol const *  relation_names);

        void set_output_predicate(func_decl * pred) { m_rule_set.set_output_predicate(pred); }

        rule_set & get_rules() { flush_add_rules(); return m_rule_set; }

        void get_rules_as_formulas(expr_ref_vector& fmls, expr_ref_vector& qs, svector<symbol>& names);
        void get_raw_rule_formulas(expr_ref_vector& fmls, svector<symbol>& names, unsigned_vector &bounds);

        void add_fact(app * head);
        void add_fact(func_decl * pred, const relation_fact & fact);

        bool has_facts(func_decl * pred) const;

        void add_rule(rule_ref& r);

        void assert_expr(expr* e);
        expr_ref get_background_assertion();
        unsigned get_num_assertions() { return m_background.size(); }
        expr*    get_assertion(unsigned i) const { return m_background[i]; }

        /**
           Method exposed from API for adding rules.
        */
        void add_rule(expr* rl, symbol const& name, unsigned bound = UINT_MAX);


        /**
           Update a named rule.
         */
        void update_rule(expr* rl, symbol const& name);

        /**
           Retrieve the maximal number of relevant unfoldings of 'pred'
           with respect to the current state.
         */
        unsigned get_num_levels(func_decl* pred);

        /**
            Retrieve reachable facts of 'pred'.
         */
        expr_ref get_reachable(func_decl *pred);
        /**
           Retrieve the current cover of 'pred' up to 'level' unfoldings.
           Return just the delta that is known at 'level'. To
           obtain the full set of properties of 'pred' one should query
           at 'level+1', 'level+2' etc, and include level=-1.
        */
        expr_ref get_cover_delta(int level, func_decl* pred);

        /**
           Add a property of predicate 'pred' at 'level'.
           It gets pushed forward when possible.
         */
        void add_cover(int level, func_decl* pred, expr* property);

        /**
          Add an invariant of predicate 'pred'.
         */
        void add_invariant (func_decl *pred, expr *property);

        /**
           \brief Check rule subsumption.
        */
        bool check_subsumes(rule const& stronger_rule, rule const& weaker_rule);

        /**
          \brief Check if rule is well-formed according to engine.
        */
        void check_rules(rule_set& r);

        /**
           \brief Return true if facts to \c pred can be added using the \c add_table_fact() function.

           This function should return true if \c pred is represented by a table_relation
           and there is no transformation of relation values before they are put into the
           table.
         */
        void add_table_fact(func_decl * pred, const table_fact & fact);
        void add_table_fact(func_decl * pred, unsigned num_args, unsigned args[]);

        /**
           \brief To be called after all rules are added.
        */
        void close();
        void ensure_closed();
        bool is_closed() { return m_closed; }

        /**
           \brief Undo the effect of the \c close operation.
         */
        void reopen();
        void ensure_opened();

        model_converter_ref& get_model_converter() { return m_mc; }
        void add_model_converter(model_converter* mc) { m_mc = concat(m_mc.get(), mc); }
        proof_converter_ref& get_proof_converter() { return m_pc; }
        void add_proof_converter(proof_converter* pc) { m_pc = concat(m_pc.get(), pc); }

        void transform_rules(rule_transformer& transf);
        void transform_rules(rule_transformer::plugin* plugin);
        void replace_rules(rule_set const& rs);
        void record_transformed_rules();

        void apply_default_transformation();

        void collect_params(param_descrs& r);

        void updt_params(params_ref const& p);

        void display_rules(std::ostream & out) const {
            m_rule_set.display(out);
        }

        void display(std::ostream & out) const;

        void display_smt2(unsigned num_queries, expr* const* qs, std::ostream& out);

        void display_profile(std::ostream& out) const;

        // -----------------------------------
        //
        // basic usage methods
        //
        // -----------------------------------

        bool canceled() {
            return !m.inc() && (m_last_status = CANCELED, true);
        }

        void cleanup();

        /**
           \brief check if query 'q' is satisfied under asserted rules and background.

           If successful, return OK and into \c result assign a relation with all
           tuples matching the query. Otherwise return reason for failure and do not modify
           \c result.

           The numbers of variables in the query body must form a contiguous sequence
           starting from zero.

           The caller becomes an owner of the relation object returned in \c result. The
           relation object, however, should not outlive the datalog context since it is
           linked to a relation plugin in the context.
         */

        lbool query(expr* q);

        lbool query_from_lvl (expr* q, unsigned lvl);
        /**
           \brief retrieve model from inductive invariant that shows query is unsat.

           \pre engine == 'pdr' || engine == 'duality' - this option is only supported
           for PDR mode and Duality mode.
         */
        model_ref get_model();

        bool is_monotone();

        /**
           \brief retrieve proof from derivation of the query.

           \pre engine == 'pdr'  || engine == 'duality'- this option is only supported
           for PDR mode and Duality mode.
         */
        proof_ref get_proof();


        /**
           Query multiple output relations.
        */
        lbool rel_query(unsigned num_rels, func_decl * const* rels);


        /**
           \brief retrieve last proof status.
        */
        execution_result get_status();

        void set_status(execution_result r) { m_last_status = r; }

        /**
           \brief retrieve formula corresponding to query that returns l_true.
           The formula describes one or more instances of the existential variables
           in the query that are derivable.
        */
        expr* get_answer_as_formula();
        /**
         * get bottom-up (from query) sequence of ground predicate instances
         * (for e.g. P(0,1,0,0,3)) that together form a ground derivation to query
         */
        expr* get_ground_sat_answer ();

        /**
         * \brief obtain the sequence of rules along the counterexample trace
         */
        void get_rules_along_trace (rule_ref_vector& rules);

        void get_rules_along_trace_as_formulas (expr_ref_vector& rules, svector<symbol>& names);


        void collect_statistics(statistics& st) const;

        void reset_statistics();

        /**
           \brief Display a certificate for reachability and/or unreachability.
        */
        std::ostream& display_certificate(std::ostream& out);

        /**
           \brief query result if it contains fact.
         */
        bool result_contains_fact(relation_fact const& f);

        rel_context_base* get_rel_context() { ensure_engine(); return m_rel; }

        void add_callback(void *state,
                          const datalog::t_new_lemma_eh new_lemma_eh,
                          const datalog::t_predecessor_eh predecessor_eh,
                          const datalog::t_unfold_eh unfold_eh) {
            ensure_engine();
            m_engine->add_callback(state, new_lemma_eh, predecessor_eh, unfold_eh);
        }

        void add_constraint (expr *c, unsigned lvl){
            ensure_engine();
            m_engine->add_constraint(c, lvl);
        }

    private:

        /**
           Just reset all tables.
        */
        void reset_tables();

        void flush_add_rules();

        void ensure_engine(expr* e = nullptr);

        // auxiliary functions for SMT2 pretty-printer.
        void declare_vars(expr_ref_vector& rules, mk_fresh_name& mk_fresh, std::ostream& out);

        //undefined and private copy constructor and operator=
        context(const context&);
        context& operator=(const context&);

        bool is_query(expr* e);
        void display_rel_decl(std::ostream& out, func_decl* f);
    };

};