13// Optimize represents a Z3 optimization context for solving optimization problems.
14// Unlike Solver which only checks satisfiability, Optimize can find optimal solutions
15// with respect to objective functions.
21// NewOptimize creates a new optimization context.
22func (c *Context) NewOptimize() *Optimize {
25 ptr: C.Z3_mk_optimize(c.ptr),
27 C.Z3_optimize_inc_ref(c.ptr, opt.ptr)
28 runtime.SetFinalizer(opt, func(o *Optimize) {
29 C.Z3_optimize_dec_ref(o.ctx.ptr, o.ptr)
34// String returns the string representation of the optimize context.
35func (o *Optimize) String() string {
36 return C.GoString(C.Z3_optimize_to_string(o.ctx.ptr, o.ptr))
39// Assert adds a constraint to the optimizer.
40func (o *Optimize) Assert(constraint *Expr) {
41 C.Z3_optimize_assert(o.ctx.ptr, o.ptr, constraint.ptr)
44// AssertAndTrack adds a constraint with a tracking literal for unsat core extraction.
45func (o *Optimize) AssertAndTrack(constraint, track *Expr) {
46 C.Z3_optimize_assert_and_track(o.ctx.ptr, o.ptr, constraint.ptr, track.ptr)
49// AssertSoft adds a soft constraint with a weight.
50// Soft constraints are used for MaxSMT problems.
51// Returns a handle to the objective.
52func (o *Optimize) AssertSoft(constraint *Expr, weight string, group string) uint {
53 cWeight := C.CString(weight)
54 cGroup := C.CString(group)
55 defer C.free(unsafe.Pointer(cWeight))
56 defer C.free(unsafe.Pointer(cGroup))
58 sym := o.ctx.MkStringSymbol(group)
59 return uint(C.Z3_optimize_assert_soft(o.ctx.ptr, o.ptr, constraint.ptr, cWeight, sym.ptr))
62// Maximize adds a maximization objective.
63// Returns a handle to the objective that can be used to retrieve bounds.
64func (o *Optimize) Maximize(expr *Expr) uint {
65 return uint(C.Z3_optimize_maximize(o.ctx.ptr, o.ptr, expr.ptr))
68// Minimize adds a minimization objective.
69// Returns a handle to the objective that can be used to retrieve bounds.
70func (o *Optimize) Minimize(expr *Expr) uint {
71 return uint(C.Z3_optimize_minimize(o.ctx.ptr, o.ptr, expr.ptr))
74// Check checks the satisfiability of the constraints and optimizes objectives.
75func (o *Optimize) Check(assumptions ...*Expr) Status {
77 if len(assumptions) == 0 {
78 result = C.Z3_optimize_check(o.ctx.ptr, o.ptr, 0, nil)
80 cAssumptions := make([]C.Z3_ast, len(assumptions))
81 for i, a := range assumptions {
82 cAssumptions[i] = a.ptr
84 result = C.Z3_optimize_check(o.ctx.ptr, o.ptr, C.uint(len(assumptions)), &cAssumptions[0])
89// Model returns the model if the constraints are satisfiable.
90func (o *Optimize) Model() *Model {
91 modelPtr := C.Z3_optimize_get_model(o.ctx.ptr, o.ptr)
95 return newModel(o.ctx, modelPtr)
98// Push creates a backtracking point.
99func (o *Optimize) Push() {
100 C.Z3_optimize_push(o.ctx.ptr, o.ptr)
103// Pop removes a backtracking point.
104func (o *Optimize) Pop() {
105 C.Z3_optimize_pop(o.ctx.ptr, o.ptr)
108// GetLower retrieves a lower bound for the objective at the given index.
109func (o *Optimize) GetLower(index uint) *Expr {
110 result := C.Z3_optimize_get_lower(o.ctx.ptr, o.ptr, C.uint(index))
114 return newExpr(o.ctx, result)
117// GetUpper retrieves an upper bound for the objective at the given index.
118func (o *Optimize) GetUpper(index uint) *Expr {
119 result := C.Z3_optimize_get_upper(o.ctx.ptr, o.ptr, C.uint(index))
123 return newExpr(o.ctx, result)
126// GetLowerAsVector retrieves a lower bound as a vector (inf, value, eps).
127// The objective value is unbounded if inf is non-zero,
128// otherwise it's represented as value + eps * EPSILON.
129func (o *Optimize) GetLowerAsVector(index uint) []*Expr {
130 vec := C.Z3_optimize_get_lower_as_vector(o.ctx.ptr, o.ptr, C.uint(index))
131 result := astVectorToExprs(o.ctx, vec)
132 if len(result) != 3 {
138// GetUpperAsVector retrieves an upper bound as a vector (inf, value, eps).
139// The objective value is unbounded if inf is non-zero,
140// otherwise it's represented as value + eps * EPSILON.
141func (o *Optimize) GetUpperAsVector(index uint) []*Expr {
142 vec := C.Z3_optimize_get_upper_as_vector(o.ctx.ptr, o.ptr, C.uint(index))
143 result := astVectorToExprs(o.ctx, vec)
144 if len(result) != 3 {
150// ReasonUnknown returns the reason why the result is unknown.
151func (o *Optimize) ReasonUnknown() string {
152 return C.GoString(C.Z3_optimize_get_reason_unknown(o.ctx.ptr, o.ptr))
155// GetHelp returns help information for the optimizer.
156func (o *Optimize) GetHelp() string {
157 return C.GoString(C.Z3_optimize_get_help(o.ctx.ptr, o.ptr))
160// SetParams sets parameters for the optimizer.
161func (o *Optimize) SetParams(params *Params) {
162 C.Z3_optimize_set_params(o.ctx.ptr, o.ptr, params.ptr)
165// Assertions returns the assertions in the optimizer.
166func (o *Optimize) Assertions() []*Expr {
167 vec := C.Z3_optimize_get_assertions(o.ctx.ptr, o.ptr)
168 return astVectorToExprs(o.ctx, vec)
171// Objectives returns the objectives in the optimizer.
172func (o *Optimize) Objectives() []*Expr {
173 vec := C.Z3_optimize_get_objectives(o.ctx.ptr, o.ptr)
174 return astVectorToExprs(o.ctx, vec)
177// UnsatCore returns the unsat core if the constraints are unsatisfiable.
178func (o *Optimize) UnsatCore() []*Expr {
179 vec := C.Z3_optimize_get_unsat_core(o.ctx.ptr, o.ptr)
180 return astVectorToExprs(o.ctx, vec)
183// FromFile parses an SMT-LIB2 file with optimization objectives and constraints.
184func (o *Optimize) FromFile(filename string) {
185 cFilename := C.CString(filename)
186 defer C.free(unsafe.Pointer(cFilename))
187 C.Z3_optimize_from_file(o.ctx.ptr, o.ptr, cFilename)
190// FromString parses an SMT-LIB2 string with optimization objectives and constraints.
191func (o *Optimize) FromString(s string) {
193 defer C.free(unsafe.Pointer(cStr))
194 C.Z3_optimize_from_string(o.ctx.ptr, o.ptr, cStr)