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/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
|