-
Notifications
You must be signed in to change notification settings - Fork 0
/
Minimization.jl
89 lines (65 loc) · 1.96 KB
/
Minimization.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
module Minimization
export minimize
using LogicalFunctions
using Base.Iterators: filter as lazy_filter
function group(table::Set{<:PartialBitVector})::Tuple{Set{Tuple{PartialBitVector, PartialBitVector}}, Set{PartialBitVector}}
matched = Set()
processed = Dict(table .=> false)
for vec in lazy_filter(v -> v in table, collect(table))
for neighbour in lazy_filter(neigh -> neigh in table, neighbours(vec))
if (neighbour, vec) ∉ matched
push!(matched, (vec, neighbour))
processed[vec] = true
processed[neighbour] = true
end
end
end
non_matched = filter(entry -> !entry.second, processed) |>
keys |>
Set
return matched, non_matched
end
function combine((vec1, vec2)::Tuple{<:PartialBitVector, <:PartialBitVector})::PartialBitVector
ret = Vector{Union{Bool, Missing}}(copy(vec1))
diff = (vec1 .!== vec2) |>
skipmissing |>
argmax
ret[diff] = missing
ret
end
function reduce_terms(table::Set{<:PartialBitVector})::Set{PartialBitVector}
prime = Set()
matched = [1]
while length(matched) > 0
matched, non_matched = group(table)
union!(prime, non_matched)
table = Set(combine.(matched))
end
prime
end
function to_dnf(minterms::Set{PartialBitVector})::Vector{Vector{Int}}
skipmissing_values(vec::Vector{<:Union{Tuple{Int, Bool}, Tuple{Int, Missing}}})::Vector{Tuple{Int, Any}} =
filter(
(idx, val)::Tuple -> !ismissing(val),
vec
)
literal((idx, val)::Tuple{Int, Bool})::Int = val ? idx : -idx
clean_minterms =
minterms .|>
enumerate .|>
collect .|>
skipmissing_values
map.(
literal,
clean_minterms
)
end
function minimize(table::TruthTable)::Vector{Vector{Int}}
table |>
positive |>
keys |>
Set |>
reduce_terms |>
to_dnf
end
end# module