Relation.lhs Building Relations and Graphs on top of the Set ADT. (c) Simon Thompson, 1995, 1998. > module Relation where > import Set > import 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. > flatten :: Set a -> [a] > flatten = flatten -- dummy definition 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