13// Tactic represents a Z3 tactic for transforming goals.
19// newTactic creates a new Tactic and manages its reference count.
20func newTactic(ctx *Context, ptr C.Z3_tactic) *Tactic {
21 t := &Tactic{ctx: ctx, ptr: ptr}
22 C.Z3_tactic_inc_ref(ctx.ptr, ptr)
23 runtime.SetFinalizer(t, func(tactic *Tactic) {
24 C.Z3_tactic_dec_ref(tactic.ctx.ptr, tactic.ptr)
29// MkTactic creates a tactic with the given name.
30func (c *Context) MkTactic(name string) *Tactic {
31 cName := C.CString(name)
32 defer C.free(unsafe.Pointer(cName))
33 return newTactic(c, C.Z3_mk_tactic(c.ptr, cName))
36// Apply applies the tactic to a goal.
37func (t *Tactic) Apply(g *Goal) *ApplyResult {
38 return newApplyResult(t.ctx, C.Z3_tactic_apply(t.ctx.ptr, t.ptr, g.ptr))
41// GetHelp returns help information for the tactic.
42func (t *Tactic) GetHelp() string {
43 return C.GoString(C.Z3_tactic_get_help(t.ctx.ptr, t.ptr))
46// AndThen creates a tactic that applies t1 and then t2.
47func (t *Tactic) AndThen(t2 *Tactic) *Tactic {
48 return newTactic(t.ctx, C.Z3_tactic_and_then(t.ctx.ptr, t.ptr, t2.ptr))
51// OrElse creates a tactic that applies t1, and if it fails, applies t2.
52func (t *Tactic) OrElse(t2 *Tactic) *Tactic {
53 return newTactic(t.ctx, C.Z3_tactic_or_else(t.ctx.ptr, t.ptr, t2.ptr))
56// Repeat creates a tactic that applies t repeatedly (at most max times).
57func (t *Tactic) Repeat(max uint) *Tactic {
58 return newTactic(t.ctx, C.Z3_tactic_repeat(t.ctx.ptr, t.ptr, C.uint(max)))
61// When creates a conditional tactic that applies t only if probe p evaluates to true.
62func (c *Context) TacticWhen(p *Probe, t *Tactic) *Tactic {
63 return newTactic(c, C.Z3_tactic_when(c.ptr, p.ptr, t.ptr))
66// TacticCond creates a conditional tactic: if p then t1 else t2.
67func (c *Context) TacticCond(p *Probe, t1, t2 *Tactic) *Tactic {
68 return newTactic(c, C.Z3_tactic_cond(c.ptr, p.ptr, t1.ptr, t2.ptr))
71// TacticFail creates a tactic that always fails.
72func (c *Context) TacticFail() *Tactic {
73 return newTactic(c, C.Z3_tactic_fail(c.ptr))
76// TacticSkip creates a tactic that always succeeds.
77func (c *Context) TacticSkip() *Tactic {
78 return newTactic(c, C.Z3_tactic_skip(c.ptr))
81// Goal represents a set of formulas that can be solved or transformed.
87// newGoal creates a new Goal and manages its reference count.
88func newGoal(ctx *Context, ptr C.Z3_goal) *Goal {
89 g := &Goal{ctx: ctx, ptr: ptr}
90 C.Z3_goal_inc_ref(ctx.ptr, ptr)
91 runtime.SetFinalizer(g, func(goal *Goal) {
92 C.Z3_goal_dec_ref(goal.ctx.ptr, goal.ptr)
97// MkGoal creates a new goal.
98func (c *Context) MkGoal(models, unsatCores, proofs bool) *Goal {
99 return newGoal(c, C.Z3_mk_goal(c.ptr, C.bool(models), C.bool(unsatCores), C.bool(proofs)))
102// Assert adds a constraint to the goal.
103func (g *Goal) Assert(constraint *Expr) {
104 C.Z3_goal_assert(g.ctx.ptr, g.ptr, constraint.ptr)
107// Size returns the number of formulas in the goal.
108func (g *Goal) Size() uint {
109 return uint(C.Z3_goal_size(g.ctx.ptr, g.ptr))
112// Formula returns the i-th formula in the goal.
113func (g *Goal) Formula(i uint) *Expr {
114 return newExpr(g.ctx, C.Z3_goal_formula(g.ctx.ptr, g.ptr, C.uint(i)))
117// NumExprs returns the number of expressions in the goal.
118func (g *Goal) NumExprs() uint {
119 return uint(C.Z3_goal_num_exprs(g.ctx.ptr, g.ptr))
122// IsDecidedSat returns true if the goal is decided to be satisfiable.
123func (g *Goal) IsDecidedSat() bool {
124 return bool(C.Z3_goal_is_decided_sat(g.ctx.ptr, g.ptr))
127// IsDecidedUnsat returns true if the goal is decided to be unsatisfiable.
128func (g *Goal) IsDecidedUnsat() bool {
129 return bool(C.Z3_goal_is_decided_unsat(g.ctx.ptr, g.ptr))
132// Reset removes all formulas from the goal.
133func (g *Goal) Reset() {
134 C.Z3_goal_reset(g.ctx.ptr, g.ptr)
137// String returns the string representation of the goal.
138func (g *Goal) String() string {
139 return C.GoString(C.Z3_goal_to_string(g.ctx.ptr, g.ptr))
142// ApplyResult represents the result of applying a tactic to a goal.
143type ApplyResult struct {
145 ptr C.Z3_apply_result
148// newApplyResult creates a new ApplyResult and manages its reference count.
149func newApplyResult(ctx *Context, ptr C.Z3_apply_result) *ApplyResult {
150 ar := &ApplyResult{ctx: ctx, ptr: ptr}
151 C.Z3_apply_result_inc_ref(ctx.ptr, ptr)
152 runtime.SetFinalizer(ar, func(result *ApplyResult) {
153 C.Z3_apply_result_dec_ref(result.ctx.ptr, result.ptr)
158// NumSubgoals returns the number of subgoals in the result.
159func (ar *ApplyResult) NumSubgoals() uint {
160 return uint(C.Z3_apply_result_get_num_subgoals(ar.ctx.ptr, ar.ptr))
163// Subgoal returns the i-th subgoal.
164func (ar *ApplyResult) Subgoal(i uint) *Goal {
165 return newGoal(ar.ctx, C.Z3_apply_result_get_subgoal(ar.ctx.ptr, ar.ptr, C.uint(i)))
168// String returns the string representation of the apply result.
169func (ar *ApplyResult) String() string {
170 return C.GoString(C.Z3_apply_result_to_string(ar.ctx.ptr, ar.ptr))
173// Probe represents a probe for checking properties of goals.
179// newProbe creates a new Probe and manages its reference count.
180func newProbe(ctx *Context, ptr C.Z3_probe) *Probe {
181 p := &Probe{ctx: ctx, ptr: ptr}
182 C.Z3_probe_inc_ref(ctx.ptr, ptr)
183 runtime.SetFinalizer(p, func(probe *Probe) {
184 C.Z3_probe_dec_ref(probe.ctx.ptr, probe.ptr)
189// MkProbe creates a probe with the given name.
190func (c *Context) MkProbe(name string) *Probe {
191 cName := C.CString(name)
192 defer C.free(unsafe.Pointer(cName))
193 return newProbe(c, C.Z3_mk_probe(c.ptr, cName))
196// Apply evaluates the probe on a goal.
197func (p *Probe) Apply(g *Goal) float64 {
198 return float64(C.Z3_probe_apply(p.ctx.ptr, p.ptr, g.ptr))
201// ProbeConst creates a probe that always evaluates to the given value.
202func (c *Context) ProbeConst(val float64) *Probe {
203 return newProbe(c, C.Z3_probe_const(c.ptr, C.double(val)))
206// ProbeLt creates a probe that evaluates to true if p1 < p2.
207func (p *Probe) Lt(p2 *Probe) *Probe {
208 return newProbe(p.ctx, C.Z3_probe_lt(p.ctx.ptr, p.ptr, p2.ptr))
211// ProbeGt creates a probe that evaluates to true if p1 > p2.
212func (p *Probe) Gt(p2 *Probe) *Probe {
213 return newProbe(p.ctx, C.Z3_probe_gt(p.ctx.ptr, p.ptr, p2.ptr))
216// ProbeLe creates a probe that evaluates to true if p1 <= p2.
217func (p *Probe) Le(p2 *Probe) *Probe {
218 return newProbe(p.ctx, C.Z3_probe_le(p.ctx.ptr, p.ptr, p2.ptr))
221// ProbeGe creates a probe that evaluates to true if p1 >= p2.
222func (p *Probe) Ge(p2 *Probe) *Probe {
223 return newProbe(p.ctx, C.Z3_probe_ge(p.ctx.ptr, p.ptr, p2.ptr))
226// ProbeEq creates a probe that evaluates to true if p1 == p2.
227func (p *Probe) Eq(p2 *Probe) *Probe {
228 return newProbe(p.ctx, C.Z3_probe_eq(p.ctx.ptr, p.ptr, p2.ptr))
231// ProbeAnd creates a probe that is the conjunction of p1 and p2.
232func (p *Probe) And(p2 *Probe) *Probe {
233 return newProbe(p.ctx, C.Z3_probe_and(p.ctx.ptr, p.ptr, p2.ptr))
236// ProbeOr creates a probe that is the disjunction of p1 and p2.
237func (p *Probe) Or(p2 *Probe) *Probe {
238 return newProbe(p.ctx, C.Z3_probe_or(p.ctx.ptr, p.ptr, p2.ptr))
241// ProbeNot creates a probe that is the negation of p.
242func (p *Probe) Not() *Probe {
243 return newProbe(p.ctx, C.Z3_probe_not(p.ctx.ptr, p.ptr))
246// Params represents a parameter set.
252// newParams creates a new Params and manages its reference count.
253func newParams(ctx *Context, ptr C.Z3_params) *Params {
254 params := &Params{ctx: ctx, ptr: ptr}
255 C.Z3_params_inc_ref(ctx.ptr, ptr)
256 runtime.SetFinalizer(params, func(p *Params) {
257 C.Z3_params_dec_ref(p.ctx.ptr, p.ptr)
262// MkParams creates a new parameter set.
263func (c *Context) MkParams() *Params {
264 return newParams(c, C.Z3_mk_params(c.ptr))
267// SetBool sets a Boolean parameter.
268func (p *Params) SetBool(key string, value bool) {
269 sym := p.ctx.MkStringSymbol(key)
270 C.Z3_params_set_bool(p.ctx.ptr, p.ptr, sym.ptr, C.bool(value))
273// SetUint sets an unsigned integer parameter.
274func (p *Params) SetUint(key string, value uint) {
275 sym := p.ctx.MkStringSymbol(key)
276 C.Z3_params_set_uint(p.ctx.ptr, p.ptr, sym.ptr, C.uint(value))
279// SetDouble sets a double parameter.
280func (p *Params) SetDouble(key string, value float64) {
281 sym := p.ctx.MkStringSymbol(key)
282 C.Z3_params_set_double(p.ctx.ptr, p.ptr, sym.ptr, C.double(value))
285// SetSymbol sets a symbol parameter.
286func (p *Params) SetSymbol(key string, value *Symbol) {
287 sym := p.ctx.MkStringSymbol(key)
288 C.Z3_params_set_symbol(p.ctx.ptr, p.ptr, sym.ptr, value.ptr)
291// String returns the string representation of the parameters.
292func (p *Params) String() string {
293 return C.GoString(C.Z3_params_to_string(p.ctx.ptr, p.ptr))