packages feed

edges 0.10 → 0.11

raw patch · 8 files changed

+76/−78 lines, 8 filesdep +cereal-vectordep +data-dworddep +vector-th-unboxdep ~deferred-foldsPVP ok

version bump matches the API change (PVP)

Dependencies added: cereal-vector, data-dword, vector-th-unbox

Dependency ranges changed: deferred-folds

API changes (from Hackage documentation)

- Edges.NodeCounting: node :: Edges source target -> Node source -> NodeCounts source
- Edges.Data: nodeCountsList :: NodeCounts entity -> [Word64]
+ Edges.Data: nodeCountsList :: NodeCounts entity -> [Word128]
- Edges.Data: nodeCountsUnboxedVector :: NodeCounts entity -> Vector Word64
+ Edges.Data: nodeCountsUnboxedVector :: NodeCounts entity -> Vector Word128
- Edges.Data: unindexNodeCounts :: (Eq entity, Hashable entity) => (Int -> Maybe entity) -> NodeCounts entity -> HashMap entity Int
+ Edges.Data: unindexNodeCounts :: (Eq entity, Hashable entity) => (Int -> Maybe entity) -> NodeCounts entity -> HashMap entity Word128

Files

edges.cabal view
@@ -1,5 +1,5 @@ name: edges-version: 0.10+version: 0.11 category: Graphs synopsis: Tools for efficient immutable graphs description: A set of tools for constructing immutable graphs which are both memory and performance-efficient.@@ -15,7 +15,7 @@  library   hs-source-dirs: library-  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, OverloadedLists, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples+  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, InstanceSigs, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, OverloadedLists, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples   default-language: Haskell2010   exposed-modules:     Edges.Data@@ -37,9 +37,11 @@   build-depends:     base >=4.7 && <5,     cereal >=0.5.5 && <0.6,+    cereal-vector >=0.2.0.1 && <0.3,     contravariant >=1.4 && <2,+    data-dword >=0.3.1.2 && <0.4,     deepseq >=1.4 && <2,-    deferred-folds >=0.6 && <0.7,+    deferred-folds >=0.6.12 && <0.7,     foldl >=1.4.2 && <2,     hashable >=1.2 && <2,     monad-par >=0.3.4.8 && <0.4,@@ -53,13 +55,14 @@     semigroupoids >=5.2 && <6,     text >=1 && <2,     unordered-containers >=0.2 && <0.3,-    vector >=0.12 && <0.13+    vector >=0.12 && <0.13,+    vector-th-unbox >=0.2.1.6 && <0.3  test-suite test   type: exitcode-stdio-1.0   hs-source-dirs: test   main-is: Main.hs-  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, OverloadedLists, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples+  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, InstanceSigs, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, OverloadedLists, PatternGuards, PatternSynonyms, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeApplications, TypeFamilies, TypeOperators, UnboxedTuples   default-language: Haskell2010   build-depends:     cereal,
library/Edges/Cereal/Get.hs view
@@ -9,8 +9,7 @@   nodeCounts :: Get (NodeCounts entity)-nodeCounts =-  NodeCounts <$> PrimArray.cerealGetAsInMemory get+nodeCounts = NodeCounts <$> get  edges :: Get (Edges a b) edges = do
library/Edges/Cereal/Put.hs view
@@ -9,8 +9,8 @@   nodeCounts :: Putter (NodeCounts entity)-nodeCounts (NodeCounts pa) =-  PrimArray.cerealPutAsInMemory put pa+nodeCounts (NodeCounts vector) =+  put vector  edges :: Putter (Edges a b) edges (Edges targetSpaceValue mpaValue) = targetSpace <> mpa where
library/Edges/Functions.hs view
@@ -62,17 +62,17 @@   Edges bAmount $ runIdentity $ PrimMultiArray.create aAmount $ \ fold ->   Identity $ Foldl.fold fold foldable -nodeCountsList :: NodeCounts entity -> [Word64]-nodeCountsList (NodeCounts pa) = foldrPrimArray' (:) [] pa+nodeCountsList :: NodeCounts entity -> [Word128]+nodeCountsList (NodeCounts vector) = UnboxedVector.foldr (:) [] vector -nodeCountsUnboxedVector :: NodeCounts entity -> UnboxedVector.Vector Word64-nodeCountsUnboxedVector (NodeCounts pa) = PrimArray.toUnboxedVector pa+nodeCountsUnboxedVector :: NodeCounts entity -> UnboxedVector.Vector Word128+nodeCountsUnboxedVector (NodeCounts vector) = vector -unindexNodeCounts :: (Eq entity, Hashable entity) => (Int -> Maybe entity) -> NodeCounts entity -> HashMap entity Int-unindexNodeCounts lookup (NodeCounts pa) = let+unindexNodeCounts :: (Eq entity, Hashable entity) => (Int -> Maybe entity) -> NodeCounts entity -> HashMap entity Word128+unindexNodeCounts lookup (NodeCounts vector) = let   unfold = do-    index <- Unfold.intsInRange 0 (pred (sizeofPrimArray pa))+    index <- Unfold.intsInRange 0 (pred (UnboxedVector.length vector))     return $ do       entity <- lookup index-      return (entity, fromIntegral (indexPrimArray pa index))+      return (entity, fromIntegral (UnboxedVector.unsafeIndex vector index))   in Unfold.fold (Foldl.hashMapByMapMaybe id) unfold
library/Edges/NodeCounting.hs view
@@ -4,7 +4,6 @@   Node,   Amount,   Edges,-  node,   nodeTargets,   targets, )@@ -19,24 +18,18 @@ import qualified PrimitiveExtras.TVarArray as TVarArray import qualified DeferredFolds.UnfoldM as UnfoldM import qualified Data.Vector.Unboxed as UnboxedVector-import qualified Control.Monad.Par.IO as Par-import qualified Control.Monad.Par as Par hiding (runParIO)+import qualified Data.Vector.Unboxed.Mutable as MutableUnboxedVector  -node :: Edges source target -> Node source -> NodeCounts source-node edges = -  nodeWithAmount (edgesSourceAmount edges)--nodeWithAmount :: Amount entity -> Node entity -> NodeCounts entity-nodeWithAmount (Amount size) (Node index) =-  NodeCounts (PrimArray.oneHot size index 1)- nodeTargets :: Edges source target -> Node source -> NodeCounts target-nodeTargets (Edges targetAmount edgesPma) (Node sourceIndex) =-  let indexUnfold = fmap fromIntegral (PrimMultiArray.toUnfoldAtM edgesPma sourceIndex)-      indexFold = PrimArray.indexCountsFold targetAmount-      countPa = UnfoldM.fold indexFold indexUnfold-      in NodeCounts countPa+nodeTargets (Edges targetAmount edgesPma) (Node sourceIndex) = do+  unsafePerformIO $ do+    targetCountsMVec <- MutableUnboxedVector.new targetAmount+    UnfoldM.forM_ (fmap fromIntegral $ PrimMultiArray.toUnfoldAtM edgesPma sourceIndex) $ \ targetIndex -> do+      targetCount <- MutableUnboxedVector.read targetCountsMVec targetIndex+      MutableUnboxedVector.unsafeWrite targetCountsMVec targetIndex (targetCount + 1)+    targetCountsVec <- UnboxedVector.unsafeFreeze targetCountsMVec+    return (NodeCounts targetCountsVec)  {-| Count the occurrences of targets based on the occurrences of sources.@@ -50,35 +43,14 @@ This function can be used to reduce the amount of computation by excluding the nodes, which don't make much difference. -}-targetsWithMinSourceAmount :: Word64 -> Edges source target -> NodeCounts source -> NodeCounts target-targetsWithMinSourceAmount minSourceCount (Edges targetAmount edgesPma) (NodeCounts sourceCountsPa) =+targetsWithMinSourceAmount :: Word128 -> Edges source target -> NodeCounts source -> NodeCounts target+targetsWithMinSourceAmount minSourceCount (Edges targetAmount edgesPma) (NodeCounts sourceCountsVec) =   unsafePerformIO $ do-    targetCountsMpa <- newPrimArray targetAmount-    forMInAscendingRange_ 0 (sizeofPrimArray sourceCountsPa) $ \ sourceIndex -> let-      sourceCount = indexPrimArray sourceCountsPa sourceIndex-      in if sourceCount >= minSourceCount-        then UnfoldM.forM_ (fmap fromIntegral $ PrimMultiArray.toUnfoldAtM edgesPma sourceIndex) $ \ targetIndex -> do-          targetCount <- readPrimArray targetCountsMpa targetIndex-          writePrimArray targetCountsMpa targetIndex (targetCount + sourceCount)-        else return ()-    targetCountsPa <- unsafeFreezePrimArray targetCountsMpa-    return (NodeCounts targetCountsPa)--{-|-Count the occurrences of targets based on the occurrences of sources.--Utilizes parallellism.--}-targetsParallelly :: Edges source target -> NodeCounts source -> NodeCounts target-targetsParallelly (Edges targetAmount edgesPma) (NodeCounts sourceCountsPa) =-  unsafePerformIO $ Par.runParIO $ do-    targetCountVarTable <- liftIO (TVarArray.new 0 targetAmount)-    Par.parFor (Par.InclusiveRange 0 (pred (sizeofPrimArray sourceCountsPa))) $ \ sourceIndex ->-      case indexPrimArray sourceCountsPa sourceIndex of-        0 -> return ()-        sourceCount ->-          liftIO $-          UnfoldM.forM_ (PrimMultiArray.toUnfoldAtM edgesPma sourceIndex) $ \ targetIndex ->-          TVarArray.modifyAt targetCountVarTable (fromIntegral targetIndex) (+ sourceCount)-    targetCountsPa <- liftIO (TVarArray.freezeAsPrimArray targetCountVarTable)-    return (NodeCounts targetCountsPa)+    targetCountsMVec <- MutableUnboxedVector.new targetAmount+    flip UnboxedVector.imapM_ sourceCountsVec $ \ sourceIndex sourceCount -> if sourceCount >= minSourceCount+      then UnfoldM.forM_ (fmap fromIntegral $ PrimMultiArray.toUnfoldAtM edgesPma sourceIndex) $ \ targetIndex -> do+        targetCount <- MutableUnboxedVector.read targetCountsMVec targetIndex+        MutableUnboxedVector.unsafeWrite targetCountsMVec targetIndex (targetCount + sourceCount)+      else return ()+    targetCountsVec <- UnboxedVector.unsafeFreeze targetCountsMVec+    return (NodeCounts targetCountsVec)
library/Edges/Prelude.hs view
@@ -5,7 +5,6 @@   modifyTVar',   forMInAscendingRange_,   forMInDescendingRange_,-  (.),   showText,   -- * Optics   Lens,@@ -24,7 +23,7 @@ ------------------------- import Control.Applicative as Exports import Control.Arrow as Exports-import Control.Category as Exports hiding ((.))+import Control.Category as Exports import Control.Concurrent as Exports import Control.Exception as Exports import Control.Monad as Exports hiding (mapM_, sequence_, forM_, msum, mapM, sequence, forM)@@ -148,7 +147,16 @@ ------------------------- import Control.DeepSeq as Exports +-- data-dword+-------------------------+import Data.DoubleWord as Exports++-- cereal-vector+-------------------------+import Data.Vector.Serialize ()+ import qualified Data.Vector.Unboxed as UnboxedVector+import qualified Data.Vector.Unboxed.Deriving as UnboxedVectorDeriving  type UnboxedVector = UnboxedVector.Vector @@ -158,9 +166,6 @@     x <- readTVar var     writeTVar var $! f x -(.) :: Semigroupoid s => s b c -> s a b -> s a c-(.) = o- {-# INLINE forMInAscendingRange_ #-} forMInAscendingRange_ :: Applicative m => Int -> Int -> (Int -> m a) -> m () forMInAscendingRange_ !startN !endN f =@@ -200,3 +205,30 @@ {-# INLINE _Just #-} _Just :: Prism' (Maybe a) a _Just = prism Just (maybe (Left Nothing) Right)+++-- * Instances for unboxed vectors+-------------------------++UnboxedVectorDeriving.derivingUnbox "Word96"+  [t| Word96 -> (Word32, Word64) |]+  [| \ (Word96 a b) -> (a, b) |]+  [| \ (a, b) -> Word96 a b |]++UnboxedVectorDeriving.derivingUnbox "Word128"+  [t| Word128 -> (Word64, Word64) |]+  [| \ (Word128 a b) -> (a, b) |]+  [| \ (a, b) -> Word128 a b |]++UnboxedVectorDeriving.derivingUnbox "Word256"+  [t| Word256 -> (Word128, Word128) |]+  [| \ (Word256 a b) -> (a, b) |]+  [| \ (a, b) -> Word256 a b |]+++-- * Instances for "cereal"+-------------------------++instance Serialize Word96+instance Serialize Word128+instance Serialize Word256
library/Edges/Types.hs view
@@ -10,7 +10,7 @@  newtype Node entity = Node Int -newtype NodeCounts entity = NodeCounts (PrimArray Word64)+newtype NodeCounts entity = NodeCounts (UnboxedVector Word128)  newtype EdgeCounts source target = EdgeCounts (PrimArray Word64) 
test/Main.hs view
@@ -46,14 +46,6 @@             node = Node 1 :: Node (Proxy 1)             in               [-                testCase "0, unoptimized" $ let-                  nodeCountsList = NodeCounting.node edges1 node & Data.nodeCountsList-                  in assertEqual (show nodeCountsList) [0, 1, 0] nodeCountsList-                ,-                testCase "1, unoptimized" $ let-                  nodeCountsList = NodeCounting.node edges1 node & NodeCounting.targets edges1 & Data.nodeCountsList-                  in assertEqual (show nodeCountsList) [1, 1, 0] nodeCountsList-                ,                 testCase "1" $ let                   nodeCountsList = NodeCounting.nodeTargets edges1 node & Data.nodeCountsList                   in assertEqual (show nodeCountsList) [1, 1, 0] nodeCountsList