z3 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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