z3 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
@@ -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