z3 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/z3/ast.rb ADDED
@@ -0,0 +1,302 @@
1
+ class Z3::Ast
2
+ attr_reader :_ast
3
+ # Do not use .new directly
4
+ def initialize(_ast)
5
+ @_ast = _ast
6
+ end
7
+
8
+ def sort
9
+ Z3::Sort.new(Z3::LowLevel.get_sort(self))
10
+ end
11
+
12
+ def to_s
13
+ Z3::LowLevel.ast_to_string(self)
14
+ end
15
+
16
+ def inspect
17
+ "Z3::Ast<#{to_s} :: #{sort.to_s}>"
18
+ end
19
+
20
+ def ~
21
+ raise Z3::Exception, "Can only be used on booleans" unless bool?
22
+ Z3::Ast.not(self)
23
+ end
24
+
25
+ def int?
26
+ sort == Z3::Sort.int
27
+ end
28
+
29
+ def bool?
30
+ sort == Z3::Sort.bool
31
+ end
32
+
33
+ def real?
34
+ sort == Z3::Sort.real
35
+ end
36
+
37
+ private def binary_arithmetic_operator(op, b)
38
+ b = Z3::Ast.from_const(b, sort) unless b.is_a?(Z3::Ast)
39
+ raise Z3::Exception, "Can't be used on booleans" if bool? or b.bool?
40
+ if sort == b.sort
41
+ a = self
42
+ else
43
+ a, b = Z3::Ast.coerce_to_same_sort(self, b)
44
+ end
45
+ Z3::Ast.send(op, a, b)
46
+ end
47
+
48
+ private def binary_int_operator(op, b)
49
+ b = Z3::Ast.from_const(b, sort) unless b.is_a?(Z3::Ast)
50
+ raise Z3::Exception, "Can only be used on integers" unless int? and b.int?
51
+ Z3::Ast.send(op, a, b)
52
+ end
53
+
54
+ def |(b)
55
+ b = Z3::Ast.from_const(b, sort) unless b.is_a?(Z3::Ast)
56
+ raise Z3::Exception, "Can only be used on booleans" unless bool? and b.bool?
57
+ Z3::Ast.or(self, b)
58
+ end
59
+
60
+ def &(b)
61
+ b = Z3::Ast.from_const(b, sort) unless b.is_a?(Z3::Ast)
62
+ raise Z3::Exception, "Can only be used on booleans" unless bool? and b.bool?
63
+ Z3::Ast.and(self, b)
64
+ end
65
+
66
+ def +(b)
67
+ binary_arithmetic_operator(:add, b)
68
+ end
69
+
70
+ def *(b)
71
+ binary_arithmetic_operator(:mul, b)
72
+ end
73
+
74
+ def -(b)
75
+ binary_arithmetic_operator(:sub, b)
76
+ end
77
+
78
+ def >=(b)
79
+ binary_arithmetic_operator(:ge, b)
80
+ end
81
+
82
+ def >(b)
83
+ binary_arithmetic_operator(:gt, b)
84
+ end
85
+
86
+ def <=(b)
87
+ binary_arithmetic_operator(:le, b)
88
+ end
89
+
90
+ def <(b)
91
+ binary_arithmetic_operator(:lt, b)
92
+ end
93
+
94
+ def **(b)
95
+ binary_arithmetic_operator(:power, b)
96
+ end
97
+
98
+ def /(b)
99
+ binary_arithmetic_operator(:div, b)
100
+ end
101
+
102
+ def %(b)
103
+ binary_int_operator(:mod, b)
104
+ end
105
+
106
+ def rem(b)
107
+ binary_int_operator(:rem, b)
108
+ end
109
+
110
+ def -@
111
+ raise "Can only apply unary negation to Int or Real" unless int? or real?
112
+ Z3::Ast.new(Z3::LowLevel.mk_unary_minus(self))
113
+ end
114
+
115
+ def ==(b)
116
+ b = Z3::Ast.from_const(b, sort) unless b.is_a?(Z3::Ast)
117
+ if sort != b.sort
118
+ a, b = Z3::Ast.coerce_to_same_sort(self, b)
119
+ else
120
+ a = self
121
+ end
122
+ Z3::Ast.eq(self, b)
123
+ end
124
+
125
+ def !=(b)
126
+ b = Z3::Ast.from_const(b, sort) unless b.is_a?(Z3::Ast)
127
+ if sort != b.sort
128
+ a, b = Z3::Ast.coerce_to_same_sort(self, b)
129
+ else
130
+ a = self
131
+ end
132
+ Z3::Ast.distinct(a, b)
133
+ end
134
+
135
+ def coerce(other)
136
+ [Z3::Ast.from_const(other, sort), self]
137
+ end
138
+
139
+ def int_to_real
140
+ raise Z3::Exception, "Type mismatch" unless int?
141
+ Z3::Ast.new(Z3::LowLevel.mk_int2real(self))
142
+ end
143
+
144
+ class <<self
145
+ def from_const(value, sort)
146
+ case sort
147
+ when Z3::Sort.bool
148
+ raise Z3::Exception, "Can't convert #{value.class} to Bool" unless value == true or value == false
149
+ if value
150
+ Z3::Ast.true
151
+ else
152
+ Z3::Ast.false
153
+ end
154
+ when Z3::Sort.int
155
+ # (int_var == 2.4) gets changed to
156
+ # ((int_to_real int_var) == (mknumeral 2.4))
157
+ raise Z3::Exception, "Can't convert #{value.class} to Real" unless value.is_a?(Numeric)
158
+ if value.is_a?(Float)
159
+ Z3::Ast.new(Z3::LowLevel.mk_numeral(value.to_s, Z3::Sort.real))
160
+ else
161
+ Z3::Ast.new(Z3::LowLevel.mk_numeral(value.to_s, sort))
162
+ end
163
+ when Z3::Sort.real
164
+ raise Z3::Exception, "Can't convert #{value.class} to Real" unless value.is_a?(Numeric)
165
+ Z3::Ast.new(Z3::LowLevel.mk_numeral(value.to_s, sort))
166
+ end
167
+ end
168
+
169
+ def coerce_bool(value)
170
+ if value.is_a?(Z3::Ast)
171
+ return value if value.bool?
172
+ raise Z3::Exception, "Can't convert #{value.sort} to Bool"
173
+ end
174
+ raise Z3::Exception, "Can't convert #{value.class} to Bool" unless value == true or value == false
175
+ if value
176
+ Z3::Ast.true
177
+ else
178
+ Z3::Ast.false
179
+ end
180
+ end
181
+
182
+ def coerce_to_same_sort(a, b)
183
+ if a.sort == Z3::Sort.int and b.sort == Z3::Sort.real
184
+ [a.int_to_real, b]
185
+ elsif b.sort == Z3::Sort.int and a.sort == Z3::Sort.real
186
+ [a, b.int_to_real]
187
+ else
188
+ raise Z3::Exception, "No rules how to coerce #{a.sort} and #{b.sort}"
189
+ end
190
+ end
191
+
192
+ def true
193
+ Z3::Ast.new(Z3::LowLevel.mk_true)
194
+ end
195
+
196
+ def false
197
+ Z3::Ast.new(Z3::LowLevel.mk_false)
198
+ end
199
+
200
+ def eq(a, b)
201
+ Z3::Ast.new(Z3::LowLevel.mk_eq(a, b))
202
+ end
203
+
204
+ def ge(a, b)
205
+ Z3::Ast.new(Z3::LowLevel.mk_ge(a, b))
206
+ end
207
+
208
+ def gt(a, b)
209
+ Z3::Ast.new(Z3::LowLevel.mk_gt(a, b))
210
+ end
211
+
212
+ def le(a, b)
213
+ Z3::Ast.new(Z3::LowLevel.mk_le(a, b))
214
+ end
215
+
216
+ def lt(a, b)
217
+ Z3::Ast.new(Z3::LowLevel.mk_lt(a, b))
218
+ end
219
+
220
+ def power(a, b)
221
+ Z3::Ast.new(Z3::LowLevel.mk_power(a, b))
222
+ end
223
+
224
+ def div(a, b)
225
+ Z3::Ast.new(Z3::LowLevel.mk_div(a, b))
226
+ end
227
+
228
+ def mod(a, b)
229
+ Z3::Ast.new(Z3::LowLevel.mk_mod(a, b))
230
+ end
231
+
232
+ def rem(a, b)
233
+ Z3::Ast.new(Z3::LowLevel.mk_rem(a, b))
234
+ end
235
+
236
+ def not(a)
237
+ a = coerce_bool(a)
238
+ Z3::Ast.new(Z3::LowLevel.mk_not(a))
239
+ end
240
+
241
+ def distinct(*args)
242
+ Z3::Ast.new(Z3::LowLevel.mk_distinct(args))
243
+ end
244
+
245
+ def and(*args)
246
+ args = args.map{|a| coerce_bool(a)}
247
+ Z3::Ast.new(Z3::LowLevel.mk_and(args))
248
+ end
249
+
250
+ def or(*args)
251
+ args = args.map{|a| coerce_bool(a)}
252
+ Z3::Ast.new(Z3::LowLevel.mk_or(args))
253
+ end
254
+
255
+ def add(*args)
256
+ Z3::Ast.new(Z3::LowLevel.mk_add(args))
257
+ end
258
+
259
+ def iff(a, b)
260
+ a = coerce_bool(a)
261
+ b = coerce_bool(b)
262
+ Z3::Ast.new(Z3::LowLevel.mk_iff(a, b))
263
+ end
264
+
265
+ def implies(a, b)
266
+ a = coerce_bool(a)
267
+ b = coerce_bool(b)
268
+ Z3::Ast.new(Z3::LowLevel.mk_implies(a, b))
269
+ end
270
+
271
+ def sub(*args)
272
+ Z3::Ast.new(Z3::LowLevel.mk_sub(args))
273
+ end
274
+
275
+ def mul(*args)
276
+ Z3::Ast.new(Z3::LowLevel.mk_mul(args))
277
+ end
278
+
279
+ def bool(name)
280
+ var(name, Z3::Sort.bool)
281
+ end
282
+
283
+ def int(name)
284
+ var(name, Z3::Sort.int)
285
+ end
286
+
287
+ def real(name)
288
+ var(name, Z3::Sort.real)
289
+ end
290
+
291
+ private
292
+
293
+ def var(name, sort)
294
+ Z3::Ast.new(
295
+ Z3::LowLevel.mk_const(
296
+ Z3::LowLevel.mk_string_symbol(name),
297
+ sort,
298
+ )
299
+ )
300
+ end
301
+ end
302
+ end
data/lib/z3/context.rb ADDED
@@ -0,0 +1,10 @@
1
+ class Z3::Context
2
+ attr_reader :_context
3
+ def initialize
4
+ @_context = Z3::LowLevel.mk_context
5
+ end
6
+
7
+ def self.instance
8
+ @instance ||= new
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ class Z3::FuncDecl
2
+ attr_reader :_func_decl
3
+ def initialize(_func_decl)
4
+ @_func_decl = _func_decl
5
+ end
6
+
7
+ def name
8
+ Z3::LowLevel.get_symbol_string(Z3::LowLevel.get_decl_name(self))
9
+ end
10
+
11
+ def arity
12
+ Z3::LowLevel.get_arity(self)
13
+ end
14
+
15
+ def to_ast
16
+ Z3::Ast.new(Z3::LowLevel.func_decl_to_ast(self))
17
+ end
18
+
19
+ def ast_parameter(i)
20
+ # vs arity ?
21
+ Z3::Ast.new(Z3::LowLevel.get_decl_ast_parameter(self, i))
22
+ end
23
+
24
+ def to_s
25
+ name
26
+ end
27
+
28
+ def inspect
29
+ "Z3::FuncDecl<#{name}/#{arity}>"
30
+ end
31
+ end
@@ -0,0 +1,254 @@
1
+ # Seriously do not use this directly in your code
2
+ # They unwrap inputs, but don't wrap returns yet
3
+
4
+ module Z3::LowLevel
5
+ class << self
6
+ # Common API
7
+ def get_version
8
+ a = FFI::MemoryPointer.new(:int)
9
+ b = FFI::MemoryPointer.new(:int)
10
+ c = FFI::MemoryPointer.new(:int)
11
+ d = FFI::MemoryPointer.new(:int)
12
+ Z3::VeryLowLevel.Z3_get_version(a,b,c,d)
13
+ [a.get_uint(0), b.get_uint(0), c.get_uint(0), d.get_uint(0)]
14
+ end
15
+
16
+ def set_error_handler(&block)
17
+ Z3::VeryLowLevel.Z3_set_error_handler(_ctx_pointer, block)
18
+ end
19
+
20
+ def global_param_set(k,v)
21
+ Z3::VeryLowLevel.Z3_global_param_set(k.to_s, v.to_s)
22
+ end
23
+
24
+ # Context API
25
+ def mk_context
26
+ Z3::VeryLowLevel.Z3_mk_context
27
+ end
28
+
29
+ # Symbol API
30
+ def mk_string_symbol(name)
31
+ Z3::VeryLowLevel.Z3_mk_string_symbol(_ctx_pointer, name)
32
+ end
33
+
34
+ def get_symbol_string(symbol)
35
+ Z3::VeryLowLevel.Z3_get_symbol_string(_ctx_pointer, symbol)
36
+ end
37
+
38
+ # Sort API
39
+ def mk_bool_sort
40
+ Z3::VeryLowLevel.Z3_mk_bool_sort(_ctx_pointer)
41
+ end
42
+
43
+ def mk_int_sort
44
+ Z3::VeryLowLevel.Z3_mk_int_sort(_ctx_pointer)
45
+ end
46
+
47
+ def mk_real_sort
48
+ Z3::VeryLowLevel.Z3_mk_real_sort(_ctx_pointer)
49
+ end
50
+
51
+ def sort_to_string(sort)
52
+ Z3::VeryLowLevel.Z3_sort_to_string(_ctx_pointer, sort._sort)
53
+ end
54
+
55
+ # Solver API
56
+ def mk_solver
57
+ Z3::VeryLowLevel.Z3_mk_solver(_ctx_pointer)
58
+ end
59
+
60
+ def solver_push(solver)
61
+ Z3::VeryLowLevel.Z3_solver_push(_ctx_pointer, solver._solver)
62
+ end
63
+
64
+ def solver_pop(solver, n)
65
+ Z3::VeryLowLevel.Z3_solver_pop(_ctx_pointer, solver._solver, n)
66
+ end
67
+
68
+ def solver_reset(solver)
69
+ Z3::VeryLowLevel.Z3_solver_reset(_ctx_pointer, solver._solver)
70
+ end
71
+
72
+ def solver_assert(solver, ast)
73
+ Z3::VeryLowLevel.Z3_solver_assert(_ctx_pointer, solver._solver, ast._ast)
74
+ end
75
+
76
+ def solver_check(solver)
77
+ Z3::VeryLowLevel.Z3_solver_check(_ctx_pointer, solver._solver)
78
+ end
79
+
80
+ def solver_inc_ref(solver)
81
+ Z3::VeryLowLevel.Z3_solver_inc_ref(_ctx_pointer, solver._solver)
82
+ end
83
+
84
+ # Model API
85
+ def solver_get_model(solver)
86
+ Z3::VeryLowLevel.Z3_solver_get_model(_ctx_pointer, solver._solver)
87
+ end
88
+
89
+ def model_get_num_consts(model)
90
+ Z3::VeryLowLevel.Z3_model_get_num_consts(_ctx_pointer, model._model)
91
+ end
92
+
93
+ def model_get_num_funcs(model)
94
+ Z3::VeryLowLevel.Z3_model_get_num_funcs(_ctx_pointer, model._model)
95
+ end
96
+
97
+ def model_get_num_sorts(model)
98
+ Z3::VeryLowLevel.Z3_model_get_num_sorts(_ctx_pointer, model._model)
99
+ end
100
+
101
+ def model_eval(model, ast, model_completion)
102
+ rv_ptr = FFI::MemoryPointer.new(:pointer)
103
+ result = Z3::VeryLowLevel.Z3_model_eval(_ctx_pointer, model._model, ast._ast, !!model_completion, rv_ptr)
104
+ if result == 1
105
+ rv_ptr.get_pointer(0)
106
+ else
107
+ raise Z3::Exception, "Evaluation of `#{ast}' failed"
108
+ end
109
+ end
110
+
111
+ def model_get_const_decl(model, i)
112
+ Z3::VeryLowLevel.Z3_model_get_const_decl(_ctx_pointer, model._model, i)
113
+ end
114
+
115
+ # FuncDecl API
116
+ def func_decl_to_ast(func_decl)
117
+ Z3::VeryLowLevel.Z3_func_decl_to_ast(_ctx_pointer, func_decl._func_decl)
118
+ end
119
+
120
+ def get_decl_name(func_decl)
121
+ Z3::VeryLowLevel.Z3_get_decl_name(_ctx_pointer, func_decl._func_decl)
122
+ end
123
+
124
+ def get_arity(func_decl)
125
+ Z3::VeryLowLevel.Z3_get_arity(_ctx_pointer, func_decl._func_decl)
126
+ end
127
+
128
+ def get_decl_ast_parameter(func_decl, i)
129
+ Z3::VeryLowLevel.Z3_get_decl_ast_parameter(_ctx_pointer, func_decl._func_decl, i)
130
+ end
131
+
132
+ def model_get_const_interp(model, func_decl)
133
+ Z3::VeryLowLevel.Z3_model_get_const_interp(_ctx_pointer, model._model, func_decl._func_decl)
134
+ end
135
+
136
+ # AST API
137
+ def mk_true
138
+ Z3::VeryLowLevel.Z3_mk_true(_ctx_pointer)
139
+ end
140
+
141
+ def mk_false
142
+ Z3::VeryLowLevel.Z3_mk_false(_ctx_pointer)
143
+ end
144
+
145
+ def mk_eq(a,b)
146
+ Z3::VeryLowLevel.Z3_mk_eq(_ctx_pointer, a._ast, b._ast)
147
+ end
148
+
149
+ def mk_ge(a,b)
150
+ Z3::VeryLowLevel.Z3_mk_ge(_ctx_pointer, a._ast, b._ast)
151
+ end
152
+
153
+ def mk_gt(a,b)
154
+ Z3::VeryLowLevel.Z3_mk_gt(_ctx_pointer, a._ast, b._ast)
155
+ end
156
+
157
+ def mk_le(a,b)
158
+ Z3::VeryLowLevel.Z3_mk_le(_ctx_pointer, a._ast, b._ast)
159
+ end
160
+
161
+ def mk_lt(a,b)
162
+ Z3::VeryLowLevel.Z3_mk_lt(_ctx_pointer, a._ast, b._ast)
163
+ end
164
+
165
+ def mk_power(a,b)
166
+ Z3::VeryLowLevel.Z3_mk_power(_ctx_pointer, a._ast, b._ast)
167
+ end
168
+
169
+ def mk_rem(a,b)
170
+ Z3::VeryLowLevel.Z3_mk_rem(_ctx_pointer, a._ast, b._ast)
171
+ end
172
+
173
+ def mk_mod(a,b)
174
+ Z3::VeryLowLevel.Z3_mk_mod(_ctx_pointer, a._ast, b._ast)
175
+ end
176
+
177
+ def mk_div(a,b)
178
+ Z3::VeryLowLevel.Z3_mk_div(_ctx_pointer, a._ast, b._ast)
179
+ end
180
+
181
+ def mk_not(a)
182
+ Z3::VeryLowLevel.Z3_mk_not(_ctx_pointer, a._ast)
183
+ end
184
+
185
+ def mk_const(_symbol, sort)
186
+ Z3::VeryLowLevel.Z3_mk_const(_ctx_pointer, _symbol, sort._sort)
187
+ end
188
+
189
+ def mk_and(asts)
190
+ Z3::VeryLowLevel.Z3_mk_and(_ctx_pointer, asts.size, asts_vector(asts))
191
+ end
192
+
193
+ def mk_or(asts)
194
+ Z3::VeryLowLevel.Z3_mk_or(_ctx_pointer, asts.size, asts_vector(asts))
195
+ end
196
+
197
+ def mk_iff(asts)
198
+ Z3::VeryLowLevel.Z3_mk_iff(_ctx_pointer, a._ast, b._ast)
199
+ end
200
+
201
+ def mk_implies(a, b)
202
+ Z3::VeryLowLevel.Z3_mk_implies(_ctx_pointer, a._ast, b._ast)
203
+ end
204
+
205
+ def mk_mul(asts)
206
+ Z3::VeryLowLevel.Z3_mk_mul(_ctx_pointer, asts.size, asts_vector(asts))
207
+ end
208
+
209
+ def mk_add(asts)
210
+ Z3::VeryLowLevel.Z3_mk_add(_ctx_pointer, asts.size, asts_vector(asts))
211
+ end
212
+
213
+ def mk_sub(asts)
214
+ Z3::VeryLowLevel.Z3_mk_sub(_ctx_pointer, asts.size, asts_vector(asts))
215
+ end
216
+
217
+ def mk_distinct(asts)
218
+ Z3::VeryLowLevel.Z3_mk_distinct(_ctx_pointer, asts.size, asts_vector(asts))
219
+ end
220
+
221
+ def ast_to_string(ast)
222
+ Z3::VeryLowLevel.Z3_ast_to_string(_ctx_pointer, ast._ast)
223
+ end
224
+
225
+ def get_sort(ast)
226
+ Z3::VeryLowLevel.Z3_get_sort(_ctx_pointer, ast._ast)
227
+ end
228
+
229
+ def mk_int2real(ast)
230
+ Z3::VeryLowLevel.Z3_mk_int2real(_ctx_pointer, ast._ast)
231
+ end
232
+
233
+ def mk_numeral(str, sort)
234
+ Z3::VeryLowLevel.Z3_mk_numeral(_ctx_pointer, str, sort._sort)
235
+ end
236
+
237
+ def mk_unary_minus(ast)
238
+ Z3::VeryLowLevel.Z3_mk_unary_minus(_ctx_pointer, ast._ast)
239
+ end
240
+
241
+ private
242
+
243
+ def asts_vector(args)
244
+ raise if args.empty?
245
+ c_args = FFI::MemoryPointer.new(:pointer, args.size)
246
+ c_args.write_array_of_pointer args.map(&:_ast)
247
+ c_args
248
+ end
249
+
250
+ def _ctx_pointer
251
+ @_ctx_pointer ||= Z3::Context.instance._context
252
+ end
253
+ end
254
+ end
data/lib/z3/model.rb ADDED
@@ -0,0 +1,49 @@
1
+ class Z3::Model
2
+ include Enumerable
3
+
4
+ attr_reader :_model
5
+ def initialize(_model)
6
+ @_model = _model
7
+ end
8
+
9
+ def num_consts
10
+ Z3::LowLevel.model_get_num_consts(self)
11
+ end
12
+
13
+ def consts
14
+ (0...num_consts).map{|i| Z3::FuncDecl.new(Z3::LowLevel.model_get_const_decl(self, i)) }
15
+ end
16
+
17
+ def num_sorts
18
+ Z3::LowLevel.model_get_num_sorts(self)
19
+ end
20
+
21
+ def num_funcs
22
+ Z3::LowLevel.model_get_num_funcs(self)
23
+ end
24
+
25
+ def model_eval(ast, model_completion=false)
26
+ Z3::Ast.new(Z3::LowLevel.model_eval(self, ast, model_completion))
27
+ end
28
+
29
+ def [](ast)
30
+ model_eval(ast)
31
+ end
32
+
33
+ def to_s
34
+ "Z3::Model<#{ map{|n,v| "#{n}=#{v}"}.join(", ") }>"
35
+ end
36
+
37
+ def inspect
38
+ to_s
39
+ end
40
+
41
+ def each
42
+ consts.sort_by(&:name).each do |c|
43
+ yield(
44
+ c.name,
45
+ Z3::Ast::new(Z3::LowLevel.model_get_const_interp(self, c))
46
+ )
47
+ end
48
+ end
49
+ end
data/lib/z3/solver.rb ADDED
@@ -0,0 +1,68 @@
1
+ class Z3::Solver
2
+ attr_reader :_solver
3
+ def initialize
4
+ @_solver = Z3::LowLevel.mk_solver
5
+ Z3::LowLevel.solver_inc_ref(self)
6
+ end
7
+
8
+ def push
9
+ Z3::LowLevel.solver_push(self)
10
+ end
11
+
12
+ def pop(n=1)
13
+ Z3::LowLevel.solver_pop(self, n)
14
+ end
15
+
16
+ def reset
17
+ Z3::LowLevel.solver_reset(self)
18
+ end
19
+
20
+ def assert(ast)
21
+ Z3::LowLevel.solver_assert(self, ast)
22
+ end
23
+
24
+ def check
25
+ check_sat_results(Z3::LowLevel.solver_check(self))
26
+ end
27
+
28
+ def model
29
+ Z3::Model.new(
30
+ Z3::LowLevel.solver_get_model(self)
31
+ )
32
+ end
33
+
34
+ def prove!(ast)
35
+ push
36
+ assert(~ast)
37
+ case check
38
+ when :sat
39
+ puts "Counterexample exists"
40
+ model.each do |n,v|
41
+ puts "* #{n} = #{v}"
42
+ end
43
+ when :unknown
44
+ puts "Unknown"
45
+ when :unsat
46
+ puts "Proven"
47
+ else
48
+ raise "Wrong SAT result #{r}"
49
+ end
50
+ ensure
51
+ pop
52
+ end
53
+
54
+ private
55
+
56
+ def check_sat_results(r)
57
+ case r
58
+ when 1
59
+ :sat
60
+ when 0
61
+ :unknown
62
+ when -1
63
+ :unsat
64
+ else
65
+ raise "Wrong SAT result #{r}"
66
+ end
67
+ end
68
+ end