z3 0.0.20160221 → 0.0.20160323
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 +4 -4
- data/README.md +3 -1
- data/examples/algebra_problems +24 -24
- data/examples/basic_int_math +8 -8
- data/examples/basic_logic +8 -8
- data/examples/bit_tricks +161 -0
- data/examples/bridges_solver +1 -1
- data/examples/clogic_puzzle_solver +135 -0
- data/examples/four_hackers_puzzle +194 -0
- data/examples/geometry_problem +11 -11
- data/examples/kakuro_solver +3 -3
- data/examples/kinematics_problems +37 -37
- data/examples/letter_connections_solver +11 -11
- data/examples/light_up_solver +5 -5
- data/examples/minisudoku_solver +4 -4
- data/examples/selfref_solver +35 -35
- data/examples/sudoku_solver +4 -4
- data/examples/verbal_arithmetic +2 -2
- data/lib/z3/exception.rb +25 -0
- data/lib/z3/func_decl.rb +7 -7
- data/lib/z3/interface.rb +255 -0
- data/lib/z3/low_level.rb +4 -6
- data/lib/z3/low_level_auto.rb +1551 -1547
- data/lib/z3/model.rb +3 -2
- data/lib/z3/solver.rb +65 -54
- data/lib/z3/sort/bitvec_sort.rb +40 -0
- data/lib/z3/sort/bool_sort.rb +31 -0
- data/lib/z3/sort/int_sort.rb +21 -0
- data/lib/z3/sort/real_sort.rb +36 -0
- data/lib/z3/sort/sort.rb +76 -0
- data/lib/z3/value/arith_value.rb +53 -0
- data/lib/z3/value/bitvec_value.rb +67 -0
- data/lib/z3/value/bool_value.rb +29 -0
- data/lib/z3/value/int_value.rb +7 -0
- data/lib/z3/value/real_value.rb +7 -0
- data/lib/z3/value/value.rb +48 -0
- data/lib/z3/very_low_level.rb +28 -45
- data/lib/z3/very_low_level_auto.rb +518 -516
- data/lib/z3.rb +23 -33
- data/spec/integration/bit_tricks_spec.rb +21 -0
- data/spec/model_spec.rb +9 -9
- data/spec/solver_spec.rb +2 -2
- data/spec/sort_spec.rb +38 -13
- data/spec/{ast_spec.rb → value_spec.rb} +60 -57
- metadata +21 -6
- data/lib/z3/ast.rb +0 -302
- data/lib/z3/sort.rb +0 -33
- /data/spec/integration/{bagic_int_math_spec.rb → basic_int_math_spec.rb} +0 -0
@@ -0,0 +1,194 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
class LogicPuzzleCase
|
6
|
+
attr_reader :index
|
7
|
+
def initialize(puzzle, index)
|
8
|
+
@puzzle = puzzle
|
9
|
+
@index = index
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_missing(key, *args)
|
13
|
+
key = key.to_s
|
14
|
+
if @puzzle.has_key?(key) and args.size == 1
|
15
|
+
@puzzle.attribute(@index, key, *args)
|
16
|
+
elsif @puzzle.has_key?(key) and args.size == 0
|
17
|
+
@puzzle.vars[key][@index]
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class LogicPuzzle
|
25
|
+
attr_reader :vars, :dict
|
26
|
+
def initialize(count)
|
27
|
+
# In puzzles of this kind, all assignments are of same size
|
28
|
+
@count = count
|
29
|
+
@solver = Z3::Solver.new
|
30
|
+
@vars = {}
|
31
|
+
@dict = {}
|
32
|
+
@cases = @count.times.map{|i| LogicPuzzleCase.new(self, i) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def each(&blk)
|
36
|
+
@cases.each(&blk)
|
37
|
+
end
|
38
|
+
|
39
|
+
def attribute_values(name, *vals)
|
40
|
+
raise "All assignments must have same number of elements" unless vals.size == @count
|
41
|
+
vars = @count.times.map{|i| Z3.Int("#{i}-#{name}") }
|
42
|
+
vars.each do |v|
|
43
|
+
@solver.assert v >= 0
|
44
|
+
@solver.assert v < @count
|
45
|
+
end
|
46
|
+
@solver.assert Z3.Distinct(*vars)
|
47
|
+
@dict[name] = vals
|
48
|
+
@vars[name] = vars
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_key?(key)
|
52
|
+
@vars.has_key?(key)
|
53
|
+
end
|
54
|
+
|
55
|
+
def attribute(idx, key, val)
|
56
|
+
raise "Attribute #{key} not defined" unless @vars.has_key?(key)
|
57
|
+
val_idx = @dict[key].index(val) or raise "Value #{val} for attribute #{key} not possible"
|
58
|
+
@vars[key][idx] == val_idx
|
59
|
+
end
|
60
|
+
|
61
|
+
def solve!
|
62
|
+
add_assertions!
|
63
|
+
if @solver.check == :sat
|
64
|
+
@solver.model.each do |k,v|
|
65
|
+
i, name = k.split("-", 2)
|
66
|
+
puts "#{k} = #{@dict[name][v.to_i]}"
|
67
|
+
end
|
68
|
+
else
|
69
|
+
puts "Puzzle has no solutions"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def implies!(a, b)
|
74
|
+
@solver.assert Z3.Implies(a, b)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class FourHackersPuzzle < LogicPuzzle
|
79
|
+
def initialize
|
80
|
+
super(4)
|
81
|
+
attribute_values *%W[name Armand Dragonene Frogger Phineus]
|
82
|
+
attribute_values *%W[alias Badger Griffin Lennard Monks]
|
83
|
+
attribute_values *%W[country Belgium England Norway Yemen]
|
84
|
+
attribute_values *%W[language C Java Lisp Perl]
|
85
|
+
attribute_values *%W[amount 10000 80000 160000 640000]
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_assertions!
|
89
|
+
each do |hacker|
|
90
|
+
implies!( hacker.name("Phineus"), hacker.amount("10000") )
|
91
|
+
implies!( hacker.alias("Lennard"), hacker.amount("160000") )
|
92
|
+
implies!( hacker.alias("Lennard"), ~hacker.country("England") )
|
93
|
+
# 2nd connection less money transferred than C coder
|
94
|
+
implies!( hacker.language("C"), @cases[1].amount < hacker.amount )
|
95
|
+
implies!( hacker.language("C"), ~hacker.country("Norway") )
|
96
|
+
implies!( hacker.name("Armand"), hacker.alias("Monks") )
|
97
|
+
end
|
98
|
+
|
99
|
+
# Armand stole more than Frogger
|
100
|
+
each do |a|
|
101
|
+
each do |b|
|
102
|
+
implies!(
|
103
|
+
a.name("Armand") & b.name("Frogger"),
|
104
|
+
a.amount > b.amount
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
each do |hacker|
|
110
|
+
implies!( hacker.name("Dragonene"), hacker.country("Belgium") )
|
111
|
+
end
|
112
|
+
|
113
|
+
# Dragonene less money than Perl coder
|
114
|
+
each do |a|
|
115
|
+
each do |b|
|
116
|
+
implies!(
|
117
|
+
a.name("Dragonene") & b.language("Perl"),
|
118
|
+
a.amount < b.amount
|
119
|
+
)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
# perl coder made the connection before Dragonene?
|
123
|
+
each do |a|
|
124
|
+
each do |b|
|
125
|
+
implies!(
|
126
|
+
a.name("Dragonene") & b.language("Perl"),
|
127
|
+
a.index > b.index
|
128
|
+
)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
# Lisp coder more money than Griffin
|
132
|
+
each do |a|
|
133
|
+
each do |b|
|
134
|
+
implies!(
|
135
|
+
a.alias("Griffin") & b.language("Lisp"),
|
136
|
+
a.amount < b.amount
|
137
|
+
)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
# 3rd connection used Java
|
141
|
+
@solver.assert @cases[2].language("Java")
|
142
|
+
# Badger stole more than Yemen coder
|
143
|
+
each do |a|
|
144
|
+
each do |b|
|
145
|
+
implies!(
|
146
|
+
a.alias("Badger") & b.country("Yemen"),
|
147
|
+
a.amount > b.amount
|
148
|
+
)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
FourHackersPuzzle.new.solve!
|
155
|
+
|
156
|
+
"""
|
157
|
+
There is little we can do but wait, so we may as well take another job.
|
158
|
+
It seems there has been a bank robbery. Scotland Yard has turned to us for help in figuring out who did it.
|
159
|
+
We have been the given the following information:
|
160
|
+
|
161
|
+
There were 4 hackers each connecting one after another.
|
162
|
+
Each hacker has a name and another alias too.
|
163
|
+
Each hacker connected from a different country.
|
164
|
+
Each hacker connected using a different programming language.
|
165
|
+
Each hacker transferred a different amount of money.
|
166
|
+
|
167
|
+
The 4 hacker names: Armand Dragonene Frogger Phineus
|
168
|
+
The 4 hacker aliases: Badger Griffin Lennard Monks
|
169
|
+
The 4 countries: Belgium England Norway Yemen
|
170
|
+
The 4 coding langauges: C Java Lisp Perl
|
171
|
+
The 4 amounts: 10000 80000 160000 640000
|
172
|
+
You must also determine the order the hackers connected: 1st, 2nd, 3rd, 4th
|
173
|
+
|
174
|
+
Perhaps following the news may help. The attacks all took place on the 29th, but the newspapers reported it for a couple of days afterwards as they found new information:
|
175
|
+
|
176
|
+
https://www.sabrefilms.co.uk/revolutionelite/casefiles/case9/img1.jpg
|
177
|
+
https://www.sabrefilms.co.uk/revolutionelite/casefiles/case9/img2.jpg
|
178
|
+
https://www.sabrefilms.co.uk/revolutionelite/casefiles/case9/img3.jpg
|
179
|
+
|
180
|
+
--------------------------------------------------------------------------------
|
181
|
+
Extracted rules:
|
182
|
+
Phineus => 10000
|
183
|
+
Lennard => 160000 && !England
|
184
|
+
2nd connection less money transferred than C coder
|
185
|
+
C coder !Norwary
|
186
|
+
Armand (Monks)
|
187
|
+
Armand stole more than Frogger
|
188
|
+
Dragonene => Belgium
|
189
|
+
Dragonene less money than Perl coder
|
190
|
+
perl coder made the connection before Dragonene?
|
191
|
+
Lisp coder more money than Griffin
|
192
|
+
3rd connection used Java
|
193
|
+
Badger stole more than Yemen coder
|
194
|
+
"""
|
data/examples/geometry_problem
CHANGED
@@ -4,17 +4,17 @@ require_relative "../lib/z3"
|
|
4
4
|
|
5
5
|
solver = Z3::Solver.new
|
6
6
|
|
7
|
-
ax = Z3
|
8
|
-
ay = Z3
|
9
|
-
bx = Z3
|
10
|
-
by = Z3
|
11
|
-
cx = Z3
|
12
|
-
cy = Z3
|
13
|
-
dx = Z3
|
14
|
-
dy = Z3
|
15
|
-
|
16
|
-
a_c = Z3
|
17
|
-
b_d = Z3
|
7
|
+
ax = Z3.Real("a.x")
|
8
|
+
ay = Z3.Real("a.y")
|
9
|
+
bx = Z3.Real("b.x")
|
10
|
+
by = Z3.Real("b.y")
|
11
|
+
cx = Z3.Real("c.x")
|
12
|
+
cy = Z3.Real("c.y")
|
13
|
+
dx = Z3.Real("d.x")
|
14
|
+
dy = Z3.Real("d.y")
|
15
|
+
|
16
|
+
a_c = Z3.Real("|a-c|")
|
17
|
+
b_d = Z3.Real("|b-d|")
|
18
18
|
|
19
19
|
solver.assert(bx == 0)
|
20
20
|
solver.assert(by == 0)
|
data/examples/kakuro_solver
CHANGED
@@ -87,7 +87,7 @@ class Kakuro
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def cell_var(x,y)
|
90
|
-
v = Z3
|
90
|
+
v = Z3.Int("c#{x},#{y}")
|
91
91
|
@solver.assert v >= 1
|
92
92
|
@solver.assert v <= 9
|
93
93
|
v
|
@@ -103,8 +103,8 @@ class Kakuro
|
|
103
103
|
y += dy
|
104
104
|
end
|
105
105
|
return if vs.empty?
|
106
|
-
@solver.assert Z3
|
107
|
-
@solver.assert Z3
|
106
|
+
@solver.assert Z3.Distinct(*vs)
|
107
|
+
@solver.assert Z3.Add(*vs) == sum
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
@@ -32,9 +32,9 @@ class KinematicsProblem01 < KinematicsProblem
|
|
32
32
|
Determine the distance traveled before takeoff.
|
33
33
|
"""
|
34
34
|
def solve!
|
35
|
-
a = Z3
|
36
|
-
t = Z3
|
37
|
-
d = Z3
|
35
|
+
a = Z3.Real("a")
|
36
|
+
t = Z3.Real("t")
|
37
|
+
d = Z3.Real("d")
|
38
38
|
assert a == 3.20
|
39
39
|
assert t == 32.8
|
40
40
|
assert d == a*t*t/2
|
@@ -47,9 +47,9 @@ class KinematicsProblem02 < KinematicsProblem
|
|
47
47
|
A car starts from rest and accelerates uniformly over a time of 5.21 seconds for a distance of 110 m. Determine the acceleration of the car.
|
48
48
|
"""
|
49
49
|
def solve!
|
50
|
-
a = Z3
|
51
|
-
t = Z3
|
52
|
-
d = Z3
|
50
|
+
a = Z3.Real("a")
|
51
|
+
t = Z3.Real("t")
|
52
|
+
d = Z3.Real("d")
|
53
53
|
assert d == a*t*t/2
|
54
54
|
assert t == 5.21
|
55
55
|
assert d == 110
|
@@ -63,10 +63,10 @@ class KinematicsProblem03 < KinematicsProblem
|
|
63
63
|
If Upton free falls for 2.60 seconds, what will be his final velocity and how far will he fall?
|
64
64
|
"""
|
65
65
|
def solve!
|
66
|
-
a = Z3
|
67
|
-
t = Z3
|
68
|
-
v = Z3
|
69
|
-
d = Z3
|
66
|
+
a = Z3.Real("a")
|
67
|
+
t = Z3.Real("t")
|
68
|
+
v = Z3.Real("v")
|
69
|
+
d = Z3.Real("d")
|
70
70
|
assert a == 9.81
|
71
71
|
assert d == a*t*t/2
|
72
72
|
assert v == a*t
|
@@ -80,11 +80,11 @@ class KinematicsProblem04 < KinematicsProblem
|
|
80
80
|
A race car accelerates uniformly from 18.5 m/s to 46.1 m/s in 2.47 seconds. Determine the acceleration of the car and the distance traveled.
|
81
81
|
"""
|
82
82
|
def solve!
|
83
|
-
a = Z3
|
84
|
-
t = Z3
|
85
|
-
vs= Z3
|
86
|
-
ve = Z3
|
87
|
-
d = Z3
|
83
|
+
a = Z3.Real("a")
|
84
|
+
t = Z3.Real("t")
|
85
|
+
vs= Z3.Real("vs")
|
86
|
+
ve = Z3.Real("ve")
|
87
|
+
d = Z3.Real("d")
|
88
88
|
assert vs == 18.5
|
89
89
|
assert ve == 46.1
|
90
90
|
assert t == 2.47
|
@@ -101,9 +101,9 @@ class KinematicsProblem05 < KinematicsProblem
|
|
101
101
|
Determine the time for the feather to fall to the surface of the moon.
|
102
102
|
"""
|
103
103
|
def solve!
|
104
|
-
a = Z3
|
105
|
-
t = Z3
|
106
|
-
d = Z3
|
104
|
+
a = Z3.Real("a")
|
105
|
+
t = Z3.Real("t")
|
106
|
+
d = Z3.Real("d")
|
107
107
|
assert a == 1.67
|
108
108
|
assert d == 1.40
|
109
109
|
assert t >= 0
|
@@ -119,10 +119,10 @@ class KinematicsProblem06 < KinematicsProblem
|
|
119
119
|
then what is the acceleration and what is the distance that the sled travels?
|
120
120
|
"""
|
121
121
|
def solve!
|
122
|
-
a = Z3
|
123
|
-
t = Z3
|
124
|
-
d = Z3
|
125
|
-
v = Z3
|
122
|
+
a = Z3.Real("a")
|
123
|
+
t = Z3.Real("t")
|
124
|
+
d = Z3.Real("d")
|
125
|
+
v = Z3.Real("v")
|
126
126
|
assert v == 444
|
127
127
|
assert t == 1.83
|
128
128
|
assert v == a*t
|
@@ -137,10 +137,10 @@ class KinematicsProblem07 < KinematicsProblem
|
|
137
137
|
Determine the acceleration of the bike.
|
138
138
|
"""
|
139
139
|
def solve!
|
140
|
-
a = Z3
|
141
|
-
t = Z3
|
142
|
-
d = Z3
|
143
|
-
v = Z3
|
140
|
+
a = Z3.Real("a")
|
141
|
+
t = Z3.Real("t")
|
142
|
+
d = Z3.Real("d")
|
143
|
+
v = Z3.Real("v")
|
144
144
|
assert v == 7.10
|
145
145
|
assert d == 35.4
|
146
146
|
assert a*t == v
|
@@ -157,10 +157,10 @@ class KinematicsProblem08 < KinematicsProblem
|
|
157
157
|
Assuming this minimum acceleration, what is the minimum allowed length for the runway?
|
158
158
|
"""
|
159
159
|
def solve!
|
160
|
-
a = Z3
|
161
|
-
t = Z3
|
162
|
-
d = Z3
|
163
|
-
v = Z3
|
160
|
+
a = Z3.Real("a")
|
161
|
+
t = Z3.Real("t")
|
162
|
+
d = Z3.Real("d")
|
163
|
+
v = Z3.Real("v")
|
164
164
|
assert a == 3
|
165
165
|
assert v == 65
|
166
166
|
assert a*t == v
|
@@ -175,9 +175,9 @@ class KinematicsProblem09 < KinematicsProblem
|
|
175
175
|
Determine the skidding distance of the car (assume uniform acceleration).
|
176
176
|
"""
|
177
177
|
def solve!
|
178
|
-
t = Z3
|
179
|
-
d = Z3
|
180
|
-
v = Z3
|
178
|
+
t = Z3.Real("t")
|
179
|
+
d = Z3.Real("d")
|
180
|
+
v = Z3.Real("v")
|
181
181
|
assert v == 22.4
|
182
182
|
assert t == 2.55
|
183
183
|
assert d == t*v/2
|
@@ -191,10 +191,10 @@ class KinematicsProblem10 < KinematicsProblem
|
|
191
191
|
Determine the takeoff speed of the kangaroo.
|
192
192
|
"""
|
193
193
|
def solve!
|
194
|
-
a = Z3
|
195
|
-
t = Z3
|
196
|
-
d = Z3
|
197
|
-
v = Z3
|
194
|
+
a = Z3.Real("a")
|
195
|
+
t = Z3.Real("t")
|
196
|
+
d = Z3.Real("d")
|
197
|
+
v = Z3.Real("v")
|
198
198
|
assert d == 2.62
|
199
199
|
assert a == -9.81
|
200
200
|
assert d == v*t/2
|
@@ -74,29 +74,29 @@ class LetterConnections
|
|
74
74
|
if x == 0
|
75
75
|
@solver.assert @dir[[x,y]] != 0
|
76
76
|
else
|
77
|
-
@solver.assert Z3
|
78
|
-
@solver.assert Z3
|
77
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 0, @line[[x,y]] == @line[[x-1,y]])
|
78
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 0, @dir[[x-1,y]] != 2)
|
79
79
|
end
|
80
80
|
# Direction Up
|
81
81
|
if y == 0
|
82
82
|
@solver.assert @dir[[x,y]] != 1
|
83
83
|
else
|
84
|
-
@solver.assert Z3
|
85
|
-
@solver.assert Z3
|
84
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 1, @line[[x,y]] == @line[[x,y-1]])
|
85
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 1, @dir[[x,y-1]] != 3)
|
86
86
|
end
|
87
87
|
# Direction Right
|
88
88
|
if x == @xsize - 1
|
89
89
|
@solver.assert @dir[[x,y]] != 2
|
90
90
|
else
|
91
|
-
@solver.assert Z3
|
92
|
-
@solver.assert Z3
|
91
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 2, @line[[x,y]] == @line[[x+1,y]])
|
92
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 2, @dir[[x+1,y]] != 0)
|
93
93
|
end
|
94
94
|
# Direction Down
|
95
95
|
if y == @ysize - 1
|
96
96
|
@solver.assert @dir[[x,y]] != 3
|
97
97
|
else
|
98
|
-
@solver.assert Z3
|
99
|
-
@solver.assert Z3
|
98
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 3, @line[[x,y]] == @line[[x,y+1]])
|
99
|
+
@solver.assert Z3.Implies(@dir[[x,y]] == 3, @dir[[x,y+1]] != 1)
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
@@ -128,14 +128,14 @@ class LetterConnections
|
|
128
128
|
end
|
129
129
|
|
130
130
|
def line_var(x, y)
|
131
|
-
v = Z3
|
131
|
+
v = Z3.Int("l#{x},#{y}")
|
132
132
|
@solver.assert v >= 0
|
133
133
|
@solver.assert v < @letters.size
|
134
134
|
v
|
135
135
|
end
|
136
136
|
|
137
137
|
def dir_var(x, y)
|
138
|
-
v = Z3
|
138
|
+
v = Z3.Int("d#{x},#{y}")
|
139
139
|
@solver.assert v >= 0
|
140
140
|
@solver.assert v <= 3
|
141
141
|
v
|
@@ -154,7 +154,7 @@ class LetterConnections
|
|
154
154
|
|
155
155
|
# Surely Z3 must have a thing for it
|
156
156
|
def condition_exactly_one(conds)
|
157
|
-
@solver.assert Z3
|
157
|
+
@solver.assert Z3.Or(*conds)
|
158
158
|
(0...conds.size).each do |ci|
|
159
159
|
(0...conds.size).each do |cj|
|
160
160
|
if ci < cj
|
data/examples/light_up_solver
CHANGED
@@ -22,7 +22,7 @@ class LightUp
|
|
22
22
|
next if v == "."
|
23
23
|
@solver.assert @lamps[[x,y]] == 0
|
24
24
|
if ("0".."4").include?(v)
|
25
|
-
@solver.assert Z3
|
25
|
+
@solver.assert Z3.Add(*lamps_next_to_cell(x,y)) == v.to_i
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -31,9 +31,9 @@ class LightUp
|
|
31
31
|
# No lamp is in raycast of another lamp
|
32
32
|
(0...@ysize).each do |y|
|
33
33
|
(0...@xsize).each do |x|
|
34
|
-
raycast = Z3
|
35
|
-
@solver.assert Z3
|
36
|
-
@solver.assert Z3
|
34
|
+
raycast = Z3.Add(*raycast_cells(x,y))
|
35
|
+
@solver.assert Z3.Implies(@lamps[[x,y]] == 0, raycast >= 1)
|
36
|
+
@solver.assert Z3.Implies(@lamps[[x,y]] == 1, raycast == 0)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -85,7 +85,7 @@ class LightUp
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def int01(x,y)
|
88
|
-
v = Z3
|
88
|
+
v = Z3.Int("l#{x},#{y}")
|
89
89
|
@solver.assert v >= 0
|
90
90
|
@solver.assert v <= 1
|
91
91
|
v
|
data/examples/minisudoku_solver
CHANGED
@@ -16,14 +16,14 @@ class MiniSudokuSolver
|
|
16
16
|
end
|
17
17
|
|
18
18
|
@cells.each do |row|
|
19
|
-
@solver.assert Z3
|
19
|
+
@solver.assert Z3.Distinct(*row)
|
20
20
|
end
|
21
21
|
@cells.transpose.each do |column|
|
22
|
-
@solver.assert Z3
|
22
|
+
@solver.assert Z3.Distinct(*column)
|
23
23
|
end
|
24
24
|
@cells.each_slice(2) do |rows|
|
25
25
|
rows.transpose.each_slice(3) do |square|
|
26
|
-
@solver.assert Z3
|
26
|
+
@solver.assert Z3.Distinct(*square.flatten)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -38,7 +38,7 @@ class MiniSudokuSolver
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def cell_var(cell, i, j)
|
41
|
-
v = Z3
|
41
|
+
v = Z3.Int("cell[#{i+1},#{j+1}]")
|
42
42
|
@solver.assert v >= 1
|
43
43
|
@solver.assert v <= 6
|
44
44
|
@solver.assert v == cell if cell != nil
|
data/examples/selfref_solver
CHANGED
@@ -10,12 +10,12 @@ class SelfRefPuzzleSolver
|
|
10
10
|
@q = {}
|
11
11
|
@a = {}
|
12
12
|
(1..20).each do |i|
|
13
|
-
@q[i] = Z3
|
13
|
+
@q[i] = Z3.Int("q#{i}")
|
14
14
|
assert @q[i] >= 1
|
15
15
|
assert @q[i] <= 5
|
16
16
|
@a[i] = {}
|
17
17
|
(1..5).each do |j|
|
18
|
-
@a[i][j] = Z3
|
18
|
+
@a[i][j] = Z3.Int("a#{i},#{' ABCDE'[j]}")
|
19
19
|
assert (@a[i][j] == 0) == (@q[i] != j)
|
20
20
|
assert (@a[i][j] == 1) == (@q[i] == j)
|
21
21
|
end
|
@@ -27,23 +27,23 @@ class SelfRefPuzzleSolver
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def cons_in(*ary)
|
30
|
-
Z3
|
30
|
+
Z3.Or(*ary.map{|i| cons_answers == i})
|
31
31
|
end
|
32
32
|
|
33
33
|
def solve!
|
34
|
-
@a_answers = Z3
|
35
|
-
@b_answers = Z3
|
36
|
-
@c_answers = Z3
|
37
|
-
@d_answers = Z3
|
38
|
-
@e_answers = Z3
|
34
|
+
@a_answers = Z3.Add(*(1..20).map{|i| @a[i][1]})
|
35
|
+
@b_answers = Z3.Add(*(1..20).map{|i| @a[i][2]})
|
36
|
+
@c_answers = Z3.Add(*(1..20).map{|i| @a[i][3]})
|
37
|
+
@d_answers = Z3.Add(*(1..20).map{|i| @a[i][4]})
|
38
|
+
@e_answers = Z3.Add(*(1..20).map{|i| @a[i][5]})
|
39
39
|
@cons_answers = b_answers + c_answers + d_answers
|
40
40
|
|
41
41
|
# Question 1
|
42
42
|
assert (q[1] == 1) == (q[1] == 2)
|
43
|
-
assert (q[1] == 2) == Z3
|
44
|
-
assert (q[1] == 3) == Z3
|
45
|
-
assert (q[1] == 4) == Z3
|
46
|
-
assert (q[1] == 5) == Z3
|
43
|
+
assert (q[1] == 2) == Z3.And(q[1] != 2, q[2] == 2)
|
44
|
+
assert (q[1] == 3) == Z3.And(q[1] != 2, q[2] != 2, q[3] == 2)
|
45
|
+
assert (q[1] == 4) == Z3.And(q[1] != 2, q[2] != 2, q[3] != 2, q[4] == 2)
|
46
|
+
assert (q[1] == 5) == Z3.And(q[1] != 2, q[2] != 2, q[3] != 2, q[4] != 2, q[5] == 2)
|
47
47
|
|
48
48
|
# Question 2
|
49
49
|
assert q[ 1] != q[ 2]
|
@@ -81,25 +81,25 @@ class SelfRefPuzzleSolver
|
|
81
81
|
assert (a_answers == 8) == (q[4] == 5)
|
82
82
|
|
83
83
|
# Question 5
|
84
|
-
assert Z3
|
85
|
-
assert Z3
|
86
|
-
assert Z3
|
87
|
-
assert Z3
|
88
|
-
assert Z3
|
84
|
+
assert Z3.Implies(q[5] == 1, q[5] == q[1])
|
85
|
+
assert Z3.Implies(q[5] == 2, q[5] == q[2])
|
86
|
+
assert Z3.Implies(q[5] == 3, q[5] == q[3])
|
87
|
+
assert Z3.Implies(q[5] == 4, q[5] == q[4])
|
88
|
+
assert Z3.Implies(q[5] == 5, q[5] == q[5])
|
89
89
|
|
90
90
|
# Question 6
|
91
91
|
assert (q[17] == 3) == (q[6] == 1)
|
92
92
|
assert (q[17] == 4) == (q[6] == 2)
|
93
93
|
assert (q[17] == 5) == (q[6] == 3)
|
94
|
-
assert Z3
|
94
|
+
assert Z3.Or(q[17] == 1, q[17] == 2) == (q[6] == 4)
|
95
95
|
assert q[6] != 5
|
96
96
|
|
97
97
|
# Question 7
|
98
|
-
assert Z3
|
99
|
-
assert Z3
|
100
|
-
assert Z3
|
101
|
-
assert Z3
|
102
|
-
assert Z3
|
98
|
+
assert Z3.Or(q[7] - q[8] == 4, q[8] - q[7] == 4) == (q[7] == 1)
|
99
|
+
assert Z3.Or(q[7] - q[8] == 3, q[8] - q[7] == 3) == (q[7] == 2)
|
100
|
+
assert Z3.Or(q[7] - q[8] == 2, q[8] - q[7] == 2) == (q[7] == 3)
|
101
|
+
assert Z3.Or(q[7] - q[8] == 1, q[8] - q[7] == 1) == (q[7] == 4)
|
102
|
+
assert Z3.Or(q[7] - q[8] == 0, q[8] - q[7] == 0) == (q[7] == 5)
|
103
103
|
|
104
104
|
# Question 8
|
105
105
|
assert (a_answers + e_answers == 4) == (q[8] == 1)
|
@@ -110,10 +110,10 @@ class SelfRefPuzzleSolver
|
|
110
110
|
|
111
111
|
# Question 9
|
112
112
|
assert (q[10] == q[9]) == (q[9] == 1)
|
113
|
-
assert Z3
|
114
|
-
assert Z3
|
115
|
-
assert Z3
|
116
|
-
assert Z3
|
113
|
+
assert Z3.And(q[10] != q[9], q[11] == q[9]) == (q[9] == 2)
|
114
|
+
assert Z3.And(q[10] != q[9], q[11] != q[9], q[12] == q[9]) == (q[9] == 3)
|
115
|
+
assert Z3.And(q[10] != q[9], q[11] != q[9], q[12] != q[9], q[13] == q[9]) == (q[9] == 4)
|
116
|
+
assert Z3.And(q[10] != q[9], q[11] != q[9], q[12] != q[9], q[13] != q[9], q[14] == q[9]) == (q[9] == 5)
|
117
117
|
|
118
118
|
# Question 10
|
119
119
|
assert (q[16] == 4) == (q[10] == 1)
|
@@ -123,7 +123,7 @@ class SelfRefPuzzleSolver
|
|
123
123
|
assert (q[16] == 3) == (q[10] == 5)
|
124
124
|
|
125
125
|
# Question 11
|
126
|
-
prec_b_answers = Z3
|
126
|
+
prec_b_answers = Z3.Add(*(1..10).map{|i| @a[i][2]})
|
127
127
|
assert (prec_b_answers == 0) == (q[11] == 1)
|
128
128
|
assert (prec_b_answers == 1) == (q[11] == 2)
|
129
129
|
assert (prec_b_answers == 2) == (q[11] == 3)
|
@@ -131,11 +131,11 @@ class SelfRefPuzzleSolver
|
|
131
131
|
assert (prec_b_answers == 4) == (q[11] == 5)
|
132
132
|
|
133
133
|
# Question 12
|
134
|
-
assert Z3
|
135
|
-
assert Z3
|
136
|
-
assert Z3
|
137
|
-
assert Z3
|
138
|
-
assert Z3
|
134
|
+
assert Z3.Implies(q[12] == 1, cons_in(2,4,6,8,10,12,14,16,18,20))
|
135
|
+
assert Z3.Implies(q[12] == 2, cons_in(1,3,5,7,9,11,13,15,17,19))
|
136
|
+
assert Z3.Implies(q[12] == 3, cons_in(1,4,9,16))
|
137
|
+
assert Z3.Implies(q[12] == 4, cons_in(2,3,5,7,11,13,17,19))
|
138
|
+
assert Z3.Implies(q[12] == 5, cons_in(5,10,15,20))
|
139
139
|
|
140
140
|
# Question 13
|
141
141
|
assert q[1] != 1
|
@@ -170,7 +170,7 @@ class SelfRefPuzzleSolver
|
|
170
170
|
assert (q[6] == 3) == (q[17] == 1)
|
171
171
|
assert (q[6] == 4) == (q[17] == 2)
|
172
172
|
assert (q[6] == 5) == (q[17] == 3)
|
173
|
-
assert Z3
|
173
|
+
assert Z3.And(q[6] != 3, q[6] != 4, q[6] != 5) == (q[17] == 4)
|
174
174
|
assert q[17] != 5
|
175
175
|
|
176
176
|
# Question 18
|
@@ -178,7 +178,7 @@ class SelfRefPuzzleSolver
|
|
178
178
|
assert (a_answers == c_answers) == (q[18] == 2)
|
179
179
|
assert (a_answers == d_answers) == (q[18] == 3)
|
180
180
|
assert (a_answers == e_answers) == (q[18] == 4)
|
181
|
-
assert Z3
|
181
|
+
assert Z3.And(
|
182
182
|
a_answers != b_answers,
|
183
183
|
a_answers != c_answers,
|
184
184
|
a_answers != d_answers,
|
data/examples/sudoku_solver
CHANGED
@@ -16,14 +16,14 @@ class SudokuSolver
|
|
16
16
|
end
|
17
17
|
|
18
18
|
@cells.each do |row|
|
19
|
-
@solver.assert Z3
|
19
|
+
@solver.assert Z3.Distinct(*row)
|
20
20
|
end
|
21
21
|
@cells.transpose.each do |column|
|
22
|
-
@solver.assert Z3
|
22
|
+
@solver.assert Z3.Distinct(*column)
|
23
23
|
end
|
24
24
|
@cells.each_slice(3) do |rows|
|
25
25
|
rows.transpose.each_slice(3) do |square|
|
26
|
-
@solver.assert Z3
|
26
|
+
@solver.assert Z3.Distinct(*square.flatten)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -38,7 +38,7 @@ class SudokuSolver
|
|
38
38
|
private
|
39
39
|
|
40
40
|
def cell_var(cell, i, j)
|
41
|
-
v = Z3
|
41
|
+
v = Z3.Int("cell[#{i+1},#{j+1}]")
|
42
42
|
@solver.assert v >= 1
|
43
43
|
@solver.assert v <= 9
|
44
44
|
@solver.assert v == cell if cell != nil
|