mirror of
https://github.com/Z3Prover/z3
synced 2026-02-20 15:34:41 +00:00
Implement finite_set_decl_plugin with complete operator support and polymorphism infrastructure (#7961)
* Initial plan * Implement finite_sets_decl_plugin with all specified operations Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Add tests for finite_sets_decl_plugin Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Add set.singleton operator to finite_sets_decl_plugin Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Refactor finite_sets_decl_plugin to use polymorphic signatures and Array sorts Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Rename finite_sets to finite_set everywhere including file names Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Rename set.filter to set.select Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Refactor finite_set_decl_plugin to use polymorphism_util Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Move psig and match method to polymorphism_util Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Add MATCH macros and fix is_fully_interp return value Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> * Add is_finite_set helper and parameter count validation Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
parent
7356b5ff88
commit
df4052ec69
9 changed files with 572 additions and 0 deletions
188
src/ast/finite_set_decl_plugin.h
Normal file
188
src/ast/finite_set_decl_plugin.h
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/*++
|
||||
Copyright (c) 2025 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
finite_set_decl_plugin.h
|
||||
|
||||
Abstract:
|
||||
Declaration plugin for finite sets signatures
|
||||
|
||||
Sort:
|
||||
FiniteSet(S)
|
||||
|
||||
Operators:
|
||||
set.empty : (FiniteSet S)
|
||||
set.singleton : S -> (FiniteSet S)
|
||||
set.union : (FiniteSet S) (FiniteSet S) -> (FiniteSet S)
|
||||
set.intersect : (FiniteSet S) (FiniteSet S) -> (FiniteSet S)
|
||||
set.difference : (FiniteSet S) (FiniteSet S) -> (FiniteSet S)
|
||||
set.in : S (FiniteSet S) -> Bool
|
||||
set.size : (FiniteSet S) -> Int
|
||||
set.subset : (FiniteSet S) (FiniteSet S) -> Bool
|
||||
set.map : (S -> T) (FiniteSet S) -> (FiniteSet T)
|
||||
set.select : (S -> Bool) (FiniteSet S) -> (FiniteSet S)
|
||||
set.range : Int Int -> (FiniteSet Int)
|
||||
|
||||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "ast/ast.h"
|
||||
#include "ast/polymorphism_util.h"
|
||||
|
||||
enum finite_set_sort_kind {
|
||||
FINITE_SET_SORT
|
||||
};
|
||||
|
||||
enum finite_set_op_kind {
|
||||
OP_FINITE_SET_EMPTY,
|
||||
OP_FINITE_SET_SINGLETON,
|
||||
OP_FINITE_SET_UNION,
|
||||
OP_FINITE_SET_INTERSECT,
|
||||
OP_FINITE_SET_DIFFERENCE,
|
||||
OP_FINITE_SET_IN,
|
||||
OP_FINITE_SET_SIZE,
|
||||
OP_FINITE_SET_SUBSET,
|
||||
OP_FINITE_SET_MAP,
|
||||
OP_FINITE_SET_SELECT,
|
||||
OP_FINITE_SET_RANGE,
|
||||
LAST_FINITE_SET_OP
|
||||
};
|
||||
|
||||
class finite_set_decl_plugin : public decl_plugin {
|
||||
ptr_vector<polymorphism::psig> m_sigs;
|
||||
bool m_init;
|
||||
|
||||
void init();
|
||||
func_decl * mk_empty(sort* element_sort);
|
||||
func_decl * mk_finite_set_op(decl_kind k, unsigned arity, sort * const * domain, sort* range);
|
||||
sort * get_element_sort(sort* finite_set_sort) const;
|
||||
bool is_finite_set(sort* s) const;
|
||||
|
||||
public:
|
||||
finite_set_decl_plugin();
|
||||
~finite_set_decl_plugin() override;
|
||||
|
||||
decl_plugin * mk_fresh() override {
|
||||
return alloc(finite_set_decl_plugin);
|
||||
}
|
||||
|
||||
void finalize() override {
|
||||
for (polymorphism::psig* s : m_sigs)
|
||||
dealloc(s);
|
||||
m_sigs.reset();
|
||||
}
|
||||
|
||||
//
|
||||
// Contract for sort:
|
||||
// parameters[0] - element sort
|
||||
//
|
||||
sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) override;
|
||||
|
||||
//
|
||||
// Contract for func_decl:
|
||||
// For OP_FINITE_SET_MAP and OP_FINITE_SET_FILTER:
|
||||
// parameters[0] - function declaration
|
||||
// For others:
|
||||
// no parameters
|
||||
func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range) override;
|
||||
|
||||
void get_op_names(svector<builtin_name> & op_names, symbol const & logic) override;
|
||||
|
||||
void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic) override;
|
||||
|
||||
expr * get_some_value(sort * s) override;
|
||||
|
||||
bool is_fully_interp(sort * s) const override;
|
||||
|
||||
bool is_value(app * e) const override;
|
||||
|
||||
bool is_unique_value(app* e) const override;
|
||||
};
|
||||
|
||||
class finite_set_recognizers {
|
||||
protected:
|
||||
family_id m_fid;
|
||||
public:
|
||||
finite_set_recognizers(family_id fid):m_fid(fid) {}
|
||||
family_id get_family_id() const { return m_fid; }
|
||||
bool is_finite_set(sort* s) const { return is_sort_of(s, m_fid, FINITE_SET_SORT); }
|
||||
bool is_finite_set(expr const* n) const { return is_finite_set(n->get_sort()); }
|
||||
bool is_empty(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_EMPTY); }
|
||||
bool is_singleton(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_SINGLETON); }
|
||||
bool is_union(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_UNION); }
|
||||
bool is_intersect(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_INTERSECT); }
|
||||
bool is_difference(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_DIFFERENCE); }
|
||||
bool is_in(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_IN); }
|
||||
bool is_size(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_SIZE); }
|
||||
bool is_subset(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_SUBSET); }
|
||||
bool is_map(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_MAP); }
|
||||
bool is_select(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_SELECT); }
|
||||
bool is_range(expr const* n) const { return is_app_of(n, m_fid, OP_FINITE_SET_RANGE); }
|
||||
|
||||
MATCH_UNARY(is_singleton);
|
||||
MATCH_UNARY(is_size);
|
||||
MATCH_BINARY(is_union);
|
||||
MATCH_BINARY(is_intersect);
|
||||
MATCH_BINARY(is_difference);
|
||||
MATCH_BINARY(is_in);
|
||||
MATCH_BINARY(is_subset);
|
||||
MATCH_BINARY(is_map);
|
||||
MATCH_BINARY(is_select);
|
||||
MATCH_BINARY(is_range);
|
||||
};
|
||||
|
||||
class finite_set_util : public finite_set_recognizers {
|
||||
ast_manager& m_manager;
|
||||
public:
|
||||
finite_set_util(ast_manager& m):
|
||||
finite_set_recognizers(m.mk_family_id("finite_set")), m_manager(m) {}
|
||||
|
||||
ast_manager& get_manager() const { return m_manager; }
|
||||
|
||||
app * mk_empty(sort* element_sort) {
|
||||
parameter param(element_sort);
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_EMPTY, 1, ¶m, 0, nullptr);
|
||||
}
|
||||
|
||||
app * mk_singleton(expr* elem) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_SINGLETON, elem);
|
||||
}
|
||||
|
||||
app * mk_union(expr* s1, expr* s2) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_UNION, s1, s2);
|
||||
}
|
||||
|
||||
app * mk_intersect(expr* s1, expr* s2) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_INTERSECT, s1, s2);
|
||||
}
|
||||
|
||||
app * mk_difference(expr* s1, expr* s2) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_DIFFERENCE, s1, s2);
|
||||
}
|
||||
|
||||
app * mk_in(expr* elem, expr* set) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_IN, elem, set);
|
||||
}
|
||||
|
||||
app * mk_size(expr* set) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_SIZE, set);
|
||||
}
|
||||
|
||||
app * mk_subset(expr* s1, expr* s2) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_SUBSET, s1, s2);
|
||||
}
|
||||
|
||||
app * mk_map(expr* arr, expr* set) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_MAP, arr, set);
|
||||
}
|
||||
|
||||
app * mk_select(expr* arr, expr* set) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_SELECT, arr, set);
|
||||
}
|
||||
|
||||
app * mk_range(expr* low, expr* high) {
|
||||
return m_manager.mk_app(m_fid, OP_FINITE_SET_RANGE, low, high);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue