probability-polynomial-1.0.1.0: test/Numeric/Measure/DiscreteSpec.hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-|
Copyright : Predictable Network Solutions Ltd., 2020-2024
License : BSD-3-Clause
-}
module Numeric.Measure.DiscreteSpec
( spec
) where
import Prelude
import Data.Function.Class
( eval
)
import Numeric.Measure.Discrete
( Discrete
, add
, after
, beforeOrAt
, convolve
, dirac
, distribution
, fromMap
, integrate
, scale
, toMap
, total
, translate
, zero
)
import Test.Hspec
( Spec
, describe
, it
)
import Test.QuickCheck
( Arbitrary
, Positive (..)
, (===)
, (==>)
, arbitrary
, cover
, property
)
import qualified Data.Map.Strict as Map
{-----------------------------------------------------------------------------
Tests
------------------------------------------------------------------------------}
spec :: Spec
spec = do
describe "instance Eq" $ do
it "add m (scale (-1) m) == zero" $ property $
\(m :: Discrete Rational) ->
cover 80 (total m /= 0) "nontrivial"
$ add m (scale (-1) m) === zero
it "dirac x /= dirac y" $ property $
\(x :: Rational) (y :: Rational) ->
x /= y ==> dirac x /= dirac y
describe "distribution" $ do
it "eval and total" $ property $
\(m :: Discrete Rational) ->
let xlast = maybe 0 fst $ Map.lookupMax $ toMap m
in total m
=== eval (distribution m) xlast
it "eval and scale" $ property $
\(m :: Discrete Rational) x s->
eval (distribution (scale s m)) x
=== s * eval (distribution m) x
describe "integrate" $ do
it "total" $ property $
\(m :: Discrete Rational) ->
integrate (const 1) m
=== total m
it "linearity, function (+)" $ property $
\(mx :: Discrete Rational) ->
let f = id
in integrate (\x -> f x + f x) mx
=== integrate f mx + integrate f mx
it "linearity, measure add" $ property $
\(mx :: Discrete Rational) my ->
let f = id
in integrate f (add mx my)
=== integrate f mx + integrate f my
it "linearity, measure scale" $ property $
\(mx :: Discrete Rational) a ->
let f = id
in integrate f (scale a mx)
=== a * integrate f mx
describe "translate" $ do
it "distribution" $ property $
\(m :: Discrete Rational) y x ->
eval (distribution (translate y m)) x
=== eval (distribution m) (x - y)
describe "beforeOrAt and after" $ do
it "add beforeOrAt after" $ property $
\(mx :: Discrete Rational) t ->
add (beforeOrAt t mx) (after t mx) === mx
it "eval distribution after" $ property $
\(mx :: Discrete Rational) t ->
eval (distribution (after t mx)) t === 0
describe "convolve" $ do
it "dirac" $ property $
\(x :: Rational) y ->
convolve (dirac x) (dirac y)
=== dirac (x + y)
it "total" $ property $
\mx (my :: Discrete Rational) ->
total (convolve mx my)
=== total mx * total my
it "symmetric" $ property $
\mx (my :: Discrete Rational) ->
convolve mx my
=== convolve my mx
it "distributive, left" $ property $
\mx my (mz :: Discrete Rational) ->
convolve (add mx my) mz
=== add (convolve mx mz) (convolve my mz)
it "distributive, right" $ property $
\mx my (mz :: Discrete Rational) ->
convolve mx (add my mz)
=== add (convolve mx my) (convolve mx mz)
it "translate, left" $ property $
\mx (my :: Discrete Rational) (Positive z) ->
translate z (convolve mx my)
=== convolve (translate z mx) my
{-----------------------------------------------------------------------------
Random generators
------------------------------------------------------------------------------}
instance (Ord a, Num a, Arbitrary a) => Arbitrary (Discrete a) where
arbitrary = fromMap . Map.fromList <$> arbitrary