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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9155c71b227576436cf55fe332fb04748bf8a2ed
|
4
|
+
data.tar.gz: bf1c5200d857ed21311d2f5cb468e8cceac2f627
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 67c4b499c50f0c288900667f13bcdcca543629d55332a6247011c8e135b1d9b41a4865f9900e2884155aa28844492c3fcb1d5aacad775e1b556e3d1a6a265d3a
|
7
|
+
data.tar.gz: 88e74e1966920896bc2ca0ec8a2712c8180aeb79a97be8551aceb69b21016df907a579091fded5b688f8ebc8bdd3ad4ede8037f6a4458b7fa1831081b5f2bcee
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
This is Ruby interface for Z3 [ https://github.com/Z3Prover/z3 ].
|
2
|
+
|
3
|
+
It's in extremely early stages of development. Pull requests always welcome.
|
4
|
+
|
5
|
+
### Interface
|
6
|
+
|
7
|
+
`Z3::VeryLowLever` / `Z3::LowLevel` are low level FFI interface, and they shouldn't be used directly.
|
8
|
+
|
9
|
+
The rest of `Z3` is high level API, but the interface is extremely unstable at this point, and it's pretty much guaranteed to change many times. Check specs or `examples/` directory for usage.
|
10
|
+
|
11
|
+
You can use most Ruby operators to construct ASTs, but use `~ | &` instead of `! || &&` for boolean operators.
|
12
|
+
|
13
|
+
As for API internals, attributes starting with `_` are FFI internals you shouldn't touch, other attributes are generally legitimate Ruby objects.
|
14
|
+
|
15
|
+
### Requirements
|
16
|
+
|
17
|
+
To use it, you'll need to install `z3`. On OSX that would be:
|
18
|
+
|
19
|
+
brew install z3
|
20
|
+
|
21
|
+
On other systems use appropriate package manager.
|
22
|
+
|
23
|
+
### Known Bugs
|
24
|
+
|
25
|
+
Ruby API tries to catch the most common mistakes, but if you use API in a weird way you can get C crash instead of nice Ruby exception.
|
26
|
+
|
27
|
+
Memory will leak a good deal. Generally avoid in long running processes.
|
@@ -0,0 +1,148 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
class AlgebraProblem
|
6
|
+
attr_reader :solver
|
7
|
+
def initialize
|
8
|
+
@solver = Z3::Solver.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def print_solution!(number)
|
12
|
+
puts("Solution to problem %s:" % number)
|
13
|
+
if @solver.check() == :sat
|
14
|
+
@solver.model.each do |n,v|
|
15
|
+
puts "* #{n} = #{v}"
|
16
|
+
end
|
17
|
+
else
|
18
|
+
puts "* Can't solve the problem"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class AlgebraProblem01 < AlgebraProblem
|
24
|
+
def solve!
|
25
|
+
x = Z3::Ast.real("x")
|
26
|
+
solver.assert 5*(-3*x - 2) - (x - 3) == -4*(4*x + 5) + 13
|
27
|
+
print_solution! "01"
|
28
|
+
# No nice way to say x is unconstrained
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class AlgebraProblem03 < AlgebraProblem
|
33
|
+
def declare_abs(var, expr)
|
34
|
+
solver.assert Z3::Ast.or(
|
35
|
+
Z3::Ast.and(var == expr, expr >= 0),
|
36
|
+
Z3::Ast.and(var == -expr, expr <= 0)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def solve!
|
41
|
+
x = Z3::Ast.real("x")
|
42
|
+
xm2abs = Z3::Ast.real("|x-2|")
|
43
|
+
declare_abs(xm2abs, x-2)
|
44
|
+
m6abs = Z3::Ast.real("|-6|")
|
45
|
+
declare_abs(m6abs, -6)
|
46
|
+
solver.assert x < 2
|
47
|
+
solver.assert xm2abs == 4*m6abs
|
48
|
+
print_solution! "03"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class AlgebraProblem04 < AlgebraProblem
|
53
|
+
def declare_distance(a_b, ax, ay, bx, by)
|
54
|
+
solver.assert a_b >= 0
|
55
|
+
solver.assert a_b**2 == (ax-bx)**2 + (ay-by)**2
|
56
|
+
end
|
57
|
+
|
58
|
+
def solve!
|
59
|
+
ax = Z3::Ast.real("ax")
|
60
|
+
ay = Z3::Ast.real("ay")
|
61
|
+
bx = Z3::Ast.real("bx")
|
62
|
+
by = Z3::Ast.real("by")
|
63
|
+
a_b = Z3::Ast.real("|a-b|")
|
64
|
+
declare_distance(a_b, ax, ay, bx, by)
|
65
|
+
solver.assert ax == -4
|
66
|
+
solver.assert ay == -5
|
67
|
+
solver.assert bx == -1
|
68
|
+
solver.assert by == -1
|
69
|
+
print_solution! "04"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class AlgebraProblem05 < AlgebraProblem
|
74
|
+
def solve!
|
75
|
+
x = Z3::Ast.real("x")
|
76
|
+
y = Z3::Ast.real("y")
|
77
|
+
solver.assert 2*x - 4*y == 9
|
78
|
+
solver.assert y == 0
|
79
|
+
print_solution! "05"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class AlgebraProblem06 < AlgebraProblem
|
84
|
+
def declare_f(x,y)
|
85
|
+
solver.assert y == 6*x + 1
|
86
|
+
end
|
87
|
+
|
88
|
+
def solve!
|
89
|
+
x1 = Z3::Ast.real("x1")
|
90
|
+
y1 = Z3::Ast.real("y1")
|
91
|
+
x2 = Z3::Ast.real("x2")
|
92
|
+
y2 = Z3::Ast.real("y2")
|
93
|
+
answer = Z3::Ast.real("answer")
|
94
|
+
solver.assert x2 == 2
|
95
|
+
solver.assert x1 == 1
|
96
|
+
declare_f(x1, y1)
|
97
|
+
declare_f(x2, y2)
|
98
|
+
solver.assert answer == y2 - y1
|
99
|
+
print_solution! "06"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class AlgebraProblem10 < AlgebraProblem
|
104
|
+
def declare_abs(var, expr)
|
105
|
+
solver.assert Z3::Ast.or(
|
106
|
+
Z3::Ast.and(var == expr, expr >= 0),
|
107
|
+
Z3::Ast.and(var == -expr, expr <= 0)
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def solve!
|
112
|
+
x = Z3::Ast.real("x")
|
113
|
+
y = Z3::Ast.real("|-2x + 2|")
|
114
|
+
declare_abs(y, -2*x + 2)
|
115
|
+
solver.assert y - 3 == -3
|
116
|
+
print_solution! "10"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
AlgebraProblem01.new.solve!
|
121
|
+
AlgebraProblem03.new.solve!
|
122
|
+
AlgebraProblem04.new.solve!
|
123
|
+
AlgebraProblem05.new.solve!
|
124
|
+
AlgebraProblem06.new.solve!
|
125
|
+
AlgebraProblem10.new.solve!
|
126
|
+
|
127
|
+
"""
|
128
|
+
http://www.analyzemath.com/Algebra1/Algebra1.html
|
129
|
+
|
130
|
+
|
131
|
+
Problem 1: Solve the equation
|
132
|
+
5(-3x - 2) - (x - 3) = -4(4x + 5) + 13
|
133
|
+
|
134
|
+
Problem 3: If x <2, simplify
|
135
|
+
|x - 2| = 4|-6|
|
136
|
+
(actually I misread original, whatever)
|
137
|
+
|
138
|
+
Problem 4: Find the distance between the points (-4 , -5) and (-1 , -1).
|
139
|
+
|
140
|
+
Problem 5: Find the x intercept of the graph of the equation
|
141
|
+
2x - 4y = 9
|
142
|
+
|
143
|
+
Problem 6: Evaluate f(2) - f(1)
|
144
|
+
f(x) = 6x + 1
|
145
|
+
|
146
|
+
Problem 10: Solve the equation
|
147
|
+
|-2x + 2| -3 = -3
|
148
|
+
"""
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
def check_multiplication_laws_1
|
6
|
+
a = Z3::Ast.int("a")
|
7
|
+
b = Z3::Ast.int("b")
|
8
|
+
solver = Z3::Solver.new
|
9
|
+
puts "Checking if (a+b)(a-b)==a*a-b*b"
|
10
|
+
solver.prove!(
|
11
|
+
(a+b)*(a-b) == (a*a - b*b)
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def check_inequalities
|
16
|
+
a = Z3::Ast.int("a")
|
17
|
+
b = Z3::Ast.int("b")
|
18
|
+
solver = Z3::Solver.new
|
19
|
+
puts "Checking if a+b >= a"
|
20
|
+
solver.prove!(a+b >= a)
|
21
|
+
|
22
|
+
solver = Z3::Solver.new
|
23
|
+
solver.assert(a >= 0)
|
24
|
+
solver.assert(b >= 0)
|
25
|
+
puts "Checking if a+b >= a if a,b >= 0"
|
26
|
+
solver.prove!(a+b >= a)
|
27
|
+
end
|
28
|
+
|
29
|
+
check_multiplication_laws_1
|
30
|
+
check_inequalities
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
def check_if_true_is_true
|
6
|
+
a = Z3::Ast.true
|
7
|
+
b = Z3::Ast.true
|
8
|
+
solver = Z3::Solver.new
|
9
|
+
puts "Checking if true == true"
|
10
|
+
solver.prove!(a == b)
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_if_true_is_false
|
14
|
+
a = Z3::Ast.true
|
15
|
+
b = Z3::Ast.false
|
16
|
+
solver = Z3::Solver.new
|
17
|
+
puts "Checking if true == false"
|
18
|
+
solver.prove!(a==b)
|
19
|
+
end
|
20
|
+
|
21
|
+
# We prove it by checking that negation is unsatisfiable
|
22
|
+
def check_de_morgan_law_1
|
23
|
+
a = Z3::Ast::bool("a")
|
24
|
+
b = Z3::Ast::bool("b")
|
25
|
+
solver = Z3::Solver.new
|
26
|
+
puts "Proving ~(a & b) == (~a | ~b)"
|
27
|
+
solver.prove!(~(a & b) == (~a | ~b))
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_de_morgan_law_2
|
31
|
+
a = Z3::Ast::bool("a")
|
32
|
+
b = Z3::Ast::bool("b")
|
33
|
+
solver = Z3::Solver.new
|
34
|
+
puts "Proving ~(a | b) == (~a & ~b)"
|
35
|
+
solver.prove!(~(a | b) == (~a & ~b))
|
36
|
+
end
|
37
|
+
|
38
|
+
check_if_true_is_true
|
39
|
+
check_if_true_is_false
|
40
|
+
check_de_morgan_law_1
|
41
|
+
check_de_morgan_law_2
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
solver = Z3::Solver.new
|
6
|
+
|
7
|
+
ax = Z3::Ast.real("a.x")
|
8
|
+
ay = Z3::Ast.real("a.y")
|
9
|
+
bx = Z3::Ast.real("b.x")
|
10
|
+
by = Z3::Ast.real("b.y")
|
11
|
+
cx = Z3::Ast.real("c.x")
|
12
|
+
cy = Z3::Ast.real("c.y")
|
13
|
+
dx = Z3::Ast.real("d.x")
|
14
|
+
dy = Z3::Ast.real("d.y")
|
15
|
+
|
16
|
+
a_c = Z3::Ast.real("|a-c|")
|
17
|
+
b_d = Z3::Ast.real("|b-d|")
|
18
|
+
|
19
|
+
solver.assert(bx == 0)
|
20
|
+
solver.assert(by == 0)
|
21
|
+
solver.assert(cx == 10)
|
22
|
+
solver.assert(cy == 0)
|
23
|
+
solver.assert(dx == cx)
|
24
|
+
solver.assert(ay == dy)
|
25
|
+
solver.assert(ax == 0)
|
26
|
+
|
27
|
+
# BD is on the circle
|
28
|
+
solver.assert(b_d**2 == (bx-dx)**2 + (by-dy)**2)
|
29
|
+
solver.assert(b_d == 20)
|
30
|
+
|
31
|
+
solver.assert(a_c**2 == (ax-cx)**2 + (ay-cy)**2)
|
32
|
+
|
33
|
+
if solver.check == :sat
|
34
|
+
model = solver.model
|
35
|
+
model.each do |n,v|
|
36
|
+
puts "* #{n} = #{v}"
|
37
|
+
end
|
38
|
+
else
|
39
|
+
puts "Can't solve the problem"
|
40
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Problems from: http://www.physicsclassroom.com/class/1DKin/Lesson-6/Sample-Problems-and-Solutions
|
4
|
+
|
5
|
+
require_relative "../lib/z3"
|
6
|
+
|
7
|
+
class KinematicsProblem
|
8
|
+
attr_reader :solver
|
9
|
+
def initialize
|
10
|
+
@solver = Z3::Solver.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def assert(ast)
|
14
|
+
@solver.assert(ast)
|
15
|
+
end
|
16
|
+
|
17
|
+
def print_solution!(number)
|
18
|
+
puts("Solution to problem %s:" % number)
|
19
|
+
if @solver.check() == :sat
|
20
|
+
@solver.model.each do |n,v|
|
21
|
+
puts "* #{n} = #{v}"
|
22
|
+
end
|
23
|
+
else
|
24
|
+
puts "* Can't solve the problem"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class KinematicsProblem01 < KinematicsProblem
|
30
|
+
"""
|
31
|
+
An airplane accelerates down a runway at 3.20 m/s2 for 32.8 s until is finally lifts off the ground.
|
32
|
+
Determine the distance traveled before takeoff.
|
33
|
+
"""
|
34
|
+
def solve!
|
35
|
+
a = Z3::Ast.real("a")
|
36
|
+
t = Z3::Ast.real("t")
|
37
|
+
d = Z3::Ast.real("d")
|
38
|
+
assert a == 3.20
|
39
|
+
assert t == 32.8
|
40
|
+
assert d == a*t*t/2
|
41
|
+
print_solution! "01"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class KinematicsProblem02 < KinematicsProblem
|
46
|
+
"""
|
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
|
+
"""
|
49
|
+
def solve!
|
50
|
+
a = Z3::Ast.real("a")
|
51
|
+
t = Z3::Ast.real("t")
|
52
|
+
d = Z3::Ast.real("d")
|
53
|
+
assert d == a*t*t/2
|
54
|
+
assert t == 5.21
|
55
|
+
assert d == 110
|
56
|
+
print_solution! "02"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class KinematicsProblem03 < KinematicsProblem
|
61
|
+
"""
|
62
|
+
Upton Chuck is riding the Giant Drop at Great America.
|
63
|
+
If Upton free falls for 2.60 seconds, what will be his final velocity and how far will he fall?
|
64
|
+
"""
|
65
|
+
def solve!
|
66
|
+
a = Z3::Ast.real("a")
|
67
|
+
t = Z3::Ast.real("t")
|
68
|
+
v = Z3::Ast.real("v")
|
69
|
+
d = Z3::Ast.real("d")
|
70
|
+
assert a == 9.81
|
71
|
+
assert d == a*t*t/2
|
72
|
+
assert v == a*t
|
73
|
+
assert t == 2.60
|
74
|
+
print_solution! "03"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class KinematicsProblem04 < KinematicsProblem
|
79
|
+
"""
|
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
|
+
"""
|
82
|
+
def solve!
|
83
|
+
a = Z3::Ast.real("a")
|
84
|
+
t = Z3::Ast.real("t")
|
85
|
+
vs= Z3::Ast.real("vs")
|
86
|
+
ve = Z3::Ast.real("ve")
|
87
|
+
d = Z3::Ast.real("d")
|
88
|
+
assert vs == 18.5
|
89
|
+
assert ve == 46.1
|
90
|
+
assert t == 2.47
|
91
|
+
assert a == (ve-vs)/t
|
92
|
+
assert d == (vs+ve)/2*t
|
93
|
+
print_solution! "04"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class KinematicsProblem05 < KinematicsProblem
|
98
|
+
"""
|
99
|
+
A feather is dropped on the moon from a height of 1.40 meters.
|
100
|
+
The acceleration of gravity on the moon is 1.67 m/s2.
|
101
|
+
Determine the time for the feather to fall to the surface of the moon.
|
102
|
+
"""
|
103
|
+
def solve!
|
104
|
+
a = Z3::Ast.real("a")
|
105
|
+
t = Z3::Ast.real("t")
|
106
|
+
d = Z3::Ast.real("d")
|
107
|
+
assert a == 1.67
|
108
|
+
assert d == 1.40
|
109
|
+
assert t >= 0
|
110
|
+
assert d == a*t*t/2
|
111
|
+
print_solution! "05"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class KinematicsProblem06 < KinematicsProblem
|
116
|
+
"""
|
117
|
+
Rocket-powered sleds are used to test the human response to acceleration.
|
118
|
+
If a rocket-powered sled is accelerated to a speed of 444 m/s in 1.83 seconds,
|
119
|
+
then what is the acceleration and what is the distance that the sled travels?
|
120
|
+
"""
|
121
|
+
def solve!
|
122
|
+
a = Z3::Ast.real("a")
|
123
|
+
t = Z3::Ast.real("t")
|
124
|
+
d = Z3::Ast.real("d")
|
125
|
+
v = Z3::Ast.real("v")
|
126
|
+
assert v == 444
|
127
|
+
assert t == 1.83
|
128
|
+
assert v == a*t
|
129
|
+
assert d == a*t*t/2
|
130
|
+
print_solution! "06"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class KinematicsProblem07 < KinematicsProblem
|
135
|
+
"""
|
136
|
+
A bike accelerates uniformly from rest to a speed of 7.10 m/s over a distance of 35.4 m.
|
137
|
+
Determine the acceleration of the bike.
|
138
|
+
"""
|
139
|
+
def solve!
|
140
|
+
a = Z3::Ast.real("a")
|
141
|
+
t = Z3::Ast.real("t")
|
142
|
+
d = Z3::Ast.real("d")
|
143
|
+
v = Z3::Ast.real("v")
|
144
|
+
assert v == 7.10
|
145
|
+
assert d == 35.4
|
146
|
+
assert a*t == v
|
147
|
+
assert t*v/2 == d
|
148
|
+
print_solution! "07"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class KinematicsProblem08 < KinematicsProblem
|
153
|
+
"""
|
154
|
+
An engineer is designing the runway for an airport.
|
155
|
+
Of the planes that will use the airport, the lowest acceleration rate is likely to be 3 m/s2.
|
156
|
+
The takeoff speed for this plane will be 65 m/s.
|
157
|
+
Assuming this minimum acceleration, what is the minimum allowed length for the runway?
|
158
|
+
"""
|
159
|
+
def solve!
|
160
|
+
a = Z3::Ast.real("a")
|
161
|
+
t = Z3::Ast.real("t")
|
162
|
+
d = Z3::Ast.real("d")
|
163
|
+
v = Z3::Ast.real("v")
|
164
|
+
assert a == 3
|
165
|
+
assert v == 65
|
166
|
+
assert a*t == v
|
167
|
+
assert t*v/2 == d
|
168
|
+
print_solution! "08"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
class KinematicsProblem09 < KinematicsProblem
|
173
|
+
"""
|
174
|
+
A car traveling at 22.4 m/s skids to a stop in 2.55 s.
|
175
|
+
Determine the skidding distance of the car (assume uniform acceleration).
|
176
|
+
"""
|
177
|
+
def solve!
|
178
|
+
t = Z3::Ast.real("t")
|
179
|
+
d = Z3::Ast.real("d")
|
180
|
+
v = Z3::Ast.real("v")
|
181
|
+
assert v == 22.4
|
182
|
+
assert t == 2.55
|
183
|
+
assert d == t*v/2
|
184
|
+
print_solution! "09"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class KinematicsProblem10 < KinematicsProblem
|
189
|
+
"""
|
190
|
+
A kangaroo is capable of jumping to a height of 2.62 m.
|
191
|
+
Determine the takeoff speed of the kangaroo.
|
192
|
+
"""
|
193
|
+
def solve!
|
194
|
+
a = Z3::Ast.real("a")
|
195
|
+
t = Z3::Ast.real("t")
|
196
|
+
d = Z3::Ast.real("d")
|
197
|
+
v = Z3::Ast.real("v")
|
198
|
+
assert d == 2.62
|
199
|
+
assert a == -9.81
|
200
|
+
assert d == v*t/2
|
201
|
+
assert v + a*t == 0
|
202
|
+
assert t >= 0
|
203
|
+
print_solution! "10"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# This is actually param for Python Z3 printer, can't work until we get that
|
208
|
+
# Z3.set_param("rational_to_decimal", true)
|
209
|
+
|
210
|
+
KinematicsProblem01.new.solve!
|
211
|
+
KinematicsProblem02.new.solve!
|
212
|
+
KinematicsProblem03.new.solve!
|
213
|
+
KinematicsProblem04.new.solve!
|
214
|
+
KinematicsProblem05.new.solve!
|
215
|
+
KinematicsProblem06.new.solve!
|
216
|
+
KinematicsProblem07.new.solve!
|
217
|
+
KinematicsProblem08.new.solve!
|
218
|
+
KinematicsProblem09.new.solve!
|
219
|
+
KinematicsProblem10.new.solve!
|
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
class LightUp
|
6
|
+
def initialize(data)
|
7
|
+
data = data.split.map{|line| line.strip.chars}
|
8
|
+
@xsize = data[0].size
|
9
|
+
@ysize = data.size
|
10
|
+
@data = map_coordinates{|x,y| data[y][x]}
|
11
|
+
@solver = Z3::Solver.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def solve!
|
15
|
+
@lamps = map_coordinates{|x,y| int01(x,y)}
|
16
|
+
|
17
|
+
# No lamps on walls
|
18
|
+
# Numbers count lamps next to node (diagonals don't count)
|
19
|
+
(0...@ysize).each do |y|
|
20
|
+
(0...@xsize).each do |x|
|
21
|
+
v = @data[[x,y]]
|
22
|
+
next if v == "."
|
23
|
+
@solver.assert @lamps[[x,y]] == 0
|
24
|
+
if ("0".."4").include?(v)
|
25
|
+
@solver.assert Z3::Ast.add(*lamps_next_to_cell(x,y)) == v.to_i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Every cell is in raycast of a lamp
|
31
|
+
# No lamp is in raycast of another lamp
|
32
|
+
(0...@ysize).each do |y|
|
33
|
+
(0...@xsize).each do |x|
|
34
|
+
raycast = Z3::Ast.add(*raycast_cells(x,y))
|
35
|
+
@solver.assert Z3::Ast.implies(@lamps[[x,y]] == 0, raycast >= 1)
|
36
|
+
@solver.assert Z3::Ast.implies(@lamps[[x,y]] == 1, raycast == 0)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
if @solver.check == :sat
|
41
|
+
@model = @solver.model
|
42
|
+
print_answer!
|
43
|
+
else
|
44
|
+
puts "failed to solve"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def lamps_next_to_cell(x0,y0)
|
51
|
+
[[x0-1,y0],[x0+1,y0],[x0,y0-1],[x0,y0+1]].map{|x,y| @lamps[[x,y]]}.compact
|
52
|
+
end
|
53
|
+
|
54
|
+
def raycast_cells(x0,y0)
|
55
|
+
result = []
|
56
|
+
[[1,0],[-1,0],[0,1],[0,-1]].each do |dx,dy|
|
57
|
+
x = x0+dx
|
58
|
+
y = y0+dy
|
59
|
+
while @data[[x,y]] == "."
|
60
|
+
result << @lamps[[x,y]]
|
61
|
+
x += dx
|
62
|
+
y += dy
|
63
|
+
end
|
64
|
+
end
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
def map_coordinates
|
69
|
+
Hash[(0...@xsize).to_a.product((0...@ysize).to_a).map{|x,y| [[x,y],yield(x,y)]}]
|
70
|
+
end
|
71
|
+
|
72
|
+
def print_answer!
|
73
|
+
(0...@ysize).each do |y|
|
74
|
+
(0...@xsize).each do |x|
|
75
|
+
if @data[[x,y]] != "."
|
76
|
+
print(@data[[x,y]])
|
77
|
+
elsif @model[@lamps[[x,y]]].to_s == "1"
|
78
|
+
print("*")
|
79
|
+
else
|
80
|
+
print(" ")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
puts "\n"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def int01(x,y)
|
88
|
+
v = Z3::Ast.int("l#{x},#{y}")
|
89
|
+
@solver.assert v >= 0
|
90
|
+
@solver.assert v <= 1
|
91
|
+
v
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
LightUp.new(
|
96
|
+
"""
|
97
|
+
....0..
|
98
|
+
.......
|
99
|
+
x.2.x..
|
100
|
+
...3...
|
101
|
+
..x.x.3
|
102
|
+
.......
|
103
|
+
..1....
|
104
|
+
"""
|
105
|
+
).solve!
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
class MiniSudokuSolver
|
6
|
+
def initialize(data)
|
7
|
+
@data = data
|
8
|
+
@solver = Z3::Solver.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def solve!
|
12
|
+
@cells = (0..5).map do |j|
|
13
|
+
(0..5).map do |i|
|
14
|
+
cell_var(@data[j][i], i, j)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
@cells.each do |row|
|
19
|
+
@solver.assert Z3::Ast.distinct(*row)
|
20
|
+
end
|
21
|
+
@cells.transpose.each do |column|
|
22
|
+
@solver.assert Z3::Ast.distinct(*column)
|
23
|
+
end
|
24
|
+
@cells.each_slice(2) do |rows|
|
25
|
+
rows.transpose.each_slice(3) do |square|
|
26
|
+
@solver.assert Z3::Ast.distinct(*square.flatten)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if @solver.check == :sat
|
31
|
+
@model = @solver.model
|
32
|
+
print_answer!
|
33
|
+
else
|
34
|
+
puts "failed to solve"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def cell_var(cell, i, j)
|
41
|
+
v = Z3::Ast.int("cell[#{i+1},#{j+1}]")
|
42
|
+
@solver.assert v >= 1
|
43
|
+
@solver.assert v <= 6
|
44
|
+
@solver.assert v == cell if cell != nil
|
45
|
+
v
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_answer!
|
49
|
+
@cells.each do |row|
|
50
|
+
puts row.map{|v| @model[v]}.join(" ")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
_ = nil
|
56
|
+
minisudoku = MiniSudokuSolver.new([
|
57
|
+
[_, _, _, 4, _, _],
|
58
|
+
[_, _, 4, 1, 2, _],
|
59
|
+
[_, _, 6, 5, 4, _],
|
60
|
+
[_, 5, 2, 3, _, _],
|
61
|
+
[_, 2, 3, 6, _, _],
|
62
|
+
[_, _, 1, _, _, _],
|
63
|
+
])
|
64
|
+
minisudoku.solve!
|