mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 03:32:28 +00:00 
			
		
		
		
	Add C API for finite sets
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									68d18c6125
								
							
						
					
					
						commit
						064f7e3088
					
				
					 5 changed files with 275 additions and 0 deletions
				
			
		|  | @ -44,6 +44,7 @@ z3_add_component(api | ||||||
|     api_context.cpp |     api_context.cpp | ||||||
|     api_datalog.cpp |     api_datalog.cpp | ||||||
|     api_datatype.cpp |     api_datatype.cpp | ||||||
|  |     api_finite_set.cpp | ||||||
|     api_fpa.cpp |     api_fpa.cpp | ||||||
|     api_goal.cpp |     api_goal.cpp | ||||||
|     api_log.cpp |     api_log.cpp | ||||||
|  |  | ||||||
|  | @ -133,6 +133,7 @@ namespace api { | ||||||
|         m_fpa_util(m()), |         m_fpa_util(m()), | ||||||
|         m_sutil(m()), |         m_sutil(m()), | ||||||
|         m_recfun(m()), |         m_recfun(m()), | ||||||
|  |         m_finite_set_util(m()), | ||||||
|         m_ast_trail(m()), |         m_ast_trail(m()), | ||||||
|         m_pmanager(m_limit) { |         m_pmanager(m_limit) { | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ Revision History: | ||||||
| #include "ast/fpa_decl_plugin.h" | #include "ast/fpa_decl_plugin.h" | ||||||
| #include "ast/recfun_decl_plugin.h" | #include "ast/recfun_decl_plugin.h" | ||||||
| #include "ast/special_relations_decl_plugin.h" | #include "ast/special_relations_decl_plugin.h" | ||||||
|  | #include "ast/finite_set_decl_plugin.h" | ||||||
| #include "ast/rewriter/seq_rewriter.h" | #include "ast/rewriter/seq_rewriter.h" | ||||||
| #include "params/smt_params.h" | #include "params/smt_params.h" | ||||||
| #include "smt/smt_kernel.h" | #include "smt/smt_kernel.h" | ||||||
|  | @ -77,6 +78,7 @@ namespace api { | ||||||
|         fpa_util                   m_fpa_util; |         fpa_util                   m_fpa_util; | ||||||
|         seq_util                   m_sutil; |         seq_util                   m_sutil; | ||||||
|         recfun::util               m_recfun; |         recfun::util               m_recfun; | ||||||
|  |         finite_set_util            m_finite_set_util; | ||||||
| 
 | 
 | ||||||
|         // Support for old solver API
 |         // Support for old solver API
 | ||||||
|         smt_params                 m_fparams; |         smt_params                 m_fparams; | ||||||
|  | @ -146,6 +148,7 @@ namespace api { | ||||||
|         datatype_util& dtutil() { return m_dt_plugin->u(); } |         datatype_util& dtutil() { return m_dt_plugin->u(); } | ||||||
|         seq_util& sutil() { return m_sutil; } |         seq_util& sutil() { return m_sutil; } | ||||||
|         recfun::util& recfun() { return m_recfun; } |         recfun::util& recfun() { return m_recfun; } | ||||||
|  |         finite_set_util& fsutil() { return m_finite_set_util; } | ||||||
|         family_id get_basic_fid() const { return basic_family_id; } |         family_id get_basic_fid() const { return basic_family_id; } | ||||||
|         family_id get_array_fid() const { return m_array_fid; } |         family_id get_array_fid() const { return m_array_fid; } | ||||||
|         family_id get_arith_fid() const { return arith_family_id; } |         family_id get_arith_fid() const { return arith_family_id; } | ||||||
|  |  | ||||||
							
								
								
									
										169
									
								
								src/api/api_finite_set.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/api/api_finite_set.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,169 @@ | ||||||
|  | /*++
 | ||||||
|  | Copyright (c) 2025 Microsoft Corporation | ||||||
|  | 
 | ||||||
|  | Module Name: | ||||||
|  | 
 | ||||||
|  |     api_finite_set.cpp | ||||||
|  | 
 | ||||||
|  | Abstract: | ||||||
|  | 
 | ||||||
|  |     API for finite sets. | ||||||
|  | 
 | ||||||
|  | Author: | ||||||
|  | 
 | ||||||
|  |     Copilot 2025-01-21 | ||||||
|  | 
 | ||||||
|  | Revision History: | ||||||
|  | 
 | ||||||
|  | --*/ | ||||||
|  | #include "api/z3.h" | ||||||
|  | #include "api/api_log_macros.h" | ||||||
|  | #include "api/api_context.h" | ||||||
|  | #include "api/api_util.h" | ||||||
|  | #include "ast/ast_pp.h" | ||||||
|  | 
 | ||||||
|  | extern "C" { | ||||||
|  | 
 | ||||||
|  |     Z3_sort Z3_API Z3_mk_finite_set_sort(Z3_context c, Z3_sort elem_sort) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_sort(c, elem_sort); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         parameter param(to_sort(elem_sort)); | ||||||
|  |         sort* ty = mk_c(c)->m().mk_sort(mk_c(c)->fsutil().get_family_id(), FINITE_SET_SORT, 1, ¶m); | ||||||
|  |         mk_c(c)->save_ast_trail(ty); | ||||||
|  |         RETURN_Z3(of_sort(ty)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool Z3_API Z3_is_finite_set_sort(Z3_context c, Z3_sort s) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_is_finite_set_sort(c, s); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         return mk_c(c)->fsutil().is_finite_set(to_sort(s)); | ||||||
|  |         Z3_CATCH_RETURN(false); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_sort Z3_API Z3_get_finite_set_sort_basis(Z3_context c, Z3_sort s) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_get_finite_set_sort_basis(c, s); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         sort* elem_sort = nullptr; | ||||||
|  |         if (!mk_c(c)->fsutil().is_finite_set(to_sort(s), elem_sort)) { | ||||||
|  |             SET_ERROR_CODE(Z3_INVALID_ARG, "expected finite set sort"); | ||||||
|  |             RETURN_Z3(nullptr); | ||||||
|  |         } | ||||||
|  |         RETURN_Z3(of_sort(elem_sort)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_empty(Z3_context c, Z3_sort set_sort) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_empty(c, set_sort); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_empty(to_sort(set_sort)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_singleton(Z3_context c, Z3_ast elem) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_singleton(c, elem); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_singleton(to_expr(elem)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_union(Z3_context c, Z3_ast s1, Z3_ast s2) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_union(c, s1, s2); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_union(to_expr(s1), to_expr(s2)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_intersect(Z3_context c, Z3_ast s1, Z3_ast s2) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_intersect(c, s1, s2); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_intersect(to_expr(s1), to_expr(s2)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_difference(Z3_context c, Z3_ast s1, Z3_ast s2) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_difference(c, s1, s2); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_difference(to_expr(s1), to_expr(s2)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_member(Z3_context c, Z3_ast elem, Z3_ast set) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_member(c, elem, set); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_in(to_expr(elem), to_expr(set)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_size(Z3_context c, Z3_ast set) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_size(c, set); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_size(to_expr(set)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_subset(Z3_context c, Z3_ast s1, Z3_ast s2) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_subset(c, s1, s2); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_subset(to_expr(s1), to_expr(s2)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_map(Z3_context c, Z3_ast f, Z3_ast set) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_map(c, f, set); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_map(to_expr(f), to_expr(set)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_filter(Z3_context c, Z3_ast f, Z3_ast set) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_filter(c, f, set); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_filter(to_expr(f), to_expr(set)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_range(Z3_context c, Z3_ast low, Z3_ast high) { | ||||||
|  |         Z3_TRY; | ||||||
|  |         LOG_Z3_mk_finite_set_range(c, low, high); | ||||||
|  |         RESET_ERROR_CODE(); | ||||||
|  |         app* a = mk_c(c)->fsutil().mk_range(to_expr(low), to_expr(high)); | ||||||
|  |         mk_c(c)->save_ast_trail(a); | ||||||
|  |         RETURN_Z3(of_ast(a)); | ||||||
|  |         Z3_CATCH_RETURN(nullptr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | }; | ||||||
							
								
								
									
										101
									
								
								src/api/z3_api.h
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								src/api/z3_api.h
									
										
									
									
									
								
							|  | @ -3389,6 +3389,107 @@ extern "C" { | ||||||
|     Z3_ast Z3_API Z3_mk_array_ext(Z3_context c, Z3_ast arg1, Z3_ast arg2); |     Z3_ast Z3_API Z3_mk_array_ext(Z3_context c, Z3_ast arg1, Z3_ast arg2); | ||||||
|     /**@}*/ |     /**@}*/ | ||||||
| 
 | 
 | ||||||
|  |     /** @name Finite Sets */ | ||||||
|  |     /**@{*/ | ||||||
|  |     /**
 | ||||||
|  |        \brief Create a finite set sort. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_sort', SORT, (_in(CONTEXT), _in(SORT))) | ||||||
|  |     */ | ||||||
|  |     Z3_sort Z3_API Z3_mk_finite_set_sort(Z3_context c, Z3_sort elem_sort); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Check if a sort is a finite set sort. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_is_finite_set_sort', BOOL, (_in(CONTEXT), _in(SORT))) | ||||||
|  |     */ | ||||||
|  |     bool Z3_API Z3_is_finite_set_sort(Z3_context c, Z3_sort s); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Get the element sort of a finite set sort. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_get_finite_set_sort_basis', SORT, (_in(CONTEXT), _in(SORT))) | ||||||
|  |     */ | ||||||
|  |     Z3_sort Z3_API Z3_get_finite_set_sort_basis(Z3_context c, Z3_sort s); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Create an empty finite set of the given sort. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_empty', AST, (_in(CONTEXT), _in(SORT))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_empty(Z3_context c, Z3_sort set_sort); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Create a singleton finite set. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_singleton', AST, (_in(CONTEXT), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_singleton(Z3_context c, Z3_ast elem); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Create the union of two finite sets. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_union', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_union(Z3_context c, Z3_ast s1, Z3_ast s2); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Create the intersection of two finite sets. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_intersect', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_intersect(Z3_context c, Z3_ast s1, Z3_ast s2); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Create the set difference of two finite sets. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_difference', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_difference(Z3_context c, Z3_ast s1, Z3_ast s2); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Check if an element is a member of a finite set. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_member', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_member(Z3_context c, Z3_ast elem, Z3_ast set); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Get the size (cardinality) of a finite set. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_size', AST, (_in(CONTEXT), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_size(Z3_context c, Z3_ast set); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Check if one finite set is a subset of another. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_subset', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_subset(Z3_context c, Z3_ast s1, Z3_ast s2); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Apply a function to all elements of a finite set. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_map', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_map(Z3_context c, Z3_ast f, Z3_ast set); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Filter a finite set using a predicate. | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_filter', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_filter(Z3_context c, Z3_ast f, Z3_ast set); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |        \brief Create a finite set of integers in the range [low, high). | ||||||
|  | 
 | ||||||
|  |        def_API('Z3_mk_finite_set_range', AST, (_in(CONTEXT), _in(AST), _in(AST))) | ||||||
|  |     */ | ||||||
|  |     Z3_ast Z3_API Z3_mk_finite_set_range(Z3_context c, Z3_ast low, Z3_ast high); | ||||||
|  |     /**@}*/ | ||||||
|  | 
 | ||||||
|     /** @name Numerals */ |     /** @name Numerals */ | ||||||
|     /**@{*/ |     /**@{*/ | ||||||
|     /**
 |     /**
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue