------------------------------------------------------------------------- -- -- Relation.hs -- -- Building Relations and Graphs on top of the Set ADT. -- -- (c) Addison-Welsey, 1996-2011. -- --------------------------------------------------------------------------- module Relation where import Set import Data.List hiding ( union ) -- -- A relation is a set of pairs. type Relation a = Set (a,a) -- -- Operations over relations. -- ^^^^^^^^^^^^^^^^^^^^^^^^^^ -- -- The image of an element under a relation. image :: Ord a => Relation a -> a -> Set a image rel val = mapSet snd (filterSet ((==val).fst) rel) -- -- The image of a set of elements under a relation. -- setImage :: Ord a => Relation a -> Set a -> Set a setImage rel = unionSet . mapSet (image rel) -- The union of a set of sets. -- unionSet :: Ord a => Set (Set a) -> Set a unionSet = foldSet union empty -- -- Add to a set its image under a relation. addImage :: Ord a => Relation a -> Set a -> Set a addImage rel st = st `union` setImage rel st -- -- Add the children (under the relation isParent) to a set. -- type People = String isParent :: Relation People isParent = isParent -- dummy definition -- needs to be replaced addChildren :: Set People -> Set People addChildren = addImage isParent -- -- Compose two relations. -- compose :: Ord a => Relation a -> Relation a -> Relation a compose rel1 rel2 = mapSet outer (filterSet equals (setProduct rel1 rel2)) where equals ((a,b),(c,d)) = (b==c) outer ((a,b),(c,d)) = (a,d) -- The product of two sets. -- setProduct :: (Ord a,Ord b) => Set a -> Set b -> Set (a,b) setProduct st1 st2 = unionSet (mapSet (adjoin st1) st2) -- -- Add an element to each element of a set, forming a set of pairs. -- adjoin :: (Ord a,Ord b) => Set a -> b -> Set (a,b) adjoin st el = mapSet (addEl el) st where addEl el el' = (el',el) -- -- The transitive closure of a relation. tClosure :: Ord a => Relation a -> Relation a tClosure rel = limit addGen rel where addGen rel' = rel' `union` compose rel' rel -- Finding a limit of a function. limit :: Eq a => (a -> a) -> a -> a limit f xs | xs == next = xs | otherwise = limit f next where next = f xs -- Graphs -- ^^^^^^ -- -- The connected components of a graph. connect :: Ord a => Relation a -> Relation a connect rel = clos `inter` solc where clos = tClosure rel solc = inverse clos -- -- The inverse of a relation swap all pairs. inverse :: Ord a => Relation a -> Relation a inverse = mapSet swap where swap (x,y) = (y,x) -- -- The equivalence classes of a(n equivalence) relation. -- classes :: Ord a => Relation a -> Set (Set a) classes rel = limit (addImages rel) start where start = mapSet sing (eles rel) -- The auxiliary functions used in classes. -- eles :: Ord a => Relation a -> Set a eles rel = mapSet fst rel `union` mapSet snd rel addImages :: Ord a => Relation a -> Set (Set a) -> Set (Set a) addImages rel = mapSet (addImage rel) -- Searching in graphs -- ^^^^^^^^^^^^^^^^^^^ -- -- The descendants v under rel which lie outside st. -- newDescs :: Ord a => Relation a -> Set a -> a -> Set a newDescs rel st v = image rel v `diff` st -- -- Breaking the abstraction barrier for sets. -- defined in Sets.hs -- flatten :: Ord a => Set a -> [a] -- Under the list implementation, we can use -- flatten = id -- -- A list of new descendants. -- findDescs :: Ord a => Relation a -> [a] -> a -> [a] findDescs rel xs v = flatten (newDescs rel (makeSet xs) v) -- -- Breadth first search. -- ^^^^^^^^^^^^^^^^^^^^^ breadthFirst :: Ord a => Relation a -> a -> [a] breadthFirst rel val = limit step start where start = [val] step xs = xs ++ nub (concat (map (findDescs rel xs) xs)) -- -- Depth first search. -- ^^^^^^^^^^^^^^^^^^^^^ depthFirst :: Ord a => Relation a -> a -> [a] depthSearch :: Ord a => Relation a -> a -> [a] -> [a] depthFirst rel v = depthSearch rel v [] depthSearch rel v used = v : depthList rel (findDescs rel used' v) used' where used' = v:used depthList :: Ord a => Relation a -> [a] -> [a] -> [a] depthList rel [] used = [] depthList rel (val:rest) used = next ++ depthList rel rest (used++next) where next | elem val used = [] | otherwise = depthSearch rel val used -- -- From the exercises... -- -- distance :: Eq a => Relation a -> a -> a -> Int