3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-22 02:57:50 +00:00

wip - alpha support for polymorphism

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.
This commit is contained in:
Nikolaj Bjorner 2023-07-12 18:09:02 -07:00
parent d6f2c23627
commit 939bf1c725
16 changed files with 987 additions and 42 deletions

View file

@ -38,6 +38,7 @@ Revision History:
#include "smt/theory_pb.h"
#include "smt/theory_fpa.h"
#include "smt/theory_str.h"
#include "smt/theory_polymorphism.h"
namespace smt {
@ -788,6 +789,11 @@ namespace smt {
m_context.register_plugin(alloc(smt::theory_special_relations, m_context, m_manager));
}
void setup::setup_polymorphism() {
if (m_manager.has_type_vars())
m_context.register_plugin(alloc(theory_polymorphism, m_context));
}
void setup::setup_unknown() {
static_features st(m_manager);
ptr_vector<expr> fmls;
@ -803,6 +809,7 @@ namespace smt {
setup_seq_str(st);
setup_fpa();
setup_special_relations();
setup_polymorphism();
}
void setup::setup_unknown(static_features & st) {
@ -819,6 +826,7 @@ namespace smt {
setup_fpa();
setup_recfuns();
setup_special_relations();
setup_polymorphism();
return;
}

View file

@ -82,6 +82,7 @@ namespace smt {
void setup_LRA();
void setup_CSP();
void setup_special_relations();
void setup_polymorphism();
void setup_AUFLIA(bool simple_array = true);
void setup_AUFLIA(static_features const & st);
void setup_AUFLIRA(bool simple_array = true);

View file

@ -0,0 +1,105 @@
/*++
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 { }
};
};