z3 0.0.20160323 → 0.0.20160330
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/knights_puzzle_solver +122 -0
- data/lib/z3/interface.rb +6 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b616eadc04d3acebed002b5e30969543ec87288
|
4
|
+
data.tar.gz: 51b12ceac3ca413e11d445c21524aa709e0d0c86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 755c4a975d120202b93efe203d3eeea53dc7898a0a15b8008c287bc7821c773f5e88a73680dd32eb4acfcd55208659c55591ee9151a06056884e2760101492a3
|
7
|
+
data.tar.gz: 5bc45fa1e31598830ce699b55cccbfac82ed9f83b72d9700fd454ecc2d05f68800bad0d2f8c2dc9f6485163b1ada994cfdd233323a52e49af1f142fa8107673e
|
@@ -0,0 +1,122 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/z3"
|
4
|
+
|
5
|
+
class KnightsPuzzle
|
6
|
+
def initialize
|
7
|
+
@x_size = 4
|
8
|
+
@y_size = 4
|
9
|
+
@num_moves = 12
|
10
|
+
@solver = Z3::Solver.new
|
11
|
+
@boards = (@num_moves+1).times.map{|t| board(t) }
|
12
|
+
@moves = @num_moves.times.map{|t| move(t)}
|
13
|
+
setup_board @boards[0], """
|
14
|
+
bbb.
|
15
|
+
xb.w
|
16
|
+
..ww
|
17
|
+
x.xw
|
18
|
+
"""
|
19
|
+
setup_board @boards[-1], """
|
20
|
+
www.
|
21
|
+
xw.b
|
22
|
+
..bb
|
23
|
+
x.xb
|
24
|
+
"""
|
25
|
+
@num_moves.times do |t|
|
26
|
+
setup_board_move @boards[t], @boards[t+1], @moves[t]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def print_board(t)
|
31
|
+
puts "State #{t}:"
|
32
|
+
puts @boards[t].transpose.map{|row| row.map{|c| ".wbx"[@model[c].to_i]}.join }.join("\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def print_move(t)
|
36
|
+
move = Hash[@moves[t].map{|k,v| [k,@model[v].to_i]}]
|
37
|
+
figure = " wbx"[move[:figure]]
|
38
|
+
puts "#{figure}: #{move[:start_x]},#{move[:start_y]} -> #{move[:end_x]},#{move[:end_y]}"
|
39
|
+
puts ""
|
40
|
+
end
|
41
|
+
|
42
|
+
def solve!
|
43
|
+
if @solver.check == :sat
|
44
|
+
@model = @solver.model
|
45
|
+
puts "Solved"
|
46
|
+
@num_moves.times do |t|
|
47
|
+
print_board(t)
|
48
|
+
print_move(t)
|
49
|
+
end
|
50
|
+
print_board(@num_moves)
|
51
|
+
else
|
52
|
+
puts "Puzzle can't be solved"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def setup_board_move(board_start, board_end, move)
|
59
|
+
@x_size.times.map do |x|
|
60
|
+
@y_size.times.map do |y|
|
61
|
+
# If not part of the move, stays the same
|
62
|
+
starts_here = (move[:start_x] == x) & (move[:start_y] == y)
|
63
|
+
ends_here = (move[:end_x] == x) & (move[:end_y] == y)
|
64
|
+
@solver.assert Z3::Implies(~starts_here & ~ends_here, board_start[x][y] == board_end[x][y])
|
65
|
+
# Every move starts with figure, ends on empty space
|
66
|
+
@solver.assert Z3::Implies(starts_here, board_start[x][y] == move[:figure])
|
67
|
+
@solver.assert Z3::Implies(starts_here, board_end[x][y] == 0)
|
68
|
+
@solver.assert Z3::Implies(ends_here, board_start[x][y] == 0)
|
69
|
+
@solver.assert Z3::Implies(ends_here, board_end[x][y] == move[:figure])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def board(t)
|
75
|
+
@x_size.times.map do |x|
|
76
|
+
@y_size.times.map do |y|
|
77
|
+
v = Z3::Int("b[#{t},#{x},#{y}]")
|
78
|
+
@solver.assert v >= 0
|
79
|
+
@solver.assert v <= 3
|
80
|
+
v
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def setup_board(vars, str)
|
86
|
+
str = str.split.map(&:chomp)
|
87
|
+
4.times do |x|
|
88
|
+
4.times do |y|
|
89
|
+
c = str[y][x]
|
90
|
+
i = ".wbx".index(c) or raise "Unknown character #{c}"
|
91
|
+
@solver.assert vars[x][y] == i
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def abs(t)
|
97
|
+
Z3::IfThenElse(t >= 0, t, -t)
|
98
|
+
end
|
99
|
+
|
100
|
+
def move(t)
|
101
|
+
move_start_x = Z3::Int("move_start_x_#{t}")
|
102
|
+
move_start_y = Z3::Int("move_start_y_#{t}")
|
103
|
+
move_end_x = Z3::Int("move_end_x_#{t}")
|
104
|
+
move_end_y = Z3::Int("move_end_y_#{t}")
|
105
|
+
figure = Z3::Int("move_figure_#{t}")
|
106
|
+
@solver.assert (figure >= 1) & (figure <= 2)
|
107
|
+
@solver.assert (move_start_x >= 0) & (move_start_x < @x_size)
|
108
|
+
@solver.assert (move_start_y >= 0) & (move_start_y < @y_size)
|
109
|
+
@solver.assert (move_end_x >= 0) & (move_end_x < @x_size)
|
110
|
+
@solver.assert (move_end_y >= 0) & (move_end_y < @y_size)
|
111
|
+
|
112
|
+
# 8 possible moves
|
113
|
+
@solver.assert (
|
114
|
+
((abs(move_start_x - move_end_x) == 2) & (abs(move_start_y - move_end_y) == 1)) |
|
115
|
+
((abs(move_start_x - move_end_x) == 1) & (abs(move_start_y - move_end_y) == 2))
|
116
|
+
)
|
117
|
+
|
118
|
+
{start_x: move_start_x, start_y: move_start_y, end_x: move_end_x, end_y: move_end_y, figure: figure}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
KnightsPuzzle.new.solve!
|
data/lib/z3/interface.rb
CHANGED
@@ -75,6 +75,12 @@ module Z3
|
|
75
75
|
BoolSort.new.new(Z3::LowLevel.mk_iff(a, b))
|
76
76
|
end
|
77
77
|
|
78
|
+
def IfThenElse(a, b, c)
|
79
|
+
a, = coerce_to_same_bool_sort(a)
|
80
|
+
b, c = coerce_to_same_sort(b, c)
|
81
|
+
b.sort.new(Z3::LowLevel.mk_ite(a, b, c))
|
82
|
+
end
|
83
|
+
|
78
84
|
def Add(*args)
|
79
85
|
raise ArgumentError if args.empty?
|
80
86
|
args = coerce_to_same_sort(*args)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: z3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.20160330
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomasz Wegrzanowski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -41,6 +41,7 @@ files:
|
|
41
41
|
- examples/geometry_problem
|
42
42
|
- examples/kakuro_solver
|
43
43
|
- examples/kinematics_problems
|
44
|
+
- examples/knights_puzzle_solver
|
44
45
|
- examples/letter_connections_solver
|
45
46
|
- examples/light_up_solver
|
46
47
|
- examples/minisudoku_solver
|