TreePO.hs revision 76408af596b604997cabe1ebde1caaa43f58b1e6
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseModule : $Header$
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseDescription : Handling of tree-like partial ordering relations
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseCopyright : (c) Ewaryst Schulz, DFKI Bremen 2010
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseLicense : GPLv2 or higher, see LICENSE.txt
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseMaintainer : ewaryst.schulz@dfki.de
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseStability : experimental
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosePortability : portable
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BoseThis module defines a basic datatype for tree-like partial orderings such as
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseencountered, e.g., in the set lattice.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose{- ( Incomparable (..)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose , SetOrdering (..)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose , SetOrInterval (..)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose , swapCompare
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose , combineCmp
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseimport qualified Data.Set as Set
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ----------------------------------------------------------------------
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- * Datatypes for comparison
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ----------------------------------------------------------------------
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosedata Incomparable = Disjoint | Overlap deriving (Eq, Show)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosedata SetOrdering = Comparable Ordering | Incomparable Incomparable deriving Eq
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseinstance Show SetOrdering where
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose show (Comparable LT) = "<"
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose show (Comparable GT) = ">"
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose show (Comparable EQ) = "="
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose show (Incomparable x) = show x
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose{- | We represent Intervals with opened or closed end points over a linearly
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose ordered type 'a' as closed intervals over the type '(a, InfDev)', for
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose infinitesimal deviation.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose - '(x, EpsLeft)' means an epsilon to the left of x
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose - '(x, Zero)' means x
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose - '(x, EpsRight)' means an epsilon to the right of x
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose We have EpsLeft < Zero < EpsRight and the ordering of 'a' lifts to the
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose lexicographical ordering of '(a, InfDev)' which captures well our intended
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose We inject the type 'a' into the type '(a, InfDev)'
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose by mapping 'x' to '(x, Zero)'.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose The mapping of intrvals is as follows:
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose A left opened interval starting at x becomes a left closed interval starting
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose at '(x, EpsRight)'.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose 'forall y > x. (y, _) > (x, EpsRight)', hence in particular
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose '(y, Zero) > (x, EpsRight)'
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose '(x, Zero) < (x, EpsRight)'
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose Analogously we represent a right opened one ending at y as a closed one
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose ending at '(x, EpsLeft)'.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosedata InfDev = EpsLeft | Zero | EpsRight deriving (Eq, Show)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseinstance Ord InfDev where
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | x == y = EQ
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | otherwise =
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose case (x, y) of
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (EpsLeft, _) -> LT
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (EpsRight, _) -> GT
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose _ -> swapCompare $ compare y x
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosenewtype CIType a = CIType (a, InfDev) deriving (Eq, Show)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | This type with the given ordering is to represent opened/closed intervals
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- over 'a' as closed intervals over '(a, InfDev)'
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseinstance Ord a => Ord (CIType a) where
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose compare (CIType (x, a)) (CIType (y, b)) =
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose case compare x y of
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose EQ -> compare a b
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | A finite set or an interval. True = closed, False = opened interval border.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosedata SetOrInterval a = Set (Set.Set a)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | IntVal (a, Bool) (a, Bool)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose deriving (Eq, Ord, Show)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | A closed interval
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosedata ClosedInterval a = ClosedInterval a a deriving (Eq, Ord, Show)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Infinite integers = integers augmented by -Infty and +Infty
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bosedata InfInt = PosInf | NegInf | FinInt Integer deriving (Show, Eq)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseinstance Ord InfInt where
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | x == y = EQ
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | otherwise =
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose case (x, y) of
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (NegInf, _) -> LT
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (PosInf, _) -> GT
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose (FinInt a, FinInt b) -> compare a b
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose _ -> swapCompare $ compare y x
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseclass Continuous a
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseclass Discrete a where
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose nextA :: a -> a
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose prevA :: a -> a
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose intsizeA :: a -> a -> Maybe Integer
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Boseinstance Discrete InfInt where
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose nextA (FinInt a) = FinInt $ a+1
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose prevA (FinInt a) = FinInt $ a-1
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose intsizeA (FinInt a) (FinInt b) = Just $ (1+) $ abs $ b-a
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose intsizeA _ _ = Nothing
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ----------------------------------------------------------------------
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- * Comparison facility for sets
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ----------------------------------------------------------------------
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Compares closed intervals [l1, r1] and [l2, r2]. Assumes
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | non-singular intervals, i.e., l1 < r1 and l2 < r2.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Works only for linearly ordered types.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosecmpClosedInts :: Ord a => ClosedInterval a -- ^ [l1, r1]
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose -> ClosedInterval a -- ^ [l2, r2]
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose -> SetOrdering
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosecmpClosedInts (ClosedInterval l1 r1) (ClosedInterval l2 r2)
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | l1 == l2 && r1 == r2 = Comparable EQ
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | l1 <= l2 && r1 >= r2 = Comparable GT
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | l1 >= l2 && r1 <= r2 = Comparable LT
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | r1 < l2 || r2 < l1 = Incomparable Disjoint
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | otherwise = Incomparable Overlap
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ----------------------------------------------------------------------
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ** Comparison for discrete types
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- ----------------------------------------------------------------------
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Membership in 'SetOrInterval'
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosemembSoID :: (Discrete a, Ord a) => a -> SetOrInterval a -> Bool
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosemembSoID x (Set s) = Set.member x s
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosemembSoID x i = let ClosedInterval a b = setToClosedIntD i in x >= a && x <= b
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Checks if the set is empty.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosenullSoID :: (Discrete a, Ord a) => SetOrInterval a -> Bool
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosenullSoID (Set s) = Set.null s
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosenullSoID i = let ClosedInterval a b = setToClosedIntD i in a > b
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | If the set is singular, i.e., consists only from one point, then we
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- return this point. Reports error on empty SoI's.
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosetoSingularD :: (Discrete a, Ord a) => SetOrInterval a -> Maybe a
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosetoSingularD d
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | nullSoID d = error "toSingularD: empty set"
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | otherwise =
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose | otherwise -> Nothing
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose _ -> let ClosedInterval a b = setToClosedIntD d
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose in if a == b then Just a else Nothing
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Transforms a 'SetOrInterval' to a closed representation
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosesetToClosedIntD :: (Discrete a, Ord a) => SetOrInterval a -> ClosedInterval a
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosesetToClosedIntD (Set s) = ClosedInterval (Set.findMin s) $ Set.findMax s
885386b7e3f1c3e74b354576b98a092b0835d64eSumit BosesetToClosedIntD (IntVal (l, bL) (r, bR)) =
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose ClosedInterval (if bL then l else nextA l) $ if bR then r else prevA r
885386b7e3f1c3e74b354576b98a092b0835d64eSumit Bose-- | Compare sets over discrete types
| fromIntegral (Set.size s) == dst ->
Comparable LT -> if any (flip membSoID i1) $ Set.toList s
membSoI x (Set s) = Set.member x s
nullSoI (Set s) = Set.null s
-- | If the set is singular, i.e., consists only from one point, then we
setToClosedInt (Set s) = ClosedInterval (CIType (Set.findMin s, Zero))
$ CIType (Set.findMax s, Zero)
| s1 `Set.isSubsetOf` s2 = Comparable LT
| s2 `Set.isSubsetOf` s1 = Comparable GT
Comparable LT -> if any (flip membSoI i1) $ Set.toList s