Advertisement
Guest User

Untitled

a guest
Feb 27th, 2015
330
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List
  2.  
  3. -- BEGIN DATA STRUCTURES --
  4.  
  5. --IMPORTANT: Attribute lists are assumed to be duplicate free
  6.  
  7. -- Attribute defintion
  8. data Attribute = Attribute Char deriving (Show,Eq, Ord)
  9.  
  10. -- A MVD (or the more special case of an FD)
  11. data MVD = FD [Attribute] [Attribute] | MVD [Attribute] [Attribute] deriving (Show,Eq)
  12.  
  13. -- A relation
  14. data Relation = Relation [Attribute] [MVD]  deriving (Show,Eq)
  15.  
  16. --Remove old MVD (if elem), add new
  17. replaceMvd :: Relation -> MVD -> MVD -> Relation
  18. replaceMvd (Relation attrs mvds) old new = (Relation attrs newMvds)
  19.   where newMvds = (filter (\x -> x /= old) mvds)++[new]
  20.  
  21. --Find out if a prticular FD is also a MVD  
  22. isFD :: MVD -> Bool
  23. isFD (FD _ _) = True
  24. isFD (MVD _ _) = False
  25.  
  26. -- END DATA STRUCTURES --
  27.  
  28. -- BEGIN COMPUTING CLOSURES --
  29.  
  30. -- Compute the closure (This is formulated as a fixpoint operation)
  31. closure :: [Attribute] -> Relation -> [Attribute]
  32. closure a r | sort (nub a) == sort nextRun = a
  33.         | otherwise = closure nextRun r
  34.   where nextRun = closureRun a r --No need to nub here, already done by the resultFunction
  35.  
  36. -- Do the next run of the closure algorithm (used to find out if we have a fixpoint)
  37. closureRun :: [Attribute] -> Relation -> [Attribute]
  38. closureRun a (Relation _ []) = a
  39. closureRun a (Relation as (mvd:mvds)) = closureRun (result a mvd) (Relation as mvds)
  40.  
  41. -- Get transitive attributes wrt to particular MVD (FD actually, MVDs are just handeled
  42. -- here for the sake of simplicity)
  43. result :: [Attribute] -> MVD -> [Attribute]
  44. result x (MVD _ _) = x
  45. result x (FD ls rs) | null (ls \\ x) = x `union` rs --If everything from ls is also in x we can merge
  46.             | otherwise = x
  47.  
  48. -- END COMPUTING CLOSURES --
  49.  
  50. -- BEGIN LEFT REDUTION --
  51.  
  52. leftReduce :: Relation -> Relation
  53. leftReduce (Relation attrs mvds) = leftReduceFDs (Relation attrs mvds) mvds
  54.  
  55. -- Left reduce all given MVDs, the second attribute is a list of mvds that are still to do
  56. leftReduceFDs :: Relation -> [MVD] -> Relation
  57. leftReduceFDs r [] = r
  58. leftReduceFDs r ((MVD _ _):mvds) = leftReduceFDs r mvds
  59. leftReduceFDs orgR ((FD ls rs):mvds) = leftReduceFDs (replaceMvd orgR orgFD (remLOneMVD orgR orgFD ls)) mvds
  60.   where orgFD = (FD ls rs)
  61.  
  62. --Removes all superfluos attributes on the left of one MVD
  63. remLOneMVD :: Relation -> MVD -> [Attribute] -> MVD
  64. remLOneMVD _ (MVD ls rs) _ = (MVD ls rs) -- MVDs need not be reduced
  65. remLOneMVD r (FD ls rs) [] = (FD ls rs)  -- base case
  66. remLOneMVD r (FD ls rs) (todo:todos) | isSuperfluosOnLeft r (FD ls rs) todo = remLOneMVD r (FD (delete todo ls) rs) todos --If current attribute is superfluos, remove it and recurse
  67.                      | otherwise = remLOneMVD r (FD ls rs) todos
  68.                      
  69. -- Checks if a given attribute is superfluos in a given FD
  70. isSuperfluosOnLeft :: Relation -> MVD -> Attribute -> Bool
  71. isSuperfluosOnLeft _ (MVD _ _) _ = False
  72. isSuperfluosOnLeft (Relation as mvds) (FD ls rs) a = a `elem` (closure attrsWithoutA (Relation as mvds))
  73.   where attrsWithoutA = delete a ls)
  74. -- END LEFT REDUCTION --
  75.  
  76. -- BEGIN RIGHT REDUTION --
  77.  
  78. rightReduce :: Relation -> Relation
  79. rightReduce (Relation attrs mvds) = rightReduceFDs (Relation attrs mvds) mvds
  80.  
  81. -- right reduce all given MVDs, the second attribute is a list of mvds that are still to do
  82. rightReduceFDs :: Relation -> [MVD] -> Relation
  83. rightReduceFDs r [] = r
  84. rightReduceFDs r ((MVD _ _):mvds) = rightReduceFDs r mvds
  85. rightReduceFDs orgR ((FD ls rs):mvds) =  rightReduceFDs (replaceMvd orgR orgFD (remROneMVD orgR orgFD rs)) mvds
  86.   where orgFD = (FD ls rs)
  87.  
  88. --Removes all superfluos attributes on the right of one MVD
  89. remROneMVD :: Relation -> MVD -> [Attribute] -> MVD
  90. remROneMVD _ (MVD ls rs) _ = (MVD ls rs) -- MVDs need not be reduced
  91. remROneMVD r (FD ls rs) [] = (FD ls rs)  -- base case
  92. remROneMVD r (FD ls rs) (todo:todos) | isSuperfluosOnRight r (FD ls rs) todo = remROneMVD r (FD  ls (delete todo rs)) todos --If current attribute i superfluos
  93.                      | otherwise = remROneMVD r (FD ls rs) todos
  94.                      
  95. -- Checks if a given attribute is superfluos in a given FD
  96. isSuperfluosOnRight :: Relation -> MVD -> Attribute -> Bool
  97. isSuperfluosOnRight _ (MVD _ _) _ = False
  98. isSuperfluosOnRight (Relation as mvds) (FD ls rs) a = a `elem` closure ls (replaceMvd (Relation as mvds) (FD ls rs) (FD ls rsWithoutA))
  99.   where rsWithoutA = delete a rs                     
  100. -- END RIGHT REDUCTION --
  101.  
  102. -- BEGIN CANONICAL COVER --
  103. canonicalCover :: Relation -> Relation
  104. canonicalCover r = mergeDuplicates $ remEmptyFD $ rightReduce $ leftReduce r
  105.  
  106. -- Remove FDs of the form X -> {}
  107. remEmptyFD :: Relation -> Relation
  108. remEmptyFD (Relation atts mvds) = (Relation atts (filter helper mvds))
  109.   where helper (FD rs []) = False
  110.     helper _ = True
  111.  
  112. -- Merge duplicate FDs of the form A->X A->Y into A -> X u Y
  113. mergeDuplicates :: Relation -> Relation
  114. mergeDuplicates (Relation as mvds) = (Relation as ((addAllToProperMVD (leftSides justFDs) justFDs)++justMVDs))
  115.   where justFDs = filter isFD mvds
  116.     justMVDs = filter (not.isFD) mvds
  117.  
  118. -- add all right sides of the given FDs to the proper FD in mvd (obtained e.g. from leftSides)
  119. addAllToProperMVD :: [MVD] -> [MVD] ->[MVD]
  120. addAllToProperMVD mvds (todo:todos) = addAllToProperMVD (addToProperMVD mvds todo) todos
  121. addAllToProperMVD mvds [] = mvds
  122.  
  123. --add right side of a given FD to the correct FD in the list (e.g. obtained from leftSides)
  124. addToProperMVD :: [MVD] -> MVD -> [MVD]
  125. addToProperMVD ((FD ls rs):mvds) (FD ls' rs') | sort ls == sort ls' = (FD ls (nub rs++rs')):mvds
  126.                           | otherwise = (FD ls rs):(addToProperMVD mvds (FD ls' rs'))
  127.  
  128. --Create FDs of the form A -> {} for each individual A
  129. leftSides :: [MVD] ->  [MVD]
  130. leftSides mvds = map (\ls -> FD ls []) (nub $ map (\(FD ls rs) -> sort ls) mvds)
  131. -- END CANONICAL COVER --
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement