-
Notifications
You must be signed in to change notification settings - Fork 0
/
MealyMachines.jl
117 lines (90 loc) · 2.35 KB
/
MealyMachines.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
module MealyMachines
export expressions, to_strings
using Base.Iterators: drop, cycle, partition, flatten
using LogicalFunctions, Minimization
using Visualization: formula
TransitionTable = Dict{Vector{Int}, Vector{Int}}
function automaton_transition(pattern::BitVector)::TransitionTable
n = length(pattern)
codes =
n |>
log |>
ceil |>
Int |>
gray_code
encode(state::Int, bit::Bool)::BitVector =
vcat(codes[state], [bit])
basic_transitions = [
encode(state, bit) => encode(next_state, false)
for (state, bit, next_state) in zip(1:n-1, pattern, 2:n)
]
push!(basic_transitions, encode(n, pattern[end]) => encode(1, true))
max_prefix(patt::BitVector, i::Int)::Int =
maximum(
length,
[patt[1:j] for j in 1:i if patt[1:j] == patt[1:n-j-1]],
init = 1
)
extended_patterns = [[pattern; true], [pattern; false]]
prefix_transitions = [
encode(i, ext[end]) => encode(max_prefix(ext, i), false)
for ext in extended_patterns
for i in 1:n
]
return merge(
Dict(prefix_transitions),
Dict(basic_transitions)
)
end
function split_columns(table::TransitionTable)::Dict{Int, TruthTable}
n_vars =
table |>
keys |>
first .|>
length |>
sum
Dict([
var => Dict([
entry.first => entry.second[var]
for entry in table
])
for var in 1:n_vars
])
end
function expressions(pattern::BitVector)::Dict{Int, DNF}
cols = pattern |>
automaton_transition |>
split_columns
Dict([
bit.first => minimize(bit.second)
for bit in cols
])
end
function to_strings(exprs::Dict{Int, DNF})::Vector{String}
n_funs = exprs |>
keys |>
length
n_vars = exprs |>
values |>
flatten .|>
collect |>
flatten |>
collect .|>
abs |>
maximum
state_names = Dict(i => "x$i" for i in 1:n_funs-1)
fun_names = merge(
state_names,
Dict(n_funs => "out")
)
var_names = merge(
state_names,
Dict(n_vars => "in")
)
formula.(
get.([exprs], 1:n_funs, nothing),
get.([fun_names], 1:n_funs, "?"),
[var_names]
)
end
end# module