z3 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/sort.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
class Z3::Sort
|
2
|
+
attr_reader :_sort
|
3
|
+
# Do not use .new directly
|
4
|
+
def initialize(_sort)
|
5
|
+
@_sort = _sort
|
6
|
+
end
|
7
|
+
|
8
|
+
def ==(other)
|
9
|
+
other.is_a?(Z3::Sort) and @_sort == other._sort
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
Z3::LowLevel.sort_to_string(self)
|
14
|
+
end
|
15
|
+
|
16
|
+
def inspect
|
17
|
+
"Z3::Sort<#{to_s}>"
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def bool
|
22
|
+
Z3::Sort.new(Z3::LowLevel.mk_bool_sort)
|
23
|
+
end
|
24
|
+
|
25
|
+
def int
|
26
|
+
Z3::Sort.new(Z3::LowLevel.mk_int_sort)
|
27
|
+
end
|
28
|
+
|
29
|
+
def real
|
30
|
+
Z3::Sort.new(Z3::LowLevel.mk_real_sort)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# Seriously do not use this directly in your code
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module Z3::VeryLowLevel
|
6
|
+
extend FFI::Library
|
7
|
+
ffi_lib "z3"
|
8
|
+
# Aliases defined just to make APIs below look nicer
|
9
|
+
ctx_pointer = :pointer
|
10
|
+
solver_pointer = :pointer
|
11
|
+
ast_pointer = :pointer
|
12
|
+
sort_pointer = :pointer
|
13
|
+
symbol = :pointer
|
14
|
+
model_pointer = :pointer
|
15
|
+
func_decl_pointer = :pointer
|
16
|
+
z3_bool = :int
|
17
|
+
|
18
|
+
# Common API
|
19
|
+
callback :error_handler, [ctx_pointer, :int], :void
|
20
|
+
|
21
|
+
attach_function :Z3_get_version, [:pointer, :pointer, :pointer, :pointer], :void
|
22
|
+
attach_function :Z3_set_error_handler, [ctx_pointer, :error_handler], :void
|
23
|
+
attach_function :Z3_global_param_set, [:string, :string], :void
|
24
|
+
|
25
|
+
# Context API
|
26
|
+
attach_function :Z3_mk_context, [], ctx_pointer
|
27
|
+
|
28
|
+
# Symbol API
|
29
|
+
attach_function :Z3_mk_string_symbol, [ctx_pointer, :string], symbol
|
30
|
+
attach_function :Z3_get_symbol_string, [ctx_pointer, symbol], :string
|
31
|
+
|
32
|
+
# Sort API
|
33
|
+
attach_function :Z3_mk_bool_sort, [ctx_pointer], sort_pointer
|
34
|
+
attach_function :Z3_mk_int_sort, [ctx_pointer], sort_pointer
|
35
|
+
attach_function :Z3_mk_real_sort, [ctx_pointer], sort_pointer
|
36
|
+
attach_function :Z3_sort_to_string, [ctx_pointer, sort_pointer], :string
|
37
|
+
|
38
|
+
# Solver API
|
39
|
+
attach_function :Z3_mk_solver, [ctx_pointer], solver_pointer
|
40
|
+
attach_function :Z3_solver_push, [ctx_pointer, solver_pointer], :void
|
41
|
+
attach_function :Z3_solver_pop, [ctx_pointer, solver_pointer, :int], :void
|
42
|
+
attach_function :Z3_solver_reset, [ctx_pointer, solver_pointer], :void
|
43
|
+
attach_function :Z3_solver_assert, [ctx_pointer, solver_pointer, ast_pointer], :void
|
44
|
+
attach_function :Z3_solver_check, [ctx_pointer, solver_pointer], z3_bool
|
45
|
+
attach_function :Z3_solver_inc_ref, [ctx_pointer, solver_pointer], :void
|
46
|
+
|
47
|
+
# Model API
|
48
|
+
attach_function :Z3_solver_get_model, [ctx_pointer, solver_pointer], model_pointer
|
49
|
+
attach_function :Z3_model_get_num_consts, [ctx_pointer, model_pointer], :int
|
50
|
+
attach_function :Z3_model_get_num_funcs, [ctx_pointer, model_pointer], :int
|
51
|
+
attach_function :Z3_model_get_num_sorts, [ctx_pointer, model_pointer], :int
|
52
|
+
attach_function :Z3_model_eval, [ctx_pointer, model_pointer, ast_pointer, :bool, :pointer], :int
|
53
|
+
attach_function :Z3_model_get_const_decl, [ctx_pointer, model_pointer, :int], func_decl_pointer
|
54
|
+
attach_function :Z3_model_get_const_interp, [ctx_pointer, model_pointer, func_decl_pointer], ast_pointer
|
55
|
+
|
56
|
+
# FuncDecl API
|
57
|
+
attach_function :Z3_func_decl_to_ast, [ctx_pointer, func_decl_pointer], ast_pointer
|
58
|
+
attach_function :Z3_get_decl_name, [ctx_pointer, func_decl_pointer], symbol
|
59
|
+
attach_function :Z3_get_arity, [ctx_pointer, func_decl_pointer], :uint
|
60
|
+
attach_function :Z3_get_decl_ast_parameter, [ctx_pointer, func_decl_pointer, :uint], ast_pointer
|
61
|
+
|
62
|
+
# AST API
|
63
|
+
attach_function :Z3_mk_true, [ctx_pointer], ast_pointer
|
64
|
+
attach_function :Z3_mk_false, [ctx_pointer], ast_pointer
|
65
|
+
attach_function :Z3_mk_eq, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
66
|
+
attach_function :Z3_mk_ge, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
67
|
+
attach_function :Z3_mk_gt, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
68
|
+
attach_function :Z3_mk_le, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
69
|
+
attach_function :Z3_mk_lt, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
70
|
+
attach_function :Z3_mk_power, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
71
|
+
attach_function :Z3_mk_rem, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
72
|
+
attach_function :Z3_mk_mod, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
73
|
+
attach_function :Z3_mk_div, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
74
|
+
attach_function :Z3_mk_not, [ctx_pointer, ast_pointer], ast_pointer
|
75
|
+
attach_function :Z3_mk_const, [ctx_pointer, symbol, sort_pointer], ast_pointer
|
76
|
+
attach_function :Z3_mk_and, [ctx_pointer, :int, :pointer], ast_pointer
|
77
|
+
attach_function :Z3_mk_or, [ctx_pointer, :int, :pointer], ast_pointer
|
78
|
+
attach_function :Z3_mk_iff, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
79
|
+
attach_function :Z3_mk_implies, [ctx_pointer, ast_pointer, ast_pointer], ast_pointer
|
80
|
+
attach_function :Z3_mk_add, [ctx_pointer, :int, :pointer], ast_pointer
|
81
|
+
attach_function :Z3_mk_sub, [ctx_pointer, :int, :pointer], ast_pointer
|
82
|
+
attach_function :Z3_mk_mul, [ctx_pointer, :int, :pointer], ast_pointer
|
83
|
+
attach_function :Z3_mk_distinct, [ctx_pointer, :int, :pointer], ast_pointer
|
84
|
+
attach_function :Z3_ast_to_string, [ctx_pointer, ast_pointer], :string
|
85
|
+
attach_function :Z3_get_sort, [ctx_pointer, ast_pointer], sort_pointer
|
86
|
+
attach_function :Z3_mk_int2real, [ctx_pointer, ast_pointer], ast_pointer
|
87
|
+
attach_function :Z3_mk_numeral, [ctx_pointer, :string, sort_pointer], ast_pointer
|
88
|
+
attach_function :Z3_mk_unary_minus, [ctx_pointer, ast_pointer], ast_pointer
|
89
|
+
end
|
data/lib/z3.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Z3
|
2
|
+
class <<self
|
3
|
+
def version
|
4
|
+
Z3::LowLevel.get_version.join(".")
|
5
|
+
end
|
6
|
+
|
7
|
+
def set_param(k,v)
|
8
|
+
Z3::LowLevel.global_param_set(k,v)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Z3::Exception < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
require_relative "z3/very_low_level"
|
17
|
+
require_relative "z3/low_level"
|
18
|
+
require_relative "z3/context"
|
19
|
+
require_relative "z3/solver"
|
20
|
+
require_relative "z3/sort"
|
21
|
+
require_relative "z3/ast"
|
22
|
+
require_relative "z3/model"
|
23
|
+
require_relative "z3/func_decl"
|
24
|
+
|
25
|
+
Z3::LowLevel.set_error_handler do |ctx, error|
|
26
|
+
error_codes_enum = %W[
|
27
|
+
Z3_OK
|
28
|
+
Z3_SORT_ERROR
|
29
|
+
Z3_IOB
|
30
|
+
Z3_INVALID_ARG
|
31
|
+
Z3_PARSER_ERROR
|
32
|
+
Z3_NO_PARSER
|
33
|
+
Z3_INVALID_PATTERN
|
34
|
+
Z3_MEMOUT_FAIL
|
35
|
+
Z3_FILE_ACCESS_ERROR
|
36
|
+
Z3_INTERNAL_FATAL
|
37
|
+
Z3_INVALID_USAGE
|
38
|
+
Z3_DEC_REF_ERROR
|
39
|
+
Z3_EXCEPTION
|
40
|
+
]
|
41
|
+
error = error_codes_enum[error] || error
|
42
|
+
raise Z3::Exception, "Z3 library failed with error #{error}"
|
43
|
+
end
|
data/spec/ast_spec.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
describe Z3::Ast do
|
2
|
+
let(:a) { Z3::Ast.int("a") }
|
3
|
+
let(:b) { Z3::Ast.int("b") }
|
4
|
+
let(:c) { Z3::Ast.bool("c") }
|
5
|
+
let(:d) { Z3::Ast.bool("d") }
|
6
|
+
let(:e) { Z3::Ast.real("e") }
|
7
|
+
let(:f) { Z3::Ast.real("f") }
|
8
|
+
|
9
|
+
it "#sort returns Sort object" do
|
10
|
+
expect(a.sort).to eq(Z3::Sort.int)
|
11
|
+
expect(c.sort).to eq(Z3::Sort.bool)
|
12
|
+
expect(e.sort).to eq(Z3::Sort.real)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "#to_s" do
|
16
|
+
expect(a.to_s).to eq("a")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "#inspect" do
|
20
|
+
expect(a.inspect).to eq("Z3::Ast<a :: Int>")
|
21
|
+
expect((e+f).inspect).to eq("Z3::Ast<(+ e f) :: Real>")
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#~" do
|
25
|
+
it "allows negating boolean variables" do
|
26
|
+
expect((~c).to_s).to eq("(not c)")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "raises exception if type cast is not possible" do
|
30
|
+
expect{~a}.to raise_error(Z3::Exception)
|
31
|
+
expect{~e}.to raise_error(Z3::Exception)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#&" do
|
36
|
+
it "allows and of boolean variables" do
|
37
|
+
expect((c & d).to_s).to eq("(and c d)")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "raises exception if type cast is not possible" do
|
41
|
+
expect{a&b}.to raise_error(Z3::Exception)
|
42
|
+
expect{e&f}.to raise_error(Z3::Exception)
|
43
|
+
expect{a&c}.to raise_error(Z3::Exception)
|
44
|
+
expect{e&c}.to raise_error(Z3::Exception)
|
45
|
+
expect{c&a}.to raise_error(Z3::Exception)
|
46
|
+
expect{c&e}.to raise_error(Z3::Exception)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#|" do
|
51
|
+
it "allows or of boolean variables" do
|
52
|
+
expect((c | d).to_s).to eq("(or c d)")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "raises exception if type cast is not possible" do
|
56
|
+
expect{a|b}.to raise_error(Z3::Exception)
|
57
|
+
expect{e|f}.to raise_error(Z3::Exception)
|
58
|
+
expect{a|c}.to raise_error(Z3::Exception)
|
59
|
+
expect{e|c}.to raise_error(Z3::Exception)
|
60
|
+
expect{c|a}.to raise_error(Z3::Exception)
|
61
|
+
expect{c|e}.to raise_error(Z3::Exception)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
%W[+ - * <= < >= >].each do |op|
|
66
|
+
describe "#{op} arithmetic operator" do
|
67
|
+
it "allows + of int or real variables" do
|
68
|
+
expect((a.send op, b).to_s).to eq "(#{op} a b)"
|
69
|
+
expect((e.send op, f).to_s).to eq "(#{op} e f)"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "casts to correct type if possible" do
|
73
|
+
expect((a.send op, e).to_s).to eq "(#{op} (to_real a) e)"
|
74
|
+
expect((e.send op, a).to_s).to eq "(#{op} e (to_real a))"
|
75
|
+
expect((a.send op, 42).to_s).to eq "(#{op} a 42)"
|
76
|
+
expect((42.send op, a).to_s).to eq "(#{op} 42 a)"
|
77
|
+
expect((a.send op, 42.5).to_s).to eq "(#{op} (to_real a) (/ 85.0 2.0))"
|
78
|
+
expect((42.5.send op, a).to_s).to eq "(#{op} (/ 85.0 2.0) (to_real a))"
|
79
|
+
expect((e.send op, 42).to_s).to eq "(#{op} e 42.0)"
|
80
|
+
expect((42.send op, e).to_s).to eq "(#{op} 42.0 e)"
|
81
|
+
expect((e.send op, 42.5).to_s).to eq "(#{op} e (/ 85.0 2.0))"
|
82
|
+
expect((42.5.send op, e).to_s).to eq "(#{op} (/ 85.0 2.0) e)"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "raises exception if type cast is not possible" do
|
86
|
+
expect{a.send op, c}.to raise_error(Z3::Exception)
|
87
|
+
expect{c.send op, a}.to raise_error(Z3::Exception)
|
88
|
+
expect{e.send op, c}.to raise_error(Z3::Exception)
|
89
|
+
expect{c.send op, e}.to raise_error(Z3::Exception)
|
90
|
+
expect{c.send op, d}.to raise_error(Z3::Exception)
|
91
|
+
expect{a.send op, true}.to raise_error(Z3::Exception)
|
92
|
+
expect{c.send op, true}.to raise_error(Z3::Exception)
|
93
|
+
expect{e.send op, true}.to raise_error(Z3::Exception)
|
94
|
+
expect{a.send op, false}.to raise_error(Z3::Exception)
|
95
|
+
expect{c.send op, false}.to raise_error(Z3::Exception)
|
96
|
+
expect{e.send op, false}.to raise_error(Z3::Exception)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#==" do
|
102
|
+
it "allows == of variables of same sort" do
|
103
|
+
expect((a == b).to_s).to eq "(= a b)"
|
104
|
+
expect((c == d).to_s).to eq "(= c d)"
|
105
|
+
expect((e == f).to_s).to eq "(= e f)"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "casts to correct type if possible" do
|
109
|
+
expect((a == 42).to_s).to eq "(= a 42)"
|
110
|
+
expect((42 == a).to_s).to eq "(= a 42)"
|
111
|
+
expect((a == e).to_s).to eq "(= (to_real a) e)"
|
112
|
+
expect((e == a).to_s).to eq "(= e (to_real a))"
|
113
|
+
expect((c == true).to_s).to eq "(= c true)"
|
114
|
+
expect((c == false).to_s).to eq "(= c false)"
|
115
|
+
expect((a == 42.5).to_s).to eq "(= (to_real a) (/ 85.0 2.0))"
|
116
|
+
expect((42.5 == a).to_s).to eq "(= (to_real a) (/ 85.0 2.0))"
|
117
|
+
expect((e == 42.5).to_s).to eq "(= e (/ 85.0 2.0))"
|
118
|
+
expect((42.5 == e).to_s).to eq "(= e (/ 85.0 2.0))"
|
119
|
+
# expect((true == c).to_s).to eq "(= true c)"
|
120
|
+
# expect((false == c).to_s).to eq "(= false c)"
|
121
|
+
end
|
122
|
+
|
123
|
+
it "raises exception if type cast is not possible" do
|
124
|
+
expect{a == c}.to raise_error(Z3::Exception)
|
125
|
+
expect{e == c}.to raise_error(Z3::Exception)
|
126
|
+
expect{a == true}.to raise_error(Z3::Exception)
|
127
|
+
expect{e == true}.to raise_error(Z3::Exception)
|
128
|
+
# expect{true == a}.to raise_error(Z3::Exception)
|
129
|
+
# expect{true == e}.to raise_error(Z3::Exception)
|
130
|
+
expect{c == 42}.to raise_error(Z3::Exception)
|
131
|
+
expect{c == 42.5}.to raise_error(Z3::Exception)
|
132
|
+
expect{42 == c}.to raise_error(Z3::Exception)
|
133
|
+
expect{42.5 == c}.to raise_error(Z3::Exception)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#!=" do
|
138
|
+
it "allows != of variables of same sort" do
|
139
|
+
expect((a != b).to_s).to eq "(distinct a b)"
|
140
|
+
expect((c != d).to_s).to eq "(distinct c d)"
|
141
|
+
expect((e != f).to_s).to eq "(distinct e f)"
|
142
|
+
end
|
143
|
+
|
144
|
+
it "casts to correct type if possible" do
|
145
|
+
expect((a != 42).to_s).to eq "(distinct a 42)"
|
146
|
+
# expect((42 != a).to_s).to eq "(distinct a 42)"
|
147
|
+
expect((a != e).to_s).to eq "(distinct (to_real a) e)"
|
148
|
+
expect((e != a).to_s).to eq "(distinct e (to_real a))"
|
149
|
+
expect((c != true).to_s).to eq "(distinct c true)"
|
150
|
+
expect((c != false).to_s).to eq "(distinct c false)"
|
151
|
+
expect((a != 42.5).to_s).to eq "(distinct (to_real a) (/ 85.0 2.0))"
|
152
|
+
# expect((42.5 != a).to_s).to eq "(distinct (to_real a) (/ 85.0 2.0))"
|
153
|
+
expect((e != 42.5).to_s).to eq "(distinct e (/ 85.0 2.0))"
|
154
|
+
# expect((42.5 != e).to_s).to eq "(distinct e (/ 85.0 2.0))"
|
155
|
+
# expect((true != c).to_s).to eq "(distinct true c)"
|
156
|
+
# expect((false != c).to_s).to eq "(distinct false c)"
|
157
|
+
end
|
158
|
+
|
159
|
+
it "raises exception if type cast is not possible" do
|
160
|
+
expect{a != c}.to raise_error(Z3::Exception)
|
161
|
+
expect{e != c}.to raise_error(Z3::Exception)
|
162
|
+
expect{a != true}.to raise_error(Z3::Exception)
|
163
|
+
expect{e != true}.to raise_error(Z3::Exception)
|
164
|
+
# expect{true != a}.to raise_error(Z3::Exception)
|
165
|
+
# expect{true != e}.to raise_error(Z3::Exception)
|
166
|
+
expect{c != 42}.to raise_error(Z3::Exception)
|
167
|
+
expect{c != 42.5}.to raise_error(Z3::Exception)
|
168
|
+
# expect{42 != c}.to raise_error(Z3::Exception)
|
169
|
+
# expect{42.5 != c}.to raise_error(Z3::Exception)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
describe "Algebra Problems" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/algebra_problems" }
|
3
|
+
it "can solve algebra puzzles" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
Solution to problem 01:
|
6
|
+
Solution to problem 03:
|
7
|
+
* x = (- 22.0)
|
8
|
+
* |-6| = 6.0
|
9
|
+
* |x-2| = 24.0
|
10
|
+
Solution to problem 04:
|
11
|
+
* ax = (- 4.0)
|
12
|
+
* ay = (- 5.0)
|
13
|
+
* bx = (- 1.0)
|
14
|
+
* by = (- 1.0)
|
15
|
+
* |a-b| = 5.0
|
16
|
+
Solution to problem 05:
|
17
|
+
* x = (/ 9.0 2.0)
|
18
|
+
* y = 0.0
|
19
|
+
Solution to problem 06:
|
20
|
+
* answer = 6.0
|
21
|
+
* x1 = 1.0
|
22
|
+
* x2 = 2.0
|
23
|
+
* y1 = 7.0
|
24
|
+
* y2 = 13.0
|
25
|
+
Solution to problem 10:
|
26
|
+
* x = 1.0
|
27
|
+
* |-2x + 2| = 0.0
|
28
|
+
EOF
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
describe "Basic Int Math" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/basic_int_math" }
|
3
|
+
it "can solve basic integer math problems" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
Checking if (a+b)(a-b)==a*a-b*b
|
6
|
+
Proven
|
7
|
+
Checking if a+b >= a
|
8
|
+
Counterexample exists
|
9
|
+
* b = (- 1)
|
10
|
+
Checking if a+b >= a if a,b >= 0
|
11
|
+
Proven
|
12
|
+
EOF
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe "Basic Logic" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/basic_logic" }
|
3
|
+
it "can solve basic logic problems" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
Checking if true == true
|
6
|
+
Proven
|
7
|
+
Checking if true == false
|
8
|
+
Counterexample exists
|
9
|
+
Proving ~(a & b) == (~a | ~b)
|
10
|
+
Proven
|
11
|
+
Proving ~(a | b) == (~a & ~b)
|
12
|
+
Proven
|
13
|
+
EOF
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
describe "Geometry Problem" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/geometry_problem" }
|
3
|
+
it "can solve verbal arithmetic puzzles" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
* a.x = 0.0
|
6
|
+
* a.y = (root-obj (+ (^ x 2) (- 300)) 1)
|
7
|
+
* b.x = 0.0
|
8
|
+
* b.y = 0.0
|
9
|
+
* c.x = 10.0
|
10
|
+
* c.y = 0.0
|
11
|
+
* d.x = 10.0
|
12
|
+
* d.y = (root-obj (+ (^ x 2) (- 300)) 1)
|
13
|
+
* |a-c| = (- 20.0)
|
14
|
+
* |b-d| = 20.0
|
15
|
+
EOF
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
describe "Kinematics Problems" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/kinematics_problems" }
|
3
|
+
it "can solve kinematics problems" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
Solution to problem 01:
|
6
|
+
* a = (/ 16.0 5.0)
|
7
|
+
* d = (/ 215168.0 125.0)
|
8
|
+
* t = (/ 164.0 5.0)
|
9
|
+
Solution to problem 02:
|
10
|
+
* a = (/ 2200000.0 271441.0)
|
11
|
+
* d = 110.0
|
12
|
+
* t = (/ 521.0 100.0)
|
13
|
+
Solution to problem 03:
|
14
|
+
* a = (/ 981.0 100.0)
|
15
|
+
* d = (/ 165789.0 5000.0)
|
16
|
+
* t = (/ 13.0 5.0)
|
17
|
+
* v = (/ 12753.0 500.0)
|
18
|
+
Solution to problem 04:
|
19
|
+
* a = (/ 2760.0 247.0)
|
20
|
+
* d = (/ 79781.0 1000.0)
|
21
|
+
* t = (/ 247.0 100.0)
|
22
|
+
* ve = (/ 461.0 10.0)
|
23
|
+
* vs = (/ 37.0 2.0)
|
24
|
+
Solution to problem 05:
|
25
|
+
* a = (/ 167.0 100.0)
|
26
|
+
* d = (/ 7.0 5.0)
|
27
|
+
* t = (root-obj (+ (* 167 (^ x 2)) (- 280)) 2)
|
28
|
+
Solution to problem 06:
|
29
|
+
* a = (/ 14800.0 61.0)
|
30
|
+
* d = (/ 20313.0 50.0)
|
31
|
+
* t = (/ 183.0 100.0)
|
32
|
+
* v = 444.0
|
33
|
+
Solution to problem 07:
|
34
|
+
* a = (/ 5041.0 7080.0)
|
35
|
+
* d = (/ 177.0 5.0)
|
36
|
+
* t = (/ 708.0 71.0)
|
37
|
+
* v = (/ 71.0 10.0)
|
38
|
+
Solution to problem 08:
|
39
|
+
* a = 3.0
|
40
|
+
* d = (/ 4225.0 6.0)
|
41
|
+
* t = (/ 65.0 3.0)
|
42
|
+
* v = 65.0
|
43
|
+
Solution to problem 09:
|
44
|
+
* d = (/ 714.0 25.0)
|
45
|
+
* t = (/ 51.0 20.0)
|
46
|
+
* v = (/ 112.0 5.0)
|
47
|
+
Solution to problem 10:
|
48
|
+
* a = (- (/ 981.0 100.0))
|
49
|
+
* d = (/ 131.0 50.0)
|
50
|
+
* t = (root-obj (+ (* 981 (^ x 2)) (- 524)) 2)
|
51
|
+
* v = (root-obj (+ (* 2500 (^ x 2)) (- 128511)) 2)
|
52
|
+
EOF
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
describe "LightUp" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/light_up_solver" }
|
3
|
+
it "can solve light up puzzle" do
|
4
|
+
expect(IO.popen(executable).read.gsub(/ *$/, "")).to eq <<EOF
|
5
|
+
* 0
|
6
|
+
*
|
7
|
+
x 2*x
|
8
|
+
*3 *
|
9
|
+
* x*x*3
|
10
|
+
*
|
11
|
+
*1 *
|
12
|
+
EOF
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
describe "MiniSudoku" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/minisudoku_solver" }
|
3
|
+
it "can solve minisudoku" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
2 1 5 4 3 6
|
6
|
+
3 6 4 1 2 5
|
7
|
+
1 3 6 5 4 2
|
8
|
+
4 5 2 3 6 1
|
9
|
+
5 2 3 6 1 4
|
10
|
+
6 4 1 2 5 3
|
11
|
+
EOF
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe "Self-Referential Aptitude Test" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/selfref_solver" }
|
3
|
+
it "can solve minisudokus" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
Q 1: D
|
6
|
+
Q 2: A
|
7
|
+
Q 3: D
|
8
|
+
Q 4: B
|
9
|
+
Q 5: E
|
10
|
+
Q 6: D
|
11
|
+
Q 7: D
|
12
|
+
Q 8: E
|
13
|
+
Q 9: D
|
14
|
+
Q10: A
|
15
|
+
Q11: B
|
16
|
+
Q12: A
|
17
|
+
Q13: D
|
18
|
+
Q14: B
|
19
|
+
Q15: A
|
20
|
+
Q16: D
|
21
|
+
Q17: B
|
22
|
+
Q18: A
|
23
|
+
Q19: B
|
24
|
+
Q20: E
|
25
|
+
EOF
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
describe "Sudoku" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/sudoku_solver" }
|
3
|
+
it "can solve sudoku" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
8 6 3 5 7 9 2 4 1
|
6
|
+
9 2 5 3 1 4 8 7 6
|
7
|
+
4 7 1 8 2 6 9 5 3
|
8
|
+
7 1 4 6 8 3 5 2 9
|
9
|
+
6 8 9 7 5 2 3 1 4
|
10
|
+
3 5 2 4 9 1 6 8 7
|
11
|
+
1 3 6 2 4 5 7 9 8
|
12
|
+
2 4 8 9 3 7 1 6 5
|
13
|
+
5 9 7 1 6 8 4 3 2
|
14
|
+
EOF
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe "Verbal Arithmetic" do
|
2
|
+
let(:executable) { "#{__dir__}/../../examples/verbal_arithmetic" }
|
3
|
+
it "can solve verbal arithmetic puzzles" do
|
4
|
+
expect(IO.popen(executable).read).to eq <<EOF
|
5
|
+
[["S", 9], ["E", 5], ["N", 6], ["D", 7]]
|
6
|
+
[["M", 1], ["O", 0], ["R", 8], ["E", 5]]
|
7
|
+
[["M", 1], ["O", 0], ["N", 6], ["E", 5], ["Y", 2]]
|
8
|
+
EOF
|
9
|
+
end
|
10
|
+
end
|
data/spec/model_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Solver and Model specs are codependent, so half of functionality of each is tested in other class's tests
|
2
|
+
describe Z3::Model do
|
3
|
+
let(:solver) { Z3::Solver.new }
|
4
|
+
let(:a) { Z3::Ast.int("a") }
|
5
|
+
let(:b) { Z3::Ast.int("b") }
|
6
|
+
let(:c) { Z3::Ast.int("c") }
|
7
|
+
let(:model) { solver.model }
|
8
|
+
|
9
|
+
it "knows how many variables are in the model" do
|
10
|
+
solver.assert(a == 2)
|
11
|
+
solver.assert(b == a+2)
|
12
|
+
expect(solver.check).to eq(:sat)
|
13
|
+
expect(model.num_consts).to eq(2)
|
14
|
+
expect(model.num_funcs).to eq(0)
|
15
|
+
expect(model.num_sorts).to eq(0)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can evaluate variables" do
|
19
|
+
solver.assert(a == 2)
|
20
|
+
solver.assert(b == a+2)
|
21
|
+
expect(solver.check).to eq(:sat)
|
22
|
+
expect(model.model_eval(a).inspect).to eq("Z3::Ast<2 :: Int>")
|
23
|
+
expect(model.model_eval(b).inspect).to eq("Z3::Ast<4 :: Int>")
|
24
|
+
expect(model.model_eval(c).inspect).to eq("Z3::Ast<c :: Int>")
|
25
|
+
expect(model.model_eval(a, true).inspect).to eq("Z3::Ast<2 :: Int>")
|
26
|
+
expect(model.model_eval(b, true).inspect).to eq("Z3::Ast<4 :: Int>")
|
27
|
+
expect(model.model_eval(c, true).inspect).to eq("Z3::Ast<0 :: Int>")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "#to_s" do
|
31
|
+
solver.assert(a == 2)
|
32
|
+
solver.assert(b == a+2)
|
33
|
+
expect(solver.check).to eq(:sat)
|
34
|
+
expect(model.to_s).to eq("Z3::Model<a=2, b=4>")
|
35
|
+
expect(model.inspect).to eq("Z3::Model<a=2, b=4>")
|
36
|
+
end
|
37
|
+
end
|
data/spec/solver_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Solver and Model specs are codependent, so half of functionality of each is tested in other class's tests
|
2
|
+
describe Z3::Solver do
|
3
|
+
let(:solver) { Z3::Solver.new }
|
4
|
+
let(:a) { Z3::Ast.int("a") }
|
5
|
+
let(:b) { Z3::Ast.int("b") }
|
6
|
+
|
7
|
+
it "basic functionality" do
|
8
|
+
solver.assert(a == b)
|
9
|
+
expect(solver.check).to eq(:sat)
|
10
|
+
solver.assert(a != b)
|
11
|
+
expect(solver.check).to eq(:unsat)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "push/pop" do
|
15
|
+
solver.assert(a == b)
|
16
|
+
solver.push
|
17
|
+
solver.assert(a != b)
|
18
|
+
expect(solver.check).to eq(:unsat)
|
19
|
+
solver.pop
|
20
|
+
expect(solver.check).to eq(:sat)
|
21
|
+
end
|
22
|
+
end
|
data/spec/sort_spec.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
describe Z3::Sort do
|
2
|
+
it "#bool creates Bool sort" do
|
3
|
+
expect(Z3::Sort.bool.to_s).to eq("Bool")
|
4
|
+
expect(Z3::Sort.bool.inspect).to eq("Z3::Sort<Bool>")
|
5
|
+
end
|
6
|
+
|
7
|
+
it "#int creates Int sort" do
|
8
|
+
expect(Z3::Sort.int.to_s).to eq("Int")
|
9
|
+
expect(Z3::Sort.int.inspect).to eq("Z3::Sort<Int>")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "#real creates Real sort" do
|
13
|
+
expect(Z3::Sort.real.to_s).to eq("Real")
|
14
|
+
expect(Z3::Sort.real.inspect).to eq("Z3::Sort<Real>")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "supports ==" do
|
18
|
+
expect(Z3::Sort.bool).to eq(Z3::Sort.bool)
|
19
|
+
expect(Z3::Sort.int).to eq(Z3::Sort.int)
|
20
|
+
expect(Z3::Sort.bool).to_not eq(Z3::Sort.int)
|
21
|
+
end
|
22
|
+
end
|