data-sketches-0.4.0.0: test/HyperLogLogSpec.hs
{-# LANGUAGE TypeApplications #-}
module HyperLogLogSpec where
import Control.Monad (forM_)
import Data.Word
import Test.Hspec
import qualified DataSketches.Distinct.HyperLogLog as HLL
spec :: Spec
spec = describe "HyperLogLog Sketch" $ do
specify "empty sketch estimates 0" $ do
sk <- HLL.mkHllSketch 12
est <- HLL.estimate sk
est `shouldBe` 0.0
specify "single item estimates ~1" $ do
sk <- HLL.mkHllSketch 12
HLL.insert sk 42
est <- HLL.estimate sk
est `shouldSatisfy` (\e -> e >= 0.5 && e <= 2.0)
specify "100 distinct items estimates approximately 100" $ do
sk <- HLL.mkHllSketch 12
forM_ [1..100 :: Word64] $ HLL.insert sk
est <- HLL.estimate sk
-- With p=12, error ~1.6%, so within ~20 is very generous
est `shouldSatisfy` (\e -> abs (e - 100) < 30)
specify "1000 distinct items estimates approximately 1000" $ do
sk <- HLL.mkHllSketch 14
forM_ [1..1000 :: Word64] $ HLL.insert sk
est <- HLL.estimate sk
est `shouldSatisfy` (\e -> abs (e - 1000) < 100)
specify "10000 distinct items estimates approximately 10000" $ do
sk <- HLL.mkHllSketch 14
forM_ [1..10000 :: Word64] $ HLL.insert sk
est <- HLL.estimate sk
est `shouldSatisfy` (\e -> abs (e - 10000) < 1000)
specify "duplicate items don't increase estimate" $ do
sk <- HLL.mkHllSketch 12
forM_ [1..100 :: Word64] $ HLL.insert sk
est1 <- HLL.estimate sk
-- Insert all the same items again
forM_ [1..100 :: Word64] $ HLL.insert sk
est2 <- HLL.estimate sk
-- Estimate should be about the same (still ~100)
abs (est2 - est1) `shouldSatisfy` (< 5)
specify "merge combines two sketches" $ do
sk1 <- HLL.mkHllSketch 12
forM_ [1..500 :: Word64] $ HLL.insert sk1
sk2 <- HLL.mkHllSketch 12
forM_ [501..1000 :: Word64] $ HLL.insert sk2
HLL.merge sk1 sk2
est <- HLL.estimate sk1
est `shouldSatisfy` (\e -> abs (e - 1000) < 100)
specify "merge with overlapping items gives correct estimate" $ do
sk1 <- HLL.mkHllSketch 12
forM_ [1..500 :: Word64] $ HLL.insert sk1
sk2 <- HLL.mkHllSketch 12
forM_ [250..750 :: Word64] $ HLL.insert sk2
HLL.merge sk1 sk2
est <- HLL.estimate sk1
-- 750 distinct items
est `shouldSatisfy` (\e -> abs (e - 750) < 100)
specify "precision is reported correctly" $ do
sk <- HLL.mkHllSketch 14
p <- HLL.precision sk
p `shouldBe` 14