-
Notifications
You must be signed in to change notification settings - Fork 0
/
Minimiser.hs
80 lines (71 loc) · 2.6 KB
/
Minimiser.hs
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
import TTableGenerator
import Parser
import Evaluator
import Data.List
fromDisjuncts :: [ASTNode] -> ASTNode
fromDisjuncts []
= ASTBottom
fromDisjuncts [n]
= n
fromDisjuncts ns
= foldr1 ASTOr ns
fromConjuncts :: [ASTNode] -> ASTNode
fromConjuncts []
= ASTTop
fromConjuncts [n]
= n
fromConjuncts ns
= foldr1 ASTAnd ns
intToBin :: Int -> [Int]
intToBin n
| n < 2 = [n]
| otherwise = (n `mod` 2) : intToBin (n `div` 2)
binZerosAt :: Int -> Int -> [Int]
binZerosAt d n
= [p | (d, p) <- zip extBinDigits (iterate (2*) 1), d == 0]
where
binDigits = intToBin n
extBinDigits = binDigits ++ replicate (d - length binDigits) 0
getMerges :: [[Int]] -> Int -> [Int] -> [[Int]]
getMerges candidates d ms@(m : _)
= [ms ++ c | c <- lookingFor, c `elem` candidates]
where
minAdd = last ms - m + 1
toAdd = filter (>= minAdd) $ binZerosAt d m
lookingFor = [map (a +) ms | a <- toAdd]
findPrimeImplicants :: [[Int]] -> Int -> [[Int]]
findPrimeImplicants candidates d
| candidates == newCandidates = newCandidates
| otherwise = findPrimeImplicants newCandidates d
where
merges = concatMap (getMerges candidates d) candidates
newCandidates = merges ++ filter (any (`notElem` concat merges)) candidates
findEssentialPrimes :: [Int] -> [[Int]] -> [[Int]]
findEssentialPrimes minterms primes
| null minterms' = singleOccs
| otherwise = p : singleOccs ++ findEssentialPrimes newMinterms ps
where
occs = map (\m -> filter (m `elem`) primes) minterms
singleOccs = unique $ map (\[x] -> x) $ filter ((1 ==) . length) occs
minterms' = filter (`notElem` concat singleOccs) minterms
primes' = filter (`notElem` singleOccs) primes
(p : ps) = sortOn (\p -> -(length $ filter (`elem` p) minterms')) primes'
newMinterms = filter (`notElem` p) minterms'
primeToNode :: TTable -> [Int] -> ASTNode
primeToNode ttable prime
= fromConjuncts nodes
where
combinations = [m | ((m, _), i) <- zip ttable [0..], i `elem` prime]
allConjuncts = unique $ concat combinations
common = filter (\c -> all (c `elem`) combinations) allConjuncts
nodes = map (\(c, v) -> if v then ASTVar c else ASTNot (ASTVar c)) common
minimise :: ASTNode -> ASTNode
minimise node
= fromDisjuncts disjuncts
where
ttable = generateTTable node
minterms = [i | ((_, v), i) <- zip ttable [0..], v == ExtTrue]
primeImplicants = findPrimeImplicants (map (: []) minterms) (length ttable)
sortedPrimes = sortOn (\ms -> -(length ms)) primeImplicants
essentialPrimes = findEssentialPrimes minterms sortedPrimes
disjuncts = map (primeToNode ttable) essentialPrimes