packages feed

HTab-1.6.3: src/HTab/DisjSet.hs

module HTab.DisjSet
( DisjSet, Pointer(..), mkDSet, find, union, isRoot, onlyFind )
where

import qualified Data.Map as Map
import HTab.Formula ( Nom )

-- a disjoint-set forest
type DisjSet x = Map.Map x x
-- meaning: if an element is *not* in DisjSet,
-- then it is a root of a class

-- invariant: there is no N such that (N,N) is in DisjSet
-- (it would provoke a look in the find function)



-- find the root of the tree in which a given element belongs to
-- at each call to "find", we optimise the DisjSet to link to the root
find :: Ord x => x -> DisjSet x -> (x,DisjSet x)
find n s = case Map.lookup n s of
             Nothing -> (n,s)
             Just parent -> let (ancestor, modifiedDisjSet) = find parent s
                             in 
                            (ancestor, Map.insert n ancestor modifiedDisjSet)


onlyFind :: Ord x => x -> DisjSet x -> x
onlyFind n s
 = case Map.lookup n s of
     Nothing -> n
     Just parent -> onlyFind parent s

-- union the sets in which a and b belong to
-- ensure : root of the merged set is the smallest root (min a b)
union :: Ord x => x -> x ->  DisjSet x -> DisjSet x
union a b s = case compare rootA rootB of
                EQ -> modifiedDisjSet2
                GT -> Map.insert rootA rootB modifiedDisjSet2
                LT -> Map.insert rootB rootA modifiedDisjSet2
               where (rootA,modifiedDisjSet1) = find a s
                     (rootB,modifiedDisjSet2) = find b modifiedDisjSet1

isRoot :: Ord x => x -> DisjSet x -> Bool
isRoot n s = Map.notMember n s

-- constructor of an empty disjoint-set forest
mkDSet :: Ord x => DisjSet x
mkDSet = Map.empty::DisjSet x

-- this should be outside of the module
data Pointer = Prefix Int | Nominal Nom
 deriving (Eq)

instance Show Pointer where
 show (Prefix p)  = '#' : show p
 show (Nominal n) = n

instance Ord Pointer where
 compare (Prefix i1)  (Prefix i2)  = compare i1 i2
 compare (Nominal i1) (Nominal i2) = compare i1 i2
 compare (Nominal _)  (Prefix _)   = GT
 compare (Prefix _)   (Nominal _)  = LT

-- We have this order (p: prefix , n: nominal):
-- p0 < p1 < ... < pn < n0 < n1 < ... < nm

-- The representative of a set is the smallest (by this order) element of the set.
-- Good news : a set always contains a prefix, so the reprensentative
-- is always the earliest prefix of the set.