1// Copyright (c) Microsoft Corporation 2025
2// Z3 Go API: Spacer quantifier elimination and model projection functions
13// ASTMap represents a mapping from Z3 ASTs to Z3 ASTs.
19// newASTMap creates a new ASTMap and manages its reference count.
20func newASTMap(ctx *Context, ptr C.Z3_ast_map) *ASTMap {
21 m := &ASTMap{ctx: ctx, ptr: ptr}
22 C.Z3_ast_map_inc_ref(ctx.ptr, ptr)
23 runtime.SetFinalizer(m, func(am *ASTMap) {
24 C.Z3_ast_map_dec_ref(am.ctx.ptr, am.ptr)
29// MkASTMap creates a new empty AST map.
30func (c *Context) MkASTMap() *ASTMap {
31 return newASTMap(c, C.Z3_mk_ast_map(c.ptr))
34// Contains returns true if the map contains the key k.
35func (m *ASTMap) Contains(k *Expr) bool {
36 return bool(C.Z3_ast_map_contains(m.ctx.ptr, m.ptr, k.ptr))
39// Find returns the value associated with key k.
40func (m *ASTMap) Find(k *Expr) *Expr {
41 return newExpr(m.ctx, C.Z3_ast_map_find(m.ctx.ptr, m.ptr, k.ptr))
44// Insert associates key k with value v in the map.
45func (m *ASTMap) Insert(k, v *Expr) {
46 C.Z3_ast_map_insert(m.ctx.ptr, m.ptr, k.ptr, v.ptr)
49// Erase removes the entry with key k from the map.
50func (m *ASTMap) Erase(k *Expr) {
51 C.Z3_ast_map_erase(m.ctx.ptr, m.ptr, k.ptr)
54// Reset removes all entries from the map.
55func (m *ASTMap) Reset() {
56 C.Z3_ast_map_reset(m.ctx.ptr, m.ptr)
59// Size returns the number of entries in the map.
60func (m *ASTMap) Size() uint {
61 return uint(C.Z3_ast_map_size(m.ctx.ptr, m.ptr))
64// Keys returns all keys in the map as an ASTVector.
65func (m *ASTMap) Keys() *ASTVector {
66 return newASTVector(m.ctx, C.Z3_ast_map_keys(m.ctx.ptr, m.ptr))
69// String returns the string representation of the map.
70func (m *ASTMap) String() string {
71 return C.GoString(C.Z3_ast_map_to_string(m.ctx.ptr, m.ptr))
74// ModelExtrapolate extrapolates a model of a formula.
75// Given a model m and formula fml, returns an expression that is implied by fml
76// and is consistent with the model. This is a Spacer-specific function.
77func (c *Context) ModelExtrapolate(m *Model, fml *Expr) *Expr {
78 return newExpr(c, C.Z3_model_extrapolate(c.ptr, m.ptr, fml.ptr))
81// QeLite performs best-effort quantifier elimination.
82// vars is a vector of variables to eliminate, body is the formula.
83func (c *Context) QeLite(vars *ASTVector, body *Expr) *Expr {
84 return newExpr(c, C.Z3_qe_lite(c.ptr, vars.ptr, body.ptr))
87// QeModelProject projects variables given a model.
88// bound is a slice of application expressions representing the variables to project.
89func (c *Context) QeModelProject(m *Model, bound []*Expr, body *Expr) *Expr {
91 cBound := make([]C.Z3_app, n)
92 for i, b := range bound {
93 cBound[i] = C.Z3_to_app(c.ptr, b.ptr)
95 var boundPtr *C.Z3_app
99 return newExpr(c, C.Z3_qe_model_project(c.ptr, m.ptr, C.uint(n), boundPtr, body.ptr))
102// QeModelProjectSkolem projects variables given a model, storing the skolem witnesses in map_.
103// bound is a slice of application expressions representing the variables to project.
104func (c *Context) QeModelProjectSkolem(m *Model, bound []*Expr, body *Expr, map_ *ASTMap) *Expr {
106 cBound := make([]C.Z3_app, n)
107 for i, b := range bound {
108 cBound[i] = C.Z3_to_app(c.ptr, b.ptr)
110 var boundPtr *C.Z3_app
112 boundPtr = &cBound[0]
114 return newExpr(c, C.Z3_qe_model_project_skolem(c.ptr, m.ptr, C.uint(n), boundPtr, body.ptr, map_.ptr))
117// QeModelProjectWithWitness projects variables given a model and extracts witnesses.
118// The map_ is populated with bindings of projected variables to witness terms.
119// bound is a slice of application expressions representing the variables to project.
120func (c *Context) QeModelProjectWithWitness(m *Model, bound []*Expr, body *Expr, map_ *ASTMap) *Expr {
122 cBound := make([]C.Z3_app, n)
123 for i, b := range bound {
124 cBound[i] = C.Z3_to_app(c.ptr, b.ptr)
126 var boundPtr *C.Z3_app
128 boundPtr = &cBound[0]
130 return newExpr(c, C.Z3_qe_model_project_with_witness(c.ptr, m.ptr, C.uint(n), boundPtr, body.ptr, map_.ptr))