13// Status represents the result of a satisfiability check.
17 // Unsatisfiable means the constraints are unsatisfiable.
18 Unsatisfiable Status = -1
19 // Unknown means Z3 could not determine satisfiability.
21 // Satisfiable means the constraints are satisfiable.
22 Satisfiable Status = 1
25// String returns the string representation of the status.
26func (s Status) String() string {
39// Solver represents a Z3 solver.
45// NewSolver creates a new solver for the given context.
46func (c *Context) NewSolver() *Solver {
49 ptr: C.Z3_mk_solver(c.ptr),
51 C.Z3_solver_inc_ref(c.ptr, s.ptr)
52 runtime.SetFinalizer(s, func(solver *Solver) {
53 C.Z3_solver_dec_ref(solver.ctx.ptr, solver.ptr)
58// NewSolverForLogic creates a solver for a specific logic.
59func (c *Context) NewSolverForLogic(logic string) *Solver {
60 sym := c.MkStringSymbol(logic)
63 ptr: C.Z3_mk_solver_for_logic(c.ptr, sym.ptr),
65 C.Z3_solver_inc_ref(c.ptr, s.ptr)
66 runtime.SetFinalizer(s, func(solver *Solver) {
67 C.Z3_solver_dec_ref(solver.ctx.ptr, solver.ptr)
72// String returns the string representation of the solver.
73func (s *Solver) String() string {
74 return C.GoString(C.Z3_solver_to_string(s.ctx.ptr, s.ptr))
77// Assert adds a constraint to the solver.
78func (s *Solver) Assert(constraint *Expr) {
79 C.Z3_solver_assert(s.ctx.ptr, s.ptr, constraint.ptr)
82// AssertAndTrack adds a constraint with a tracking literal.
83func (s *Solver) AssertAndTrack(constraint, track *Expr) {
84 C.Z3_solver_assert_and_track(s.ctx.ptr, s.ptr, constraint.ptr, track.ptr)
87// Check checks the satisfiability of the constraints.
88func (s *Solver) Check() Status {
89 result := C.Z3_solver_check(s.ctx.ptr, s.ptr)
93// CheckAssumptions checks satisfiability under assumptions.
94func (s *Solver) CheckAssumptions(assumptions ...*Expr) Status {
95 if len(assumptions) == 0 {
98 cAssumptions := make([]C.Z3_ast, len(assumptions))
99 for i, a := range assumptions {
100 cAssumptions[i] = a.ptr
102 result := C.Z3_solver_check_assumptions(s.ctx.ptr, s.ptr, C.uint(len(assumptions)), &cAssumptions[0])
103 return Status(result)
106// Model returns the model if the constraints are satisfiable.
107func (s *Solver) Model() *Model {
108 modelPtr := C.Z3_solver_get_model(s.ctx.ptr, s.ptr)
112 return newModel(s.ctx, modelPtr)
115// Push creates a backtracking point.
116func (s *Solver) Push() {
117 C.Z3_solver_push(s.ctx.ptr, s.ptr)
120// Pop removes backtracking points.
121func (s *Solver) Pop(n uint) {
122 C.Z3_solver_pop(s.ctx.ptr, s.ptr, C.uint(n))
125// Reset removes all assertions from the solver.
126func (s *Solver) Reset() {
127 C.Z3_solver_reset(s.ctx.ptr, s.ptr)
130// NumScopes returns the number of backtracking points.
131func (s *Solver) NumScopes() uint {
132 return uint(C.Z3_solver_get_num_scopes(s.ctx.ptr, s.ptr))
135// Assertions returns the assertions in the solver.
136func (s *Solver) Assertions() []*Expr {
137 vec := C.Z3_solver_get_assertions(s.ctx.ptr, s.ptr)
138 return astVectorToExprs(s.ctx, vec)
141// UnsatCore returns the unsat core if the constraints are unsatisfiable.
142func (s *Solver) UnsatCore() []*Expr {
143 vec := C.Z3_solver_get_unsat_core(s.ctx.ptr, s.ptr)
144 return astVectorToExprs(s.ctx, vec)
147// ReasonUnknown returns the reason why the result is unknown.
148func (s *Solver) ReasonUnknown() string {
149 return C.GoString(C.Z3_solver_get_reason_unknown(s.ctx.ptr, s.ptr))
152// GetStatistics returns the statistics for the solver.
153// Statistics include performance metrics, memory usage, and decision statistics.
154func (s *Solver) GetStatistics() *Statistics {
155 ptr := C.Z3_solver_get_statistics(s.ctx.ptr, s.ptr)
156 return newStatistics(s.ctx, ptr)
159// FromFile parses and asserts SMT-LIB2 formulas from a file.
160// The solver will contain the assertions from the file after this call.
161func (s *Solver) FromFile(filename string) {
162 cFilename := C.CString(filename)
163 defer C.free(unsafe.Pointer(cFilename))
164 C.Z3_solver_from_file(s.ctx.ptr, s.ptr, cFilename)
167// FromString parses and asserts SMT-LIB2 formulas from a string.
168// The solver will contain the assertions from the string after this call.
169func (s *Solver) FromString(str string) {
170 cStr := C.CString(str)
171 defer C.free(unsafe.Pointer(cStr))
172 C.Z3_solver_from_string(s.ctx.ptr, s.ptr, cStr)
175// GetHelp returns a string describing all available solver parameters.
176func (s *Solver) GetHelp() string {
177 return C.GoString(C.Z3_solver_get_help(s.ctx.ptr, s.ptr))
180// SetParams sets solver parameters.
181// Parameters control solver behavior such as timeout, proof generation, etc.
182func (s *Solver) SetParams(params *Params) {
183 C.Z3_solver_set_params(s.ctx.ptr, s.ptr, params.ptr)
186// GetParamDescrs returns parameter descriptions for the solver.
187func (s *Solver) GetParamDescrs() *ParamDescrs {
188 ptr := C.Z3_solver_get_param_descrs(s.ctx.ptr, s.ptr)
189 return newParamDescrs(s.ctx, ptr)
192// Interrupt interrupts the solver execution.
193// This is useful for stopping long-running solver operations gracefully.
194func (s *Solver) Interrupt() {
195 C.Z3_solver_interrupt(s.ctx.ptr, s.ptr)
198// Units returns the unit clauses (literals) learned by the solver.
199// Unit clauses are assertions that have been simplified to single literals.
200// This is useful for debugging and understanding solver behavior.
201func (s *Solver) Units() []*Expr {
202 vec := C.Z3_solver_get_units(s.ctx.ptr, s.ptr)
203 return astVectorToExprs(s.ctx, vec)
206// NonUnits returns the non-unit clauses in the solver's current state.
207// These are clauses that have not been reduced to unit clauses.
208// This is useful for debugging and understanding solver behavior.
209func (s *Solver) NonUnits() []*Expr {
210 vec := C.Z3_solver_get_non_units(s.ctx.ptr, s.ptr)
211 return astVectorToExprs(s.ctx, vec)
214// Trail returns the decision trail of the solver.
215// The trail contains the sequence of literals assigned during search.
216// This is useful for understanding the solver's decision history.
217// Note: This function works primarily with SimpleSolver. For solvers created
218// using tactics (e.g., NewSolver()), it may return an error.
219func (s *Solver) Trail() []*Expr {
220 vec := C.Z3_solver_get_trail(s.ctx.ptr, s.ptr)
221 return astVectorToExprs(s.ctx, vec)
224// TrailLevels returns the decision levels for each literal in the trail.
225// The returned slice has the same length as the trail, where each element
226// indicates the decision level at which the corresponding trail literal was assigned.
227// This is useful for understanding the structure of the search tree.
228// Note: This function works primarily with SimpleSolver. For solvers created
229// using tactics (e.g., NewSolver()), it may return an error.
230func (s *Solver) TrailLevels() []uint {
231 // Get the trail vector directly from the C API
232 trailVec := C.Z3_solver_get_trail(s.ctx.ptr, s.ptr)
233 C.Z3_ast_vector_inc_ref(s.ctx.ptr, trailVec)
234 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, trailVec)
236 n := uint(C.Z3_ast_vector_size(s.ctx.ptr, trailVec))
241 // Allocate the levels array
242 levels := make([]C.uint, n)
244 // Get the levels using the trail vector directly
245 // Safe to pass &levels[0] because we checked n > 0 above
246 C.Z3_solver_get_levels(s.ctx.ptr, s.ptr, trailVec, C.uint(n), &levels[0])
248 // Convert to Go slice
249 result := make([]uint, n)
250 for i := uint(0); i < n; i++ {
251 result[i] = uint(levels[i])
256// CongruenceRoot returns the congruence class representative of the given expression.
257// This returns the root element in the congruence closure for the term.
258// Note: This function works primarily with SimpleSolver. Terms and variables that
259// are eliminated during pre-processing are not visible to the congruence closure.
260func (s *Solver) CongruenceRoot(expr *Expr) *Expr {
261 ast := C.Z3_solver_congruence_root(s.ctx.ptr, s.ptr, expr.ptr)
262 return newExpr(s.ctx, ast)
265// CongruenceNext returns the next element in the congruence class of the given expression.
266// This allows iteration through all elements in a congruence class.
267// Note: This function works primarily with SimpleSolver. Terms and variables that
268// are eliminated during pre-processing are not visible to the congruence closure.
269func (s *Solver) CongruenceNext(expr *Expr) *Expr {
270 ast := C.Z3_solver_congruence_next(s.ctx.ptr, s.ptr, expr.ptr)
271 return newExpr(s.ctx, ast)
274// CongruenceExplain returns an explanation for why two expressions are congruent.
275// The result is an expression that justifies the congruence between a and b.
276// Note: This function works primarily with SimpleSolver. Terms and variables that
277// are eliminated during pre-processing are not visible to the congruence closure.
278func (s *Solver) CongruenceExplain(a, b *Expr) *Expr {
279 ast := C.Z3_solver_congruence_explain(s.ctx.ptr, s.ptr, a.ptr, b.ptr)
280 return newExpr(s.ctx, ast)
283// SetInitialValue provides an initial value hint for a variable to the solver.
284// This can help guide the solver to find solutions more efficiently.
285// The variable must be a constant or function application, and the value must be
286// compatible with the variable's sort.
287func (s *Solver) SetInitialValue(variable, value *Expr) {
288 C.Z3_solver_set_initial_value(s.ctx.ptr, s.ptr, variable.ptr, value.ptr)
291// Cube extracts a cube (conjunction of literals) from the solver state.
292// vars is an optional list of variables to use as cube variables; if nil, the solver decides.
293// cutoff specifies the backtrack level cutoff for cube generation.
294// Returns a slice of expressions representing the cube, or nil when the search space is exhausted.
295func (s *Solver) Cube(vars []*Expr, cutoff uint) []*Expr {
296 varVec := C.Z3_mk_ast_vector(s.ctx.ptr)
297 C.Z3_ast_vector_inc_ref(s.ctx.ptr, varVec)
298 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, varVec)
299 for _, v := range vars {
300 C.Z3_ast_vector_push(s.ctx.ptr, varVec, v.ptr)
302 result := C.Z3_solver_cube(s.ctx.ptr, s.ptr, varVec, C.uint(cutoff))
303 return astVectorToExprs(s.ctx, result)
306// GetConsequences retrieves fixed assignments for variables given assumptions.
307// Returns the status and the set of consequences as implications.
308func (s *Solver) GetConsequences(assumptions []*Expr, variables []*Expr) (Status, []*Expr) {
309 asmVec := C.Z3_mk_ast_vector(s.ctx.ptr)
310 C.Z3_ast_vector_inc_ref(s.ctx.ptr, asmVec)
311 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, asmVec)
312 varVec := C.Z3_mk_ast_vector(s.ctx.ptr)
313 C.Z3_ast_vector_inc_ref(s.ctx.ptr, varVec)
314 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, varVec)
315 consVec := C.Z3_mk_ast_vector(s.ctx.ptr)
316 C.Z3_ast_vector_inc_ref(s.ctx.ptr, consVec)
317 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, consVec)
318 for _, a := range assumptions {
319 C.Z3_ast_vector_push(s.ctx.ptr, asmVec, a.ptr)
321 for _, v := range variables {
322 C.Z3_ast_vector_push(s.ctx.ptr, varVec, v.ptr)
324 r := Status(C.Z3_solver_get_consequences(s.ctx.ptr, s.ptr, asmVec, varVec, consVec))
325 return r, astVectorToExprs(s.ctx, consVec)
328// SolveFor solves constraints treating given variables symbolically.
329// variables are the variables to solve for, terms are the substitution terms,
330// and guards are the Boolean guards for the substitutions.
331func (s *Solver) SolveFor(variables []*Expr, terms []*Expr, guards []*Expr) {
332 varVec := C.Z3_mk_ast_vector(s.ctx.ptr)
333 C.Z3_ast_vector_inc_ref(s.ctx.ptr, varVec)
334 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, varVec)
335 termVec := C.Z3_mk_ast_vector(s.ctx.ptr)
336 C.Z3_ast_vector_inc_ref(s.ctx.ptr, termVec)
337 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, termVec)
338 guardVec := C.Z3_mk_ast_vector(s.ctx.ptr)
339 C.Z3_ast_vector_inc_ref(s.ctx.ptr, guardVec)
340 defer C.Z3_ast_vector_dec_ref(s.ctx.ptr, guardVec)
341 for _, v := range variables {
342 C.Z3_ast_vector_push(s.ctx.ptr, varVec, v.ptr)
344 for _, t := range terms {
345 C.Z3_ast_vector_push(s.ctx.ptr, termVec, t.ptr)
347 for _, g := range guards {
348 C.Z3_ast_vector_push(s.ctx.ptr, guardVec, g.ptr)
350 C.Z3_solver_solve_for(s.ctx.ptr, s.ptr, varVec, termVec, guardVec)
353// ImportModelConverter imports the model converter from src into this solver.
354// This transfers model simplifications from one solver instance to another,
355// useful when combining results from multiple solver instances.
356func (dst *Solver) ImportModelConverter(src *Solver) {
357 C.Z3_solver_import_model_converter(dst.ctx.ptr, src.ptr, dst.ptr)
360// Translate creates a copy of the solver in the target context.
361// This is useful when working with multiple Z3 contexts.
362func (s *Solver) Translate(target *Context) *Solver {
363 ptr := C.Z3_solver_translate(s.ctx.ptr, s.ptr, target.ptr)
364 newSolver := &Solver{ctx: target, ptr: ptr}
365 C.Z3_solver_inc_ref(target.ptr, ptr)
366 runtime.SetFinalizer(newSolver, func(solver *Solver) {
367 C.Z3_solver_dec_ref(solver.ctx.ptr, solver.ptr)
372// GetProof returns the proof of unsatisfiability from the last check.
373// Returns nil if no proof is available (e.g. the result was not UNSAT,
374// or proof production is disabled).
375func (s *Solver) GetProof() *Expr {
376 result := C.Z3_solver_get_proof(s.ctx.ptr, s.ptr)
380 return newExpr(s.ctx, result)
383// AddSimplifier creates a new solver with the given simplifier attached for
384// pre-processing assertions before solving.
385func (s *Solver) AddSimplifier(simplifier *Simplifier) *Solver {
386 ptr := C.Z3_solver_add_simplifier(s.ctx.ptr, s.ptr, simplifier.ptr)
387 newSolver := &Solver{ctx: s.ctx, ptr: ptr}
388 C.Z3_solver_inc_ref(s.ctx.ptr, ptr)
389 runtime.SetFinalizer(newSolver, func(solver *Solver) {
390 C.Z3_solver_dec_ref(solver.ctx.ptr, solver.ptr)
395// Dimacs converts the solver's Boolean formula to DIMACS CNF format.
396// If includeNames is true, variable names are included in the output.
397func (s *Solver) Dimacs(includeNames bool) string {
398 return C.GoString(C.Z3_solver_to_dimacs_string(s.ctx.ptr, s.ptr, C.bool(includeNames)))
401// Model represents a Z3 model (satisfying assignment).
407// newModel creates a new Model and manages its reference count.
408func newModel(ctx *Context, ptr C.Z3_model) *Model {
409 m := &Model{ctx: ctx, ptr: ptr}
410 C.Z3_model_inc_ref(ctx.ptr, ptr)
411 runtime.SetFinalizer(m, func(model *Model) {
412 C.Z3_model_dec_ref(model.ctx.ptr, model.ptr)
417// String returns the string representation of the model.
418func (m *Model) String() string {
419 return C.GoString(C.Z3_model_to_string(m.ctx.ptr, m.ptr))
422// NumConsts returns the number of constants in the model.
423func (m *Model) NumConsts() uint {
424 return uint(C.Z3_model_get_num_consts(m.ctx.ptr, m.ptr))
427// NumFuncs returns the number of function interpretations in the model.
428func (m *Model) NumFuncs() uint {
429 return uint(C.Z3_model_get_num_funcs(m.ctx.ptr, m.ptr))
432// GetConstDecl returns the i-th constant declaration in the model.
433func (m *Model) GetConstDecl(i uint) *FuncDecl {
434 return newFuncDecl(m.ctx, C.Z3_model_get_const_decl(m.ctx.ptr, m.ptr, C.uint(i)))
437// GetFuncDecl returns the i-th function declaration in the model.
438func (m *Model) GetFuncDecl(i uint) *FuncDecl {
439 return newFuncDecl(m.ctx, C.Z3_model_get_func_decl(m.ctx.ptr, m.ptr, C.uint(i)))
442// Eval evaluates an expression in the model.
443// If modelCompletion is true, Z3 will assign an interpretation for uninterpreted constants.
444func (m *Model) Eval(expr *Expr, modelCompletion bool) (*Expr, bool) {
446 var completion C.bool
448 completion = C.bool(true)
450 completion = C.bool(false)
452 success := C.Z3_model_eval(m.ctx.ptr, m.ptr, expr.ptr, completion, &result)
453 if success == C.bool(false) {
456 return newExpr(m.ctx, result), true
459// GetConstInterp returns the interpretation of a constant.
460func (m *Model) GetConstInterp(decl *FuncDecl) *Expr {
461 result := C.Z3_model_get_const_interp(m.ctx.ptr, m.ptr, decl.ptr)
465 return newExpr(m.ctx, result)
468// FuncInterp represents a function interpretation in a model.
469type FuncInterp struct {
474// GetFuncInterp returns the interpretation of a function.
475func (m *Model) GetFuncInterp(decl *FuncDecl) *FuncInterp {
476 result := C.Z3_model_get_func_interp(m.ctx.ptr, m.ptr, decl.ptr)
480 fi := &FuncInterp{ctx: m.ctx, ptr: result}
481 C.Z3_func_interp_inc_ref(m.ctx.ptr, result)
482 runtime.SetFinalizer(fi, func(f *FuncInterp) {
483 C.Z3_func_interp_dec_ref(f.ctx.ptr, f.ptr)
488// NumEntries returns the number of entries in the function interpretation.
489func (fi *FuncInterp) NumEntries() uint {
490 return uint(C.Z3_func_interp_get_num_entries(fi.ctx.ptr, fi.ptr))
493// GetElse returns the else value of the function interpretation.
494func (fi *FuncInterp) GetElse() *Expr {
495 result := C.Z3_func_interp_get_else(fi.ctx.ptr, fi.ptr)
496 return newExpr(fi.ctx, result)
499// GetArity returns the arity of the function interpretation.
500func (fi *FuncInterp) GetArity() uint {
501 return uint(C.Z3_func_interp_get_arity(fi.ctx.ptr, fi.ptr))
504// FuncEntry represents a single entry in a FuncInterp finite map.
505type FuncEntry struct {
510// newFuncEntry creates a new FuncEntry and manages its reference count.
511func newFuncEntry(ctx *Context, ptr C.Z3_func_entry) *FuncEntry {
512 e := &FuncEntry{ctx: ctx, ptr: ptr}
513 C.Z3_func_entry_inc_ref(ctx.ptr, ptr)
514 runtime.SetFinalizer(e, func(entry *FuncEntry) {
515 C.Z3_func_entry_dec_ref(entry.ctx.ptr, entry.ptr)
520// GetEntry returns the i-th entry in the function interpretation.
521func (fi *FuncInterp) GetEntry(i uint) *FuncEntry {
522 return newFuncEntry(fi.ctx, C.Z3_func_interp_get_entry(fi.ctx.ptr, fi.ptr, C.uint(i)))
525// SetElse sets the else value of the function interpretation.
526func (fi *FuncInterp) SetElse(val *Expr) {
527 C.Z3_func_interp_set_else(fi.ctx.ptr, fi.ptr, val.ptr)
530// AddEntry adds a new entry to the function interpretation.
531// The args slice provides the argument values and val is the return value.
532func (fi *FuncInterp) AddEntry(args []*Expr, val *Expr) {
533 vec := C.Z3_mk_ast_vector(fi.ctx.ptr)
534 C.Z3_ast_vector_inc_ref(fi.ctx.ptr, vec)
535 defer C.Z3_ast_vector_dec_ref(fi.ctx.ptr, vec)
536 for _, a := range args {
537 C.Z3_ast_vector_push(fi.ctx.ptr, vec, a.ptr)
539 C.Z3_func_interp_add_entry(fi.ctx.ptr, fi.ptr, vec, val.ptr)
542// GetValue returns the return value of the function entry.
543func (e *FuncEntry) GetValue() *Expr {
544 return newExpr(e.ctx, C.Z3_func_entry_get_value(e.ctx.ptr, e.ptr))
547// GetNumArgs returns the number of arguments in the function entry.
548func (e *FuncEntry) GetNumArgs() uint {
549 return uint(C.Z3_func_entry_get_num_args(e.ctx.ptr, e.ptr))
552// GetArg returns the i-th argument of the function entry.
553func (e *FuncEntry) GetArg(i uint) *Expr {
554 return newExpr(e.ctx, C.Z3_func_entry_get_arg(e.ctx.ptr, e.ptr, C.uint(i)))
557// HasInterp reports whether the model contains an interpretation for the given declaration.
558func (m *Model) HasInterp(decl *FuncDecl) bool {
559 return bool(C.Z3_model_has_interp(m.ctx.ptr, m.ptr, decl.ptr))
562// SortUniverse returns the universe of values for an uninterpreted sort in the model.
563// The universe is represented as a list of distinct expressions.
564// Returns nil if the sort is not an uninterpreted sort in this model.
565func (m *Model) SortUniverse(sort *Sort) []*Expr {
566 vec := C.Z3_model_get_sort_universe(m.ctx.ptr, m.ptr, sort.ptr)
570 return astVectorToExprs(m.ctx, vec)
573// Translate creates a copy of the model in the target context.
574func (m *Model) Translate(target *Context) *Model {
575 ptr := C.Z3_model_translate(m.ctx.ptr, m.ptr, target.ptr)
576 return newModel(target, ptr)