This repository has been archived by the owner on Apr 30, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFODBR.hs
146 lines (113 loc) · 4.42 KB
/
FODBR.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
module FODBR where
import Data.List (foldl',sort,(\\))
type FODBR a b = (BMT a b, BMT b a)
build :: (Ord a, Ord b) => [(a,b)] -> FODBR a b
build list = (l, r) where
l = construct . compact . sort $ list
r = construct . compact . sort . map swap $ list
buildC :: (Ord a, Ord b) => [(a,[b])] -> FODBR a b
buildC clist = (l, r) where
l = construct clist
r = construct . compact . sort . map swap . tolist $ l
union :: (Ord a, Ord b) => FODBR a b -> FODBR a b -> FODBR a b
union (lt,rt) (lt',rt') = (lt'',rt'') where
lt'' = trunion lt lt'
rt'' = trunion rt rt'
compose :: (Ord a, Ord b, Ord c) => FODBR a b -> FODBR b c -> FODBR a c
compose (lt,rt) (lt',rt') = (lt'',rt'') where
lt'' = trcomp lt lt'
rt'' = trcomp rt' rt
invert :: (Ord a, Ord b) => FODBR a b -> FODBR b a
invert = swap
minus :: (Ord a, Ord b) => FODBR a b -> FODBR a b -> FODBR a b
minus (lt,rt) (lt', rt') = (lt'',rt'') where
lt'' = trminus lt lt'
rt'' = trminus rt rt'
restrict :: (Ord a, Ord b) => FODBR a b -> (a -> b -> Bool) -> FODBR a b
restrict (l, r) f = (l',r') where
l' = trestrict l f
r' = trestrict r (flip f)
trans :: (Ord a) => FODBR a a -> FODBR a a
trans (l,r) = buildC $ map (\x -> (x, allsucc l x)) (keys l)
allsucc :: (Ord a) => BMT a a -> a -> [a]
allsucc tree x = fix (\xs -> xs `nubunion` find tree xs) (find1 tree x)
fix :: (Eq a) => (a -> a) -> a -> a
fix f x
| f x == x = x
| otherwise = fix f (f x)
swap :: (a, b) -> (b, a)
swap (x, y) = (y, x)
data BMT a b =
Empty
| Branch !(a,[b]) !(BMT a b) !(BMT a b)
deriving (Eq)
construct :: (Ord a, Ord b) => [(a,[b])] -> BMT a b
construct [] = Empty
construct list = construct' (length list) list where
construct' n list | n == 0 = Empty
| n > 0 = Branch p (construct' ll l) (construct' lr r)
where
ll = n `div` 2
lr = ((n+1) `div` 2) - 1
(l,p:r) = splitAt ll list
compact :: (Ord a, Ord b) => [(a,b)] -> [(a,[b])]
compact [] = []
compact l@((x,y):r) = (x, ys):compact ri
where
ys = map snd le
(le, ri) = break ((x /=).fst) l
tolist :: (Ord a, Ord b) => BMT a b -> [(a,b)]
tolist tree = concatMap (\x -> (map (\y -> (x,y)) (find1 tree x))) $ keys tree
find1 :: (Ord a, Ord b) => BMT a b -> a -> [b]
find1 Empty _ = []
find1 (Branch (k,vs) lst rst) x
| x == k = vs
| x < k = find1 lst x
| x > k = find1 rst x
find :: (Ord a, Ord b) => BMT a b -> [a] -> [b]
find tree xs = snub . sort . concatMap (find1 tree) $ xs
fall :: (Ord a, Ord b) => BMT a b -> [a] -> [b]
fall _ [] = []
fall tree (x:xs) = foldl' nubisect (find1 tree x) $ map (find1 tree) xs
trunion :: (Ord a, Ord b) => BMT a b -> BMT a b -> BMT a b
trunion one another = construct base where
base = map (\key -> (key, nubunion (find1 one key) (find1 another key))) $ keys one
trcomp :: (Ord a, Ord b, Ord c) => BMT a b -> BMT b c -> BMT a c
trcomp one another = construct base where
base = map (\key -> (key, find another (find1 one key))) (keys one)
trminus :: (Ord a, Ord b) => BMT a b -> BMT a b -> BMT a b
trminus one another = construct base where
base = map (\key -> (key, find1 one key `nubminus` find1 another key)) (keys one)
trestrict :: (Ord a, Ord b) => BMT a b -> (a -> b -> Bool) -> BMT a b
trestrict Empty _ = Empty
trestrict (Branch (k, vs) l r) f = Branch (k, filter (f k) vs) (trestrict l f) (trestrict r f)
nubunion :: (Ord a) => [a] -> [a] -> [a]
nubunion xs ys = snub (sort xs) ++ ys
nubisect :: (Ord a) => [a] -> [a] -> [a]
nubisect [] _ = []
nubisect _ [] = []
nubisect (x:r) (x':r')
| x == x' = x:nubisect r r'
| x < x' = nubisect r (x':r')
| x > x' = nubisect (x:r) r'
nubminus :: (Ord a) => [a] -> [a] -> [a]
nubminus [] _ = []
nubminus x [] = x
nubminus (x:r) (x':r')
| x == x' = nubminus r r'
| x < x' = x : nubminus r (x':r')
| x > x' = nubminus (x:r) r'
snub :: (Ord a) => [a] -> [a]
snub [] = []
snub (x:r) = x:snub r'
where
r' = dropWhile (x ==) r
suchThat :: (Ord a, Ord b) => BMT a b -> (a -> [b] -> Bool) -> [(a,[b])]
suchThat Empty _ = []
suchThat (Branch (k,vs) l r) f = suchThat l f ++ if f k vs then [(k,vs)] else [] ++ suchThat r f
getStat :: (Ord a, Ord b) => BMT a b -> (a -> [b] -> c) -> (c -> c -> c -> c) -> c -> c
getStat Empty _ _ h = h
getStat (Branch (k,vs) lst rst) f combine h = combine (f k vs) (getStat lst f combine h) (getStat rst f combine h)
keys :: (Ord a, Ord b) => BMT a b -> [a]
keys Empty = []
keys (Branch (k,_) lst rst) = keys lst ++ [k] ++ keys rst