module Statistics ( tests_Statistics ) where import Control.Monad( replicateM ) import Data.AEq import Data.List( foldl' ) import Debug.Trace import Test.Framework import Test.Framework.Providers.QuickCheck2 import Test.QuickCheck hiding ( vector ) import qualified Test.QuickCheck as QC import Numeric.LinearAlgebra import qualified Numeric.LinearAlgebra.Packed as P import qualified Numeric.LinearAlgebra.Matrix as M import qualified Numeric.LinearAlgebra.Vector as V import Test.QuickCheck.LinearAlgebra( VectorList(..), WeightedVectorList(..) ) import qualified Test.QuickCheck.LinearAlgebra as Test import Typed testAEq actual expected = if actual ~== expected then True else trace ("expected: " ++ show expected ++ "\nactual: " ++ show actual) False tests_Statistics = testGroup "Statistics" [ testPropertyD "sum" prop_sum , testPropertyD "weightedSum" prop_weightedSum , testPropertyD "mean" prop_mean , testPropertyD "weightedMean" prop_weightedMean , testPropertyD "weightedMean (equal weights)" prop_weightedMean_eqw , testPropertyD "Matrix cov" prop_Matrix_cov , testPropertyD "Matrix covWithMean" prop_Matrix_covWithMean , testPropertyD "Matrix weightedCov (equal weights)" prop_Matrix_weightedCov_eqw , testPropertyD "Matrix weightedCov" prop_Matrix_weightedCov , testPropertyD "Matrix weightedCovWithMean" prop_Matrix_weightedCovWithMean , testPropertyD "Packed cov" prop_Packed_cov , testPropertyD "Packed covWithMean" prop_Packed_covWithMean , testPropertyD "Packed weightedCov (equal weights)" prop_Packed_weightedCov_eqw , testPropertyD "Packed weightedCov" prop_Packed_weightedCov , testPropertyD "Packed weightedCovWithMean" prop_Packed_weightedCovWithMean ] prop_sum t (VectorList p xs) = V.sum p xs ~== foldl' V.add (V.constant p 0) xs where _ = typed t (head xs) prop_weightedSum t (WeightedVectorList p wxs) = V.weightedSum p wxs ~== V.sum p (map (uncurry V.scale) wxs) where n = length wxs _ = typed t (snd $ head wxs) prop_mean t (VectorList p xs) = V.mean p xs ~== V.scale (1/n) (V.sum p xs) where n = fromIntegral $ max (length xs) 1 _ = typed t (head xs) prop_weightedMean_eqw t (VectorList p xs) = let wxs = zip (repeat 1) xs in V.weightedMean p wxs ~== V.mean p xs where _ = typed t (head xs) prop_weightedMean t (WeightedVectorList p wxs) = let w_sum = (sum . fst . unzip) wxs in V.weightedMean p wxs ~== if w_sum == 0 then V.constant p 0 else V.scale (1/w_sum) (V.weightedSum p wxs) where n = length wxs _ = typed t (snd $ head wxs) prop_Matrix_cov t (VectorList p xs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let xbar = V.mean p xs ys = [ V.sub x xbar | x <- xs ] scale = case method of { UnbiasedCov -> 1/(n-1) ; MLCov -> 1/n } cov' = foldl' (flip $ \y -> M.rank1Update scale y y) (M.constant (p,p) 0) ys cov = M.cov p method xs in M.hermMulVector cov z ~== M.mulVector NoTrans cov' z where n = fromIntegral $ length xs _ = typed t $ head xs prop_Matrix_covWithMean t (VectorList p xs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let xbar = V.mean p xs cov' = M.covWithMean xbar method xs cov = M.cov p method xs in M.hermMulVector cov z ~== M.hermMulVector cov' z where n = fromIntegral $ length xs _ = typed t $ head xs prop_Matrix_weightedCov_eqw t (VectorList p xs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let wxs = zip (repeat 1) xs cov = M.weightedCov p method wxs cov' = M.cov p method xs in M.hermMulVector cov z ~== M.hermMulVector cov' z where n = fromIntegral $ length xs _ = typed t $ head xs prop_Matrix_weightedCov t (WeightedVectorList p wxs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let (ws,xs) = unzip wxs w_sum = sum ws ws' = [ w / w_sum | w <- ws ] w2_sum = sum [ w*w | w <- ws' ] scale = case method of { UnbiasedCov -> 1/(1-w2_sum) ; MLCov -> 1 } xbar = V.weightedMean p wxs wys = [ (w, V.sub x xbar) | (w,x) <- zip ws' xs ] cov' = if w_sum == 0 then M.constant (p,p) 0 else foldl' (flip $ \(w,y) -> M.rank1Update (scale*w) y y) (M.constant (p,p) 0) wys cov = M.weightedCov p method wxs in M.hermMulVector cov z ~== M.mulVector NoTrans cov' z where n = fromIntegral $ length wxs _ = typed t $ snd $ head wxs prop_Matrix_weightedCovWithMean t (WeightedVectorList p wxs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let xbar = V.weightedMean p wxs cov' = M.weightedCov p method wxs cov = M.weightedCovWithMean xbar method wxs in M.hermMulVector cov z ~== M.hermMulVector cov' z where n = fromIntegral $ length wxs _ = typed t $ snd $ head wxs prop_Packed_cov t (VectorList p xs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let cov' = M.cov p method xs cov = P.cov p method xs in P.hermMulVector cov z ~== M.hermMulVector cov' z where n = fromIntegral $ length xs _ = typed t $ head xs prop_Packed_covWithMean t (VectorList p xs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let xbar = V.mean p xs cov = P.covWithMean xbar method xs cov' = P.cov p method xs in P.hermMulVector cov z ~== P.hermMulVector cov' z where n = fromIntegral $ length xs _ = typed t $ head xs prop_Packed_weightedCov_eqw t (VectorList p xs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let wxs = zip (repeat 1) xs cov = P.weightedCov p method wxs cov' = P.cov p method xs in P.hermMulVector cov z ~== P.hermMulVector cov' z where n = fromIntegral $ length xs _ = typed t $ head xs prop_Packed_weightedCov t (WeightedVectorList p wxs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let cov' = M.weightedCov p method wxs cov = P.weightedCov p method wxs in P.hermMulVector cov z ~== M.hermMulVector cov' z where n = fromIntegral $ length wxs _ = typed t $ snd $ head wxs prop_Packed_weightedCovWithMean t (WeightedVectorList p wxs) = forAll (Test.vector p) $ \z -> forAll (elements [ UnbiasedCov, MLCov ]) $ \method -> let xbar = V.weightedMean p wxs cov' = P.weightedCov p method wxs cov = P.weightedCovWithMean xbar method wxs in P.hermMulVector cov z ~== P.hermMulVector cov' z where n = fromIntegral $ length wxs _ = typed t $ snd $ head wxs