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.
- checksums.yaml +7 -0
- data/README.md +27 -0
- data/examples/algebra_problems +148 -0
- data/examples/basic_int_math +30 -0
- data/examples/basic_logic +41 -0
- data/examples/geometry_problem +40 -0
- data/examples/kinematics_problems +219 -0
- data/examples/light_up_solver +105 -0
- data/examples/minisudoku_solver +64 -0
- data/examples/selfref_solver +370 -0
- data/examples/sudoku_solver +67 -0
- data/examples/verbal_arithmetic +47 -0
- data/lib/z3/ast.rb +302 -0
- data/lib/z3/context.rb +10 -0
- data/lib/z3/func_decl.rb +31 -0
- data/lib/z3/low_level.rb +254 -0
- data/lib/z3/model.rb +49 -0
- data/lib/z3/solver.rb +68 -0
- data/lib/z3/sort.rb +33 -0
- data/lib/z3/very_low_level.rb +89 -0
- data/lib/z3.rb +43 -0
- data/spec/ast_spec.rb +172 -0
- data/spec/integration/algebra_problems_spec.rb +30 -0
- data/spec/integration/bagic_int_math_spec.rb +14 -0
- data/spec/integration/basic_logic_spec.rb +15 -0
- data/spec/integration/geometry_problem_spec.rb +17 -0
- data/spec/integration/kinematics_problems_spec.rb +54 -0
- data/spec/integration/light_up_spec.rb +14 -0
- data/spec/integration/minisudoku_spec.rb +13 -0
- data/spec/integration/selfref_spec.rb +27 -0
- data/spec/integration/sudoku_spec.rb +16 -0
- data/spec/integration/verbal_arithmetic_spec.rb +10 -0
- data/spec/model_spec.rb +37 -0
- data/spec/solver_spec.rb +22 -0
- data/spec/sort_spec.rb +22 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/z3_spec.rb +5 -0
- metadata +81 -0
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
data/lib/z3/func_decl.rb
ADDED
@@ -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
|
data/lib/z3/low_level.rb
ADDED
@@ -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
|