Improve performance of Relation.difference, Relation3.difference

This commit is contained in:
Mitchell Rosen 2021-10-06 18:41:08 -04:00
parent 023a86c585
commit 3a19e522b3
2 changed files with 30 additions and 11 deletions

View File

@ -9,6 +9,7 @@ module Unison.Util.Relation
fromManyRan, fromManyRan,
fromMap, fromMap,
fromMultimap, fromMultimap,
fromSet, fromSet,
unsafeFromMultimaps, unsafeFromMultimaps,
@ -75,6 +76,7 @@ module Unison.Util.Relation
-- ** Combinations -- ** Combinations
difference, difference,
difference1,
intersection, intersection,
joinDom, joinDom,
joinRan, joinRan,
@ -149,12 +151,26 @@ unsafeFromMultimaps domain range =
-- * Functions about relations -- * Functions about relations
-- | Compute the difference of two relations.
difference :: (Ord a, Ord b) => Relation a b -> Relation a b -> Relation a b difference :: (Ord a, Ord b) => Relation a b -> Relation a b -> Relation a b
difference a b = fromList . S.toList $ diffSet difference (Relation d1 r1) (Relation d2 r2) =
Relation
(Map.differenceWith setDifference1 d1 d2)
(Map.differenceWith setDifference1 r1 r2)
where where
diffSet = S.difference seta setb -- Set difference, but return Nothing if the difference is empty.
seta = S.fromList . toList $ a setDifference1 :: Ord a => Set a -> Set a -> Maybe (Set a)
setb = S.fromList . toList $ b setDifference1 xs ys =
if S.null zs then Nothing else Just zs
where
zs = S.difference xs ys
-- | Like 'difference', but returns @Nothing@ if the difference is empty.
difference1 :: (Ord a, Ord b) => Relation a b -> Relation a b -> Maybe (Relation a b)
difference1 xs ys =
if null zs then Nothing else Just zs
where
zs = difference xs ys
-- The size is calculated using the domain. -- The size is calculated using the domain.
@ -373,6 +389,8 @@ filterManyDom r = filterDom (`manyDom` r) r
-- | -- |
-- True if the relation @r@ is the 'empty' relation. -- True if the relation @r@ is the 'empty' relation.
--
-- /O(1)/.
null :: Relation a b -> Bool null :: Relation a b -> Bool
null r = M.null $ domain r null r = M.null $ domain r

View File

@ -96,12 +96,13 @@ insertAll, deleteAll :: Foldable f => Ord a => Ord b => Ord c
insertAll f r = foldl' (\r x -> uncurry3 insert x r) r f insertAll f r = foldl' (\r x -> uncurry3 insert x r) r f
deleteAll f r = foldl' (\r x -> uncurry3 delete x r) r f deleteAll f r = foldl' (\r x -> uncurry3 delete x r) r f
-- | Compute the difference of two relations.
difference :: (Ord a, Ord b, Ord c) difference :: (Ord a, Ord b, Ord c) => Relation3 a b c -> Relation3 a b c -> Relation3 a b c
=> Relation3 a b c difference (Relation3 a1 b1 c1) (Relation3 a2 b2 c2) =
-> Relation3 a b c Relation3
-> Relation3 a b c (Map.differenceWith R.difference1 a1 a2)
difference a b = deleteAll (Unison.Util.Relation3.toList b) a (Map.differenceWith R.difference1 b1 b2)
(Map.differenceWith R.difference1 c1 c2)
delete a b c Relation3{..} = delete a b c Relation3{..} =
Relation3 Relation3