2N/ADescription : Relations, based on maps
2N/ACopyright : (c) Uni Bremen 2003-2005
2N/AMaintainer : Christian.Maeder@dfki.de
2N/AStability : provisional
2N/APortability : portable
2N/Asupply a simple data type for (precedence or subsort) relations. A
2N/Arelation is conceptually a set of (ordered) pairs,
2N/Abut the hidden implementation is based on a map of sets.
2N/AAn alternative view is that of a directed Graph
2N/Awithout isolated nodes.
2N/A'Rel' is a directed graph with elements (Ord a) as (uniquely labelled) nodes
2N/Aand (unlabelled) edges (with a multiplicity of at most one).
2N/AUsage: start with an 'empty' relation, 'insert' edges, and test for
2N/Aan edge 'member' (before or after calling 'transClosure').
2N/AIt is possible to insert self edges or bigger cycles.
2N/AChecking for a 'path' corresponds to checking for a member in the
2N/Atransitive (possibly non-reflexive) closure. A further 'insert', however,
2N/Amay destroy the closedness property of a relation.
2N/AThe functions 'image', and 'setInsert' are utility functions
2N/Afor plain maps involving sets.
2N/A , succs, predecessors, irreflex, sccOfClosure
2N/A , transClosure, fromList, toList, image, toPrecMap
2N/A , intransKernel, mostRight, restrict, delSet
2N/A , toSet, fromSet, topSort, nodes, collaps
2N/A , transpose, transReduce, setInsert, setToMap
2N/A , flatSet, partSet, partList, leqClasses
2N/Aimport Prelude hiding (map, null)
-- | is the first relation a sub-relation of the second
isSubrelOf :: Ord a => Rel a -> Rel a -> Bool
-- | get direct successors
succs :: Ord a => Rel a -> a ->
Set.Set a
-- | get all transitive successors
reachable :: Ord a => Rel a -> a ->
Set.Set a
-- | predecessors of one node in the given set of a nodes
-- | get direct predecessors inefficiently
predecessors :: Ord a => Rel a -> a ->
Set.Set a
-- | test for 'member' or transitive membership (non-empty path)
path :: Ord a => a -> a -> Rel a -> Bool
-- | compute transitive closure (make all transitive members direct members)
transClosure :: Ord a => Rel a -> Rel a
-- | get reverse relation
transpose :: Ord a => Rel a -> Rel a
transpose = fromList .
List.map ( \ (a, b) -> (b, a)) . toList
-- | make relation irreflexive
irreflex :: Ord a => Rel a -> Rel a
-- | compute strongly connected components for a transitively closed relation
let c = preds m k v in -- get the cycle
-- | compute strongly connected components for a transitively closed relation
sccOfClosure :: Ord a => Rel a -> [
Set.Set a]
-- | restrict to elements not in the input set
-- | restrict to elements not in the input set
delSet :: Ord a =>
Set.Set a -> Rel a -> Rel a
{- | restrict strongly connected components to its minimal representative
(input sets must be non-null). Direct cycles may remain. -}
collaps :: Ord a => [
Set.Set a] -> Rel a -> Rel a
{- | transitive reduction (minimal relation with the same transitive closure)
of a transitively closed DAG (
i.e. without cycles)! -}
transReduce :: Ord a => Rel a -> Rel a
-- keep all (i, j) in rel for which no c with (i, c) and (c, j) in rel
-- | convert a list of ordered pairs to a relation
fromList :: Ord a => [(a, a)] -> Rel a
-- | convert a relation to a list of ordered pairs
toList :: Rel a -> [(a, a)]
toList = concatMap (\ (a, bs) ->
List.map (\ b -> (a, b)) bs)
-- | Insert into a set of values
-- | map the values of a relation
map :: (Ord a, Ord b) => (a -> b) -> Rel a -> Rel b
-- | Restriction of a relation under a set
restrict :: Ord a => Rel a ->
Set.Set a -> Rel a
restrict r s = delSet (nodes r Set.\\ s) r
-- | convert a relation to a set of ordered pairs
toSet :: (Ord a) => Rel a ->
Set.Set (a, a)
-- | convert a set of ordered pairs to a relation
fromSet :: (Ord a) =>
Set.Set (a, a) -> Rel a
-- | convert a sorted list of ordered pairs to a relation
fromAscList :: (Ord a) => [(a, a)] -> Rel a
-- | all nodes of the edges
nodes :: Ord a => Rel a ->
Set.Set a
topSortDAGM m = if
Map.null m then [] else
topSortDAG :: Ord a => Rel a -> [
Set.Set a]
-- | topologically sort a closed relation (ignore isolated cycles)
topSort :: Ord a => Rel a -> [
Set.Set a]
topSort r = let cs = sccOfClosure r in
List.map (expandCycle cs) $ topSortDAG $ irreflex $ collaps cs r
{- | Construct a precedence map from a closed relation. Indices range
between 1 and the second value that is output. -}
toPrecMap :: Ord a => Rel a -> (
Map.Map a Int, Int)
toPrecMap = foldl ( \ (m1, c) s -> let n = c + 1 in
-- | find the cycle and add it to the result set
expandCycle cs s = case cs of
{- | gets the most right elements of the irreflexive relation,
unless no hierarchy is left then isolated nodes are output -}
mostRightOfCollapsed :: Ord a => Rel a ->
Set.Set a
find s such that x in s => forall y . yRx or not yRx and not xRy
* precondition: (transClosure r == r)
* strongly connected components (cycles) are treated as a compound node
mostRight :: Ord a => Rel a ->
Set.Set a
in expandCycle cs (mostRightOfCollapsed $ collaps cs r)
intransitive kernel of a reflexive and transitive closure
* precondition: (transClosure r == r)
* cycles are uniquely represented (according to Ord)
intransKernel :: Ord a => Rel a -> Rel a
in foldr addCycle (transReduce $ collaps cs r) cs
-- | add a cycle given by a set in the collapsed node
addCycle :: Ord a =>
Set.Set a -> Rel a -> Rel a
{- | calculates if two given elements have a common left element
* if one of the arguments is not present False is returned
haveCommonLeftElem :: Ord a => a -> a -> Rel a -> Bool
haveCommonLeftElem t1 t2 =
{- | partitions a set into a list of disjoint non-empty subsets
determined by the given function as equivalence classes -}
{- | partitions a list into a list of disjoint non-empty lists
determined by the given function as equivalence classes -}
partList :: (a -> a -> Bool) -> [a] -> [[a]]
-- | Divide a Set (List) into equivalence classes
w.r.t. eq
leqClasses :: Ord a => (a -> a -> Bool) ->
Set.Set a -> [[a]]
{- | flattens a list of non-empty sets and uses the minimal element of
each set to represent the set -}
{- | checks if a given relation is locally filtered
* precondition: the relation must already be closed by transitive closure
locallyFiltered :: Ord a => Rel a -> Bool
locallyFiltered rel = check . flatSet . partSet iso $ mostRight rel
(&& not (haveCommonLeftElem x y rel))) True s'