1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
|
{-# LANGUAGE CPP #-}
{-# LANGUAGE MultiParamTypeClasses #-}
#if __GLASGOW_HASKELL__ >= 702
{-# LANGUAGE Safe #-}
#endif
#if __GLASGOW_HASKELL__ >= 706
{-# LANGUAGE DeriveGeneric #-}
#endif
#if __GLASGOW_HASKELL__ >= 710 && __GLASGOW_HASKELL__ < 802
{-# LANGUAGE AutoDeriveTypeable #-}
#endif
-----------------------------------------------------------------------------
-- |
-- Module : Data.PriorityQueue.FingerTree
-- Copyright : (c) Ross Paterson 2008
-- License : BSD-style
-- Maintainer : R.Paterson@city.ac.uk
-- Stability : experimental
-- Portability : non-portable (MPTCs and functional dependencies)
--
-- Interval maps implemented using the 'FingerTree' type, following
-- section 4.8 of
--
-- * Ralf Hinze and Ross Paterson,
-- \"Finger trees: a simple general-purpose data structure\",
-- /Journal of Functional Programming/ 16:2 (2006) pp 197-217.
-- <http://staff.city.ac.uk/~ross/papers/FingerTree.html>
--
-- An amortized running time is given for each operation, with /n/
-- referring to the size of the priority queue. These bounds hold even
-- in a persistent (shared) setting.
--
-- /Note/: Many of these operations have the same names as similar
-- operations on lists in the "Prelude". The ambiguity may be resolved
-- using either qualification or the @hiding@ clause.
--
-----------------------------------------------------------------------------
module Data.IntervalMap.FingerTree (
-- * Intervals
Interval(..), low, high, point,
-- * Interval maps
IntervalMap, empty, singleton, insert, union,
-- * Searching
search, intersections, dominators,
-- * Extraction
bounds, leastView, splitAfter
) where
import qualified Data.FingerTree as FT
import Data.FingerTree (FingerTree, Measured(..), ViewL(..), (<|), (><))
import Prelude hiding (null)
#if MIN_VERSION_base(4,6,0)
import GHC.Generics
#endif
#if MIN_VERSION_base(4,8,0)
import qualified Prelude (null)
#else
import Control.Applicative ((<$>))
import Data.Foldable (Foldable(foldMap))
import Data.Monoid
import Data.Traversable (Traversable(traverse))
#endif
#if (MIN_VERSION_base(4,9,0)) && !(MIN_VERSION_base(4,11,0))
import Data.Semigroup
#endif
import Data.Foldable (toList)
----------------------------------
-- 4.8 Application: interval trees
----------------------------------
-- | A closed interval. The lower bound should be less than or equal
-- to the upper bound.
data Interval v = Interval v v -- ^ Lower and upper bounds of the interval.
deriving (Eq, Ord, Show, Read
#if __GLASGOW_HASKELL__ >= 706
, Generic
#endif
)
-- | Lower bound of the interval
low :: Interval v -> v
low (Interval lo _) = lo
-- | Upper bound of the interval
high :: Interval v -> v
high (Interval _ hi) = hi
-- | An interval in which the lower and upper bounds are equal.
point :: v -> Interval v
point v = Interval v v
data Node v a = Node (Interval v) a
deriving (Eq, Ord, Show, Read
#if __GLASGOW_HASKELL__ >= 706
, Generic
#endif
)
instance Functor (Node v) where
fmap f (Node i x) = Node i (f x)
instance Foldable (Node v) where
foldMap f (Node _ x) = f x
instance Traversable (Node v) where
traverse f (Node i x) = Node i <$> f x
-- rightmost interval (including largest lower bound) and largest upper bound.
data IntInterval v = NoInterval | IntInterval (Interval v) v
#if __GLASGOW_HASKELL__ >= 706
deriving (Generic)
#endif
#if MIN_VERSION_base(4,9,0)
instance Ord v => Semigroup (IntInterval v) where
(<>) = intervalUnion
#endif
instance Ord v => Monoid (IntInterval v) where
mempty = NoInterval
#if !(MIN_VERSION_base(4,11,0))
mappend = intervalUnion
#endif
intervalUnion :: Ord v => IntInterval v -> IntInterval v -> IntInterval v
NoInterval `intervalUnion` i = i
i `intervalUnion` NoInterval = i
IntInterval _ hi1 `intervalUnion` IntInterval int2 hi2 =
IntInterval int2 (max hi1 hi2)
instance (Ord v) => Measured (IntInterval v) (Node v a) where
measure (Node i _) = IntInterval i (high i)
-- | Map of closed intervals, possibly with duplicates.
newtype IntervalMap v a =
IntervalMap (FingerTree (IntInterval v) (Node v a))
#if __GLASGOW_HASKELL__ >= 706
deriving (Generic)
#endif
-- ordered lexicographically by interval
instance Functor (IntervalMap v) where
fmap f (IntervalMap t) = IntervalMap (FT.unsafeFmap (fmap f) t)
-- | Values in lexicographical order of intervals.
instance Foldable (IntervalMap v) where
foldMap f (IntervalMap t) = foldMap (foldMap f) t
#if MIN_VERSION_base(4,8,0)
null (IntervalMap t) = FT.null t
#endif
-- | Traverse the intervals in lexicographical order.
instance Traversable (IntervalMap v) where
traverse f (IntervalMap t) =
IntervalMap <$> FT.unsafeTraverse (traverse f) t
instance (Eq v, Eq a) => Eq (IntervalMap v a) where
IntervalMap xs == IntervalMap ys = toList xs == toList ys
-- | Lexicographical ordering
instance (Ord v, Ord a) => Ord (IntervalMap v a) where
compare (IntervalMap xs) (IntervalMap ys) = compare (toList xs) (toList ys)
instance (Show v, Show a) => Show (IntervalMap v a) where
showsPrec p (IntervalMap ns)
| FT.null ns = showString "empty"
| otherwise =
showParen (p > 0) (showIntervals (toList ns))
where
showIntervals [] = showString "empty"
showIntervals (Node i x:ixs) =
showString "insert " . showsPrec 11 i .
showChar ' ' . showsPrec 11 x .
showString " $ " . showIntervals ixs
#if MIN_VERSION_base(4,9,0)
-- | 'union'.
instance (Ord v) => Semigroup (IntervalMap v a) where
(<>) = union
#endif
-- | 'empty' and 'union'.
instance (Ord v) => Monoid (IntervalMap v a) where
mempty = empty
#if !(MIN_VERSION_base(4,11,0))
mappend = union
#endif
-- | /O(1)/. The empty interval map.
empty :: (Ord v) => IntervalMap v a
empty = IntervalMap FT.empty
-- | /O(1)/. Interval map with a single entry.
singleton :: (Ord v) => Interval v -> a -> IntervalMap v a
singleton i x = IntervalMap (FT.singleton (Node i x))
-- | /O(log n)/. Insert an interval and associated value into a map.
-- The map may contain duplicate intervals; the new entry will be inserted
-- before any existing entries for the same interval.
insert :: (Ord v) => Interval v -> a -> IntervalMap v a -> IntervalMap v a
insert (Interval lo hi) _ m | lo > hi = m
insert i x (IntervalMap t) = IntervalMap (l >< Node i x <| r)
where
(l, r) = FT.split larger t
larger (IntInterval k _) = k >= i
larger NoInterval = error "larger NoInterval"
-- | /O(m log (n/\//m))/. Merge two interval maps.
-- The map may contain duplicate intervals; entries with equal intervals
-- are kept in the original order.
union :: (Ord v) => IntervalMap v a -> IntervalMap v a -> IntervalMap v a
union (IntervalMap xs) (IntervalMap ys) = IntervalMap (merge1 xs ys)
where
merge1 as bs = case FT.viewl as of
EmptyL -> bs
a@(Node i _) :< as' -> l >< a <| merge2 as' r
where
(l, r) = FT.split larger bs
larger (IntInterval k _) = k >= i
larger NoInterval = error "larger NoInterval"
merge2 as bs = case FT.viewl bs of
EmptyL -> as
b@(Node i _) :< bs' -> l >< b <| merge1 r bs'
where
(l, r) = FT.split larger as
larger (IntInterval k _) = k > i
larger NoInterval = error "larger NoInterval"
-- | /O(k log (n/\//k))/. All intervals that intersect with the given
-- interval, in lexicographical order.
intersections :: (Ord v) => Interval v -> IntervalMap v a -> [(Interval v, a)]
intersections i = inRange (low i) (high i)
-- | /O(k log (n/\//k))/. All intervals that contain the given interval,
-- in lexicographical order.
dominators :: (Ord v) => Interval v -> IntervalMap v a -> [(Interval v, a)]
dominators i = inRange (high i) (low i)
-- | /O(k log (n/\//k))/. All intervals that contain the given point,
-- in lexicographical order.
search :: (Ord v) => v -> IntervalMap v a -> [(Interval v, a)]
search p = inRange p p
-- | /O(k log (n/\//k))/. All intervals that intersect with the given
-- interval, in lexicographical order.
inRange :: (Ord v) => v -> v -> IntervalMap v a -> [(Interval v, a)]
inRange lo hi (IntervalMap t) = matches (FT.takeUntil (greater hi) t)
where
matches xs = case FT.viewl (FT.dropUntil (atleast lo) xs) of
EmptyL -> []
Node i x :< xs' -> (i, x) : matches xs'
-- | /O(1)/. @'bounds' m@ returns @'Nothing'@ if @m@ is empty, and
-- otherwise @'Just' i@, where @i@ is the smallest interval containing
-- all the intervals in the map.
--
-- @since 0.1.3.0
bounds :: (Ord v) => IntervalMap v a -> Maybe (Interval v)
bounds (IntervalMap t) = case measure t of
NoInterval -> Nothing
IntInterval _ hi -> case FT.viewl t of
EmptyL -> Nothing
Node (Interval lo _) _ FT.:< _ -> Just (Interval lo hi)
-- | /O(1)/. @'leastView' m@ returns @'Nothing'@ if @m@ is empty, and
-- otherwise @'Just' ((i, x), m')@, where @i@ is the least interval,
-- @x@ is the associated value, and @m'@ is the rest of the map.
--
-- @since 0.1.3.0
leastView :: Ord v =>
IntervalMap v a -> Maybe ((Interval v, a), IntervalMap v a)
leastView (IntervalMap t) = case FT.viewl t of
EmptyL -> Nothing
Node i a FT.:< t' -> Just ((i, a), IntervalMap t')
-- | /O(log(min(i,n-i)))/. @'splitAfter' k m@ returns a pair of submaps,
-- one consisting of intervals whose lower bound is less than or equal
-- to @k@, and the other of those whose lower bound is greater.
--
-- @since 0.1.3.0
splitAfter :: Ord v =>
v -> IntervalMap v a -> (IntervalMap v a, IntervalMap v a)
splitAfter k (IntervalMap t) = (IntervalMap before, IntervalMap after)
where
(before, after) = FT.split (greater k) t
atleast :: (Ord v) => v -> IntInterval v -> Bool
atleast k (IntInterval _ hi) = k <= hi
atleast _ NoInterval = error "atleast NoInterval"
greater :: (Ord v) => v -> IntInterval v -> Bool
greater k (IntInterval i _) = low i > k
greater _ NoInterval = error "greater NoInterval"
{-
-- Examples
mkMap :: (Ord v) => [(v, v, a)] -> IntervalMap v a
mkMap = foldr ins empty
where
ins (lo, hi, n) = insert (Interval lo hi) n
composers :: IntervalMap Int String
composers = mkMap [
(1685, 1750, "Bach"),
(1685, 1759, "Handel"),
(1732, 1809, "Haydn"),
(1756, 1791, "Mozart"),
(1770, 1827, "Beethoven"),
(1782, 1840, "Paganini"),
(1797, 1828, "Schubert"),
(1803, 1869, "Berlioz"),
(1810, 1849, "Chopin"),
(1833, 1897, "Brahms"),
(1838, 1875, "Bizet")]
mathematicians :: IntervalMap Int String
mathematicians = mkMap [
(1642, 1727, "Newton"),
(1646, 1716, "Leibniz"),
(1707, 1783, "Euler"),
(1736, 1813, "Lagrange"),
(1777, 1855, "Gauss"),
(1811, 1831, "Galois")]
-}
|