z3-src 503.0.0

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
/*++
Copyright (c) 2006 Microsoft Corporation

Module Name:

    smt_justification.h

Abstract:

    Proof-like objects for tracking dependencies in the SMT engine, and generating proofs.

Author:

    Leonardo de Moura (leonardo) 2008-02-18.

Revision History:

--*/
#pragma once

#include "ast/ast.h"
#include "smt/smt_types.h"
#include "smt/smt_literal.h"
#include "smt/smt_eq_justification.h"

namespace smt {
    
    class conflict_resolution;
    class context;

    typedef ptr_vector<justification> justification_vector;

    /**
       \brief Pseudo-proof objects. They are mainly used to track dependencies.
       When proof generation is enabled, they are also used to produce proofs.
       
       Justification objects are allocated using a stack based policy.
       Actually, there is one exception: justification of lemmas. 
       Lemmas created at scope level n may remain alive even after scope level n is backtracked.
       Lemmas are deleted by a GC that runs from time to time. So, a justification attached
       to a lemma will may remain alive after scope level n is backtracked.
       
       So, I allow justification objects to be allocated in regions and
       in the regular heap. The method in_region() should return true if the object is
       allocated in a region. 
    */
    class justification {
        unsigned m_mark:1;
        unsigned m_in_region:1; // true if the object was allocated in a region.
    public:
        justification(bool in_region = true):m_mark(false), m_in_region(in_region) {}
        virtual ~justification() = default;

        /**
           \brief This method should return true if the method del_eh needs to be invoked 
           to free resources.
        */
        virtual bool has_del_eh() const {
            return false; 
        }

        /**
           \brief Free the resources allocated by this object.
        */
        virtual void del_eh(ast_manager & m) {
        }

        /**
           \brief Mark the antecedents the justification object.
           The antecedents are marked using the mark methods of the 
           conflict_resolution object.
        */
        virtual void get_antecedents(conflict_resolution & cr){
        }

        /**
           \brief Return the id of the theory that produced the proof object.
        */
        virtual theory_id get_from_theory() const {
            return null_theory_id;
        }

        void set_mark() { SASSERT(!m_mark); m_mark = true; }

        void unset_mark() { SASSERT(m_mark); m_mark = false; }

        bool is_marked() const { return m_mark; }
        
        unsigned hash() const { return get_ptr_hash(this); }

        virtual proof * mk_proof(conflict_resolution & cr) = 0;

        bool in_region() const { return m_in_region; }

        virtual char const * get_name() const { return "unknown"; }
        
        virtual void display_debug_info(conflict_resolution & cr, std::ostream & out) { /* do nothing */ }

    };

    class justification_proof_wrapper : public justification {
        proof * m_proof;
    public:
        justification_proof_wrapper(context & ctx, proof * pr, bool in_region = true);

        bool has_del_eh() const override {
            return true;
        }
        
        void del_eh(ast_manager & m) override;
        
        proof * mk_proof(conflict_resolution & cr) override;
        
        char const * get_name() const override { return "proof-wrapper"; }
    };

    class unit_resolution_justification : public justification {
        justification * m_antecedent;
        unsigned        m_num_literals;
        literal *       m_literals;
    public:
        unit_resolution_justification(context& ctx, justification * js, unsigned num_lits, literal const * lits);

        unit_resolution_justification(justification * js, unsigned num_lits, literal const * lits);

        ~unit_resolution_justification() override;

        bool has_del_eh() const override {
            return !in_region() && m_antecedent && m_antecedent->has_del_eh();
        }
        
        void del_eh(ast_manager & m) override {
            if (!in_region() && m_antecedent) m_antecedent->del_eh(m); 
        }

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "unit-resolution"; }

    };

    class eq_conflict_justification : public justification {
        enode *          m_node1;
        enode *          m_node2;
        eq_justification m_js;
    public:
        eq_conflict_justification(enode * n1, enode * n2, eq_justification js):
            m_node1(n1),
            m_node2(n2),
            m_js(js) {
        }

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "eq-conflict"; }
    };
    
    /**
       \brief Justification for m_node = root
    */
    class eq_root_propagation_justification : public justification {
        enode *         m_node;
    public:
        eq_root_propagation_justification(enode * n):m_node(n) {
        }

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "eq-root"; }
    };        

    /**
       \brief Justification for m_node1 = m_node2
    */
    class eq_propagation_justification : public justification {
        enode *         m_node1;
        enode *         m_node2;
    public:
        eq_propagation_justification(enode * n1, enode * n2):m_node1(n1), m_node2(n2) {
        }

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "eq-propagation"; }
    };        

    /**
       \brief Justification for p(x) <=> p(y), p(x)  ===>  p(y)
    */
    class mp_iff_justification : public justification {
        enode *         m_node1;  // p(x)
        enode *         m_node2;  // p(y)
    public:
        mp_iff_justification(enode * n1, enode * n2):m_node1(n1), m_node2(n2) {
        }

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "mp-iff"; }
    };

    /**
       \brief Abstract class for justifications that contains set of literals.
    */
    class simple_justification : public justification {
    protected:
        unsigned        m_num_literals;
        literal *       m_literals;
        
        bool antecedent2proof(conflict_resolution & cr, ptr_buffer<proof> & result);

    public:
        simple_justification(context& ctx, unsigned num_lits, literal const * lits);

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override = 0;

        char const * get_name() const override { return "simple"; }

    };

    class simple_theory_justification : public simple_justification {
    protected:
        family_id      m_th_id;
        vector<parameter> m_params;
    public:
        simple_theory_justification(
            family_id fid, context& ctx, 
            unsigned num_lits, literal const * lits,
            unsigned num_params, parameter* params):
            simple_justification(ctx, num_lits, lits),
            m_th_id(fid), m_params(num_params, params) {}

        bool has_del_eh() const override { return !m_params.empty(); }

        void del_eh(ast_manager & m) override { m_params.reset(); }

        theory_id get_from_theory() const override { return m_th_id; }
 
    };

    class theory_axiom_justification : public simple_theory_justification {
    public:

        theory_axiom_justification(family_id fid, context& ctx,
                                   unsigned num_lits, literal const * lits, 
                                   unsigned num_params = 0, parameter* params = nullptr):
            simple_theory_justification(fid, ctx, num_lits, lits, num_params, params)  {}
        
        void get_antecedents(conflict_resolution & cr) override {}

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "theory-axiom"; }
    };

    class theory_propagation_justification : public simple_theory_justification {
        literal        m_consequent;
        void log(context& ctx);
    public:
        theory_propagation_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits, literal consequent, 
                                         unsigned num_params = 0, parameter* params = nullptr):
            simple_theory_justification(fid, ctx, num_lits, lits, num_params, params), m_consequent(consequent) { log(ctx); }

        proof * mk_proof(conflict_resolution & cr) override;


        char const * get_name() const override { return "theory-propagation"; }
        
    };
     
    class theory_conflict_justification : public simple_theory_justification {
        void log(context& ctx);
    public:
        theory_conflict_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits, 
                                      unsigned num_params = 0, parameter* params = nullptr):
            simple_theory_justification(fid, ctx, num_lits, lits, num_params, params) { log(ctx); }

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "theory-conflict"; }
    };

    /**
       \brief Abstract class for justifications that contains set of literals and equalities.
    */
    class ext_simple_justification : public simple_justification {
    protected:
        unsigned        m_num_eqs;
        enode_pair *    m_eqs;
        
        bool antecedent2proof(conflict_resolution & cr, ptr_buffer<proof> & result);

    public:
        ext_simple_justification(context& ctx, unsigned num_lits, literal const * lits, 
                                 unsigned num_eqs, enode_pair const * eqs);

        void get_antecedents(conflict_resolution & cr) override;

        proof * mk_proof(conflict_resolution & cr) override = 0;

        char const * get_name() const override { return "ext-simple"; }
    };

    /**
       \brief Abstract class for justifications that contains set of literals and equalities.
    */
    class ext_theory_simple_justification : public ext_simple_justification {
    protected:
        family_id m_th_id;
        vector<parameter> m_params;

    public:
        ext_theory_simple_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits, 
                                        unsigned num_eqs, enode_pair const * eqs, 
                                        unsigned num_params = 0, parameter* params = nullptr):
            ext_simple_justification(ctx, num_lits, lits, num_eqs, eqs), m_th_id(fid), m_params(num_params, params) {}

        bool has_del_eh() const override { return !m_params.empty(); }

        void del_eh(ast_manager & m) override { m_params.reset(); }

        theory_id get_from_theory() const override { return m_th_id; }
    };

    class ext_theory_propagation_justification : public ext_theory_simple_justification {
        literal        m_consequent;
        void log(context& ctx);
    public:
        ext_theory_propagation_justification(family_id fid, context & ctx, 
                                             unsigned num_lits, literal const * lits, 
                                             unsigned num_eqs, enode_pair const * eqs,
                                             literal consequent,
                                             unsigned num_params = 0, parameter* params = nullptr):
            ext_theory_simple_justification(fid, ctx, num_lits, lits, num_eqs, eqs, num_params, params), 
            m_consequent(consequent) {
            log(ctx);
        }

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "ext-theory-propagation"; }
        
    };

    class ext_theory_conflict_justification : public ext_theory_simple_justification {
        void log(context& ctx);
    public:
        ext_theory_conflict_justification(family_id fid, context& ctx, unsigned num_lits, literal const * lits, 
                                          unsigned num_eqs, enode_pair const * eqs,
                                          unsigned num_params = 0, parameter* params = nullptr):
            ext_theory_simple_justification(fid, ctx, num_lits, lits, num_eqs, eqs, num_params, params) {
            log(ctx);
        }

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "ext-theory-conflict"; }
    };

    class ext_theory_eq_propagation_justification : public ext_theory_simple_justification {
        enode *        m_lhs;
        enode *        m_rhs;
        void log(context& ctx);
    public:
        ext_theory_eq_propagation_justification(
            family_id fid, context& ctx, 
            unsigned num_lits, literal const * lits, 
            unsigned num_eqs, enode_pair const * eqs,
            enode * lhs, enode * rhs,
            unsigned num_params = 0, parameter* params = nullptr):
            ext_theory_simple_justification(fid, ctx, num_lits, lits, num_eqs, eqs, num_params, params), m_lhs(lhs), m_rhs(rhs) { log(ctx); }

        ext_theory_eq_propagation_justification(
            family_id fid, context& ctx, 
            enode * lhs, enode * rhs):
            ext_theory_simple_justification(fid, ctx, 0, nullptr, 0, nullptr, 0, nullptr), m_lhs(lhs), m_rhs(rhs) { log(ctx); }

        
        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "ext-theory-eq-propagation"; }
    };  

    /**
       \brief A theory lemma is similar to a theory axiom, but it is attached to a CLS_AUX_LEMMA clause instead of CLS_AUX.
       So, it cannot be stored in the heap, and it is unsafe to store literals, since it may be deleted during backtracking.
       Instead, they store a set of pairs (sign, expr). This pair is represented as a tagged pointer.
    */
    class theory_lemma_justification : public justification {
        family_id    m_th_id;
        vector<parameter> m_params;
        unsigned     m_num_literals;
        expr **      m_literals;
        
    public:
        theory_lemma_justification(family_id fid, context & ctx, unsigned num_lits, literal const * lits, 
                                   unsigned num_params = 0, parameter* params = nullptr);

        ~theory_lemma_justification() override;

        bool has_del_eh() const override {
            return true;
        }
        
        void del_eh(ast_manager & m) override;
        
        void get_antecedents(conflict_resolution & cr) override {}

        proof * mk_proof(conflict_resolution & cr) override;

        char const * get_name() const override { return "theory-lemma"; }
    };
      
}