@@ -30,11 +30,17 @@ import Data.Graph.Inductive.Graph
30
30
import Control.Applicative (liftA2 )
31
31
import Data.IntMap (IntMap )
32
32
import qualified Data.IntMap as IM
33
- import Data.List (sort )
33
+ import Data.List (foldl' , sort )
34
34
import Data.Maybe (fromMaybe )
35
35
36
36
#if MIN_VERSION_containers (0,4,2)
37
- import Control.DeepSeq (NFData (.. ))
37
+ import Control.DeepSeq (NFData (.. ))
38
+ #endif
39
+
40
+ #if MIN_VERSION_containers(0,5,0)
41
+ import qualified Data.IntMap.Strict as IMS
42
+ #else
43
+ import qualified Data.IntMap as IMS
38
44
#endif
39
45
40
46
#if __GLASGOW_HASKELL__ >= 702
@@ -115,9 +121,11 @@ instance Graph Gr where
115
121
116
122
instance DynGraph Gr where
117
123
(p, v, l, s) & (Gr g)
118
- = let ! g1 = IM. insert v (fromAdj p, l, fromAdj s) g
119
- ! g2 = addSucc g1 v p
120
- ! g3 = addPred g2 v s
124
+ = let ! g1 = IM. insert v (preds, l, succs) g
125
+ ! (np, preds) = fromAdjCounting p
126
+ ! (ns, succs) = fromAdjCounting s
127
+ ! g2 = addSucc g1 v np preds
128
+ ! g3 = addPred g2 v ns succs
121
129
in Gr g3
122
130
123
131
#if MIN_VERSION_containers (0,4,2)
@@ -144,8 +152,8 @@ matchGr node (Gr g)
144
152
-> let ! g1 = IM. delete node g
145
153
! p' = IM. delete node p
146
154
! s' = IM. delete node s
147
- ! g2 = clearPred g1 node ( IM. keys s')
148
- ! g3 = clearSucc g2 node ( IM. keys p')
155
+ ! g2 = clearPred g1 node s'
156
+ ! g3 = clearSucc g2 node p'
149
157
in (Just (toAdj p', node, label, toAdj s), Gr g3)
150
158
151
159
----------------------------------------------------------------------
@@ -166,11 +174,11 @@ fastInsNode (v, l) (Gr g) = g' `seq` Gr g'
166
174
fastInsEdge :: LEdge b -> Gr a b -> Gr a b
167
175
fastInsEdge (v, w, l) (Gr g) = g2 `seq` Gr g2
168
176
where
169
- g1 = IM. adjust addSucc ' v g
170
- g2 = IM. adjust addPred ' w g1
177
+ g1 = IM. adjust addS ' v g
178
+ g2 = IM. adjust addP ' w g1
171
179
172
- addSucc ' (ps, l', ss) = (ps, l', IM. insertWith addLists w [l] ss)
173
- addPred ' (ps, l', ss) = (IM. insertWith addLists v [l] ps, l', ss)
180
+ addS ' (ps, l', ss) = (ps, l', IM. insertWith addLists w [l] ss)
181
+ addP ' (ps, l', ss) = (IM. insertWith addLists v [l] ps, l', ss)
174
182
175
183
{-# RULES
176
184
"gmap/Data.Graph.Inductive.PatriciaTree" gmap = fastGMap
@@ -220,6 +228,31 @@ toAdj = concatMap expand . IM.toList
220
228
fromAdj :: Adj b -> IntMap [b ]
221
229
fromAdj = IM. fromListWith addLists . map (second (: [] ) . swap)
222
230
231
+ data FromListCounting a = FromListCounting ! Int ! (IntMap a )
232
+ deriving (Eq , Show , Read )
233
+
234
+ getFromListCounting :: FromListCounting a -> (Int , IntMap a )
235
+ getFromListCounting (FromListCounting i m) = (i, m)
236
+ {-# INLINE getFromListCounting #-}
237
+
238
+ fromListWithKeyCounting :: (Int -> a -> a -> a ) -> [(Int , a )] -> (Int , IntMap a )
239
+ fromListWithKeyCounting f = getFromListCounting . foldl' ins (FromListCounting 0 IM. empty)
240
+ where
241
+ ins (FromListCounting i t) (k,x) = FromListCounting (i + 1 ) (IM. insertWithKey f k x t)
242
+ {-# INLINE fromListWithKeyCounting #-}
243
+
244
+ fromListWithCounting :: (a -> a -> a ) -> [(Int , a )] -> (Int , IntMap a )
245
+ fromListWithCounting f = fromListWithKeyCounting (\ _ x y -> f x y)
246
+ {-# INLINE fromListWithCounting #-}
247
+
248
+ fromAdjCounting :: Adj b -> (Int , IntMap [b ])
249
+ fromAdjCounting = fromListWithCounting addLists . map (second (: [] ) . swap)
250
+
251
+ -- We use differenceWith to modify a graph more than bulkThreshold times,
252
+ -- and repeated insertWith otherwise.
253
+ bulkThreshold :: Int
254
+ bulkThreshold = 5
255
+
223
256
toContext :: Node -> Context' a b -> Context a b
224
257
toContext v (ps, a, ss) = (toAdj ps, v, a, toAdj ss)
225
258
@@ -238,33 +271,44 @@ addLists [a] as = a : as
238
271
addLists as [a] = a : as
239
272
addLists xs ys = xs ++ ys
240
273
241
- addSucc :: GraphRep a b -> Node -> [(b , Node )] -> GraphRep a b
242
- addSucc g _ [] = g
243
- addSucc g v ((l, p) : rest) = addSucc g' v rest
244
- where
245
- g' = IM. adjust f p g
246
- f (ps, l', ss) = (ps, l', IM. insertWith addLists v [l] ss)
247
-
248
-
249
- addPred :: GraphRep a b -> Node -> [(b , Node )] -> GraphRep a b
250
- addPred g _ [] = g
251
- addPred g v ((l, s) : rest) = addPred g' v rest
274
+ addSucc :: forall a b . GraphRep a b -> Node -> Int -> IM. IntMap [b ] -> GraphRep a b
275
+ addSucc g0 v numAdd xs
276
+ | numAdd < bulkThreshold = IM. foldlWithKey' go g0 xs
252
277
where
253
- g' = IM. adjust f s g
254
- f (ps, l', ss) = (IM. insertWith addLists v [l] ps, l', ss)
255
-
278
+ go :: GraphRep a b -> Node -> [b ] -> GraphRep a b
279
+ go g p l = IMS. adjust f p g
280
+ where f (ps, l', ss) = let ! ss' = IM. insertWith (++) v l ss
281
+ in (ps, l', ss')
282
+ addSucc g v _ xs = IMS. differenceWith go g xs
283
+ where
284
+ go :: Context' a b -> [b ] -> Maybe (Context' a b )
285
+ go (ps, l', ss) l = let ! ss' = IM. insertWith (++) v l ss
286
+ in Just (ps, l', ss')
256
287
257
- clearSucc :: GraphRep a b -> Node -> [ Node ] -> GraphRep a b
258
- clearSucc g _ [] = g
259
- clearSucc g v (p : rest) = clearSucc g' v rest
288
+ addPred :: forall a b . GraphRep a b -> Node -> Int -> IM. IntMap [ b ] -> GraphRep a b
289
+ addPred g0 v numAdd xs
290
+ | numAdd < bulkThreshold = IM. foldlWithKey' go g0 xs
260
291
where
261
- g' = IM. adjust f p g
262
- f (ps, l, ss) = (ps, l, IM. delete v ss)
292
+ go :: GraphRep a b -> Node -> [b ] -> GraphRep a b
293
+ go g p l = IMS. adjust f p g
294
+ where f (ps, l', ss) = let ! ps' = IM. insertWith (++) v l ps
295
+ in (ps', l', ss)
296
+ addPred g v _ xs = IMS. differenceWith go g xs
297
+ where
298
+ go :: Context' a b -> [b ] -> Maybe (Context' a b )
299
+ go (ps, l', ss) l = let ! ps' = IM. insertWith (++) v l ps
300
+ in Just (ps', l', ss)
263
301
302
+ clearSucc :: forall a b x . GraphRep a b -> Node -> IM. IntMap x -> GraphRep a b
303
+ clearSucc g v = IMS. differenceWith go g
304
+ where
305
+ go :: Context' a b -> x -> Maybe (Context' a b )
306
+ go (ps, l, ss) _ = let ! ss' = IM. delete v ss
307
+ in Just (ps, l, ss')
264
308
265
- clearPred :: GraphRep a b -> Node -> [Node ] -> GraphRep a b
266
- clearPred g _ [] = g
267
- clearPred g v (s: rest) = clearPred g' v rest
309
+ clearPred :: forall a b x . GraphRep a b -> Node -> IM. IntMap x -> GraphRep a b
310
+ clearPred g v = IMS. differenceWith go g
268
311
where
269
- g' = IM. adjust f s g
270
- f (ps, l, ss) = (IM. delete v ps, l, ss)
312
+ go :: Context' a b -> x -> Maybe (Context' a b )
313
+ go (ps, l, ss) _ = let ! ps' = IM. delete v ps
314
+ in Just (ps', l, ss)
0 commit comments