-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKleeneAlgebra.hs
105 lines (98 loc) · 2.67 KB
/
KleeneAlgebra.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
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
{-# LANGUAGE TupleSections #-}
module KleeneAlgebra where
import Data.Bifunctor (first)
import qualified Data.Set as S
import GraphUtils
import Regexp
data Axiom
= A1
| A1'
| A2
| A3
| A4
| A5
| A5'
| A6
| A6'
| A7
| A7'
| A8
| A8'
| A9
| A9'
| A10
| A10'
| A11
| A11'
deriving (Bounded, Enum, Eq, Ord, Show)
rewrite :: Regexp -> S.Set (Regexp, Axiom)
rewrite r =
S.unions
[ S.fromList $ map (,a) (apply a r) | a <- [minBound .. maxBound]
]
rewriteRec :: Regexp -> S.Set (Regexp, Axiom)
rewriteRec r = case r of
Empty -> rewrite r
Single _ -> rewrite r
SingleEmpty -> rewrite r
Star x -> rewrite r `S.union` mapFst Star (rewriteRec x)
Union x y ->
rewrite r
`S.union` mapFst (`Union` y) (rewriteRec x)
`S.union` mapFst (x `Union`) (rewriteRec y)
Concat x y ->
rewrite r
`S.union` mapFst (`Concat` y) (rewriteRec x)
`S.union` mapFst (x `Concat`) (rewriteRec y)
where
mapFst f = S.map (first f)
apply :: Axiom -> Regexp -> [Regexp]
apply A1 (a `Union` (b `Union` c)) =
return $ (a `Union` b) `Union` c
apply A1' ((a `Union` b) `Union` c) =
return $ a `Union` (b `Union` c)
apply A2 (a `Union` b) =
return $ b `Union` a
apply A3 (a `Union` a')
| a == a' = return a
apply A4 (a `Union` Empty) =
return a
apply A5 (a `Concat` (b `Concat` c)) =
return $ (a `Concat` b) `Concat` c
apply A5' ((a `Concat` b) `Concat` c) =
return $ a `Concat` (b `Concat` c)
apply A6 (a `Concat` SingleEmpty) =
return a
apply A6' (SingleEmpty `Concat` a) =
return a
apply A7 (a `Concat` Empty) =
return Empty
apply A7' (Empty `Concat` a) =
return Empty
apply A8 (a `Concat` (b `Union` c)) =
return $ (a `Concat` b) `Union` (a `Concat` c)
apply A8' ((a `Concat` b) `Union` (a' `Concat` c))
| a == a' = return $ a `Concat` (b `Union` c)
apply A9 ((a `Union` b) `Concat` c) =
return $ (a `Concat` c) `Union` (b `Concat` c)
apply A9' ((a `Concat` c) `Union` (b `Concat` c'))
| c == c' = return $ (a `Union` b) `Concat` c
apply A10 (SingleEmpty `Union` (a `Concat` Star a'))
| a == a' = return $ Star a
apply A10' (Star a) =
return $ SingleEmpty `Union` (a `Concat` Star a)
apply A11 (a `Concat` Star a')
| a == a' = return $ Star a `Concat` a
apply A11' (Star a `Concat` a')
| a == a' = return $ a `Concat` Star a
apply _ _ = []
simplify :: Int -> Regexp -> [S.Set (Regexp, [Axiom])]
simplify n r = simplify' [S.singleton (r, [])]
where
simplify' plys
| length plys > n = plys
| otherwise =
let ply' = nextPly rewriteRec (last plys) plys
c0 = complexity r
reasonable r' = complexity r' <= 100 * c0
in simplify' $ plys ++ [S.filter (reasonable . fst) ply']