mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	An initial update to support polymorphism from SMTLIB3 and the API (so far C, Python). The WIP SMTLIB3 format is assumed to be supporting the following declaration ``` (declare-type-var A) ``` Whenever A is used in a type signature of a function/constant or bound quantified variable, it is taken to mean that all instantiations of A are included in the signature and assertions. For example, if the function f is declared with signature A -> A, then there is a version of f for all instances of A. The semantics of polymorphism appears to follow previous proposals: the instances are effectively different functions. This may clash with some other notions, such as the type signature forall 'a . 'a -> 'a would be inhabited by a unique function (the identity), while this is not enforced in this version (and hopefully never because it is more busy work). The C API has the function 'Z3_mk_type_variable' to create a type variable and applying functions modulo polymorphic type signatures is possible. The kind Z3_TYPE_VAR is added to sort discriminators. This version is considered as early alpha. It passes a first rudimentary unit test involving quantified axioms, declare-fun, define-fun, and define-fun-rec.
		
			
				
	
	
		
			105 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*++
 | |
| Copyright (c) 2023 Microsoft Corporation
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|     theory_polymorphism.h
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|     Plugin for handling polymorphism 
 | |
|     The plugin instantiates polymorphic axioms based on occurrences of polymorphic functions in other axioms.
 | |
|     It uses blocking literals to restart search when there are new axioms that can be instantiated.
 | |
| 
 | |
| Author:
 | |
| 
 | |
|     Nikolaj Bjorner (nbjorner) 2013-07-11
 | |
| 
 | |
| --*/
 | |
| #pragma once
 | |
| 
 | |
| #include "ast/polymorphism_inst.h"
 | |
| #include "smt/smt_theory.h"
 | |
| 
 | |
| namespace smt {
 | |
| 
 | |
|     class theory_polymorphism : public theory {
 | |
|         trail_stack        m_trail;
 | |
|         polymorphism::inst m_inst;
 | |
|         expr_ref           m_assumption;
 | |
|         unsigned           m_qhead = 0;
 | |
|         bool               m_pending = true;
 | |
|         
 | |
|         bool internalize_atom(app*, bool) override { return false; }
 | |
|         bool internalize_term(app*) override { return false; }
 | |
|         void new_eq_eh(theory_var, theory_var) override { }
 | |
|         void new_diseq_eh(theory_var, theory_var) override {}
 | |
|         theory* mk_fresh(context* new_ctx) override { return alloc(theory_polymorphism, *new_ctx); }
 | |
|         char const * get_name() const override { return "polymorphism"; }
 | |
|         void display(std::ostream& out) const override {}
 | |
| 
 | |
|         void push_scope_eh() override {
 | |
|             m_trail.push_scope();
 | |
|         }
 | |
| 
 | |
|         void pop_scope_eh(unsigned n) override {
 | |
|             m_trail.pop_scope(n);
 | |
|         }
 | |
| 
 | |
|         bool can_propagate() override {
 | |
|             return m_pending;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|         * Assert instances of polymorphic axioms
 | |
|         */
 | |
|         void propagate() override {
 | |
|             if (!m_pending)
 | |
|                 return;
 | |
|             m_pending = false;
 | |
|             vector<polymorphism::instantiation> instances;
 | |
|             m_inst.instantiate(instances);
 | |
|             if (instances.empty())
 | |
|                 return;
 | |
|             for (auto const& [orig, inst, sub] : instances) 
 | |
|                 ctx.add_asserted(inst);
 | |
|             ctx.internalize_assertions();
 | |
|         }
 | |
| 
 | |
|         final_check_status final_check_eh() override {
 | |
|             if (m_inst.pending()) 
 | |
|                 ctx.assign(~mk_literal(m_assumption), nullptr);
 | |
|             return FC_DONE;
 | |
|         }
 | |
| 
 | |
|         void add_theory_assumptions(expr_ref_vector & assumptions) override {
 | |
|             if (m_qhead == ctx.get_num_asserted_formulas())
 | |
|                 return;
 | |
|             m_assumption = m.mk_fresh_const("poly", m.mk_bool_sort());
 | |
|             assumptions.push_back(m_assumption);
 | |
|             ctx.push_trail(value_trail(m_qhead));
 | |
|             for (; m_qhead < ctx.get_num_asserted_formulas(); ++m_qhead)
 | |
|                 m_inst.add(ctx.get_asserted_formula(m_qhead));
 | |
|             m_pending = true;
 | |
|         }
 | |
| 
 | |
|         bool should_research(expr_ref_vector & assumptions) override {
 | |
|             for (auto * a : assumptions)
 | |
|                 if (a == m_assumption)
 | |
|                     return true;
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
| 
 | |
|     public:
 | |
|         theory_polymorphism(context& ctx):
 | |
|             theory(ctx, poly_family_id),
 | |
|             m_inst(ctx.get_manager(), m_trail),
 | |
|             m_assumption(ctx.get_manager()) {}
 | |
|         
 | |
|         void init_model(model_generator & mg) override { }
 | |
|     };
 | |
| 
 | |
| };
 | |
| 
 | |
| 
 |