easytensor-2.1.1.0: test/Numeric/Matrix/BidiagonalTest.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
module Numeric.Matrix.BidiagonalTest (runTests) where
import Control.Monad (join)
import Data.Kind
import Data.Monoid (All (..))
import Numeric.Arbitraries
import Numeric.DataFrame
import Numeric.Dimensions
import Numeric.Matrix.Bidiagonal
import Test.QuickCheck
validateBidiagonal :: forall (t :: Type) (n :: Nat) (m :: Nat)
. ( KnownDim n, KnownDim m
, RealFloatExtras t, Show t
, MatrixDeterminant t n
, MatrixDeterminant t m
)
=> Matrix t n m -> BiDiag t n m -> Property
validateBidiagonal a BiDiag {..} =
counterexample
(unlines
[ "failed a =~= u %* b %* transpose v:"
, "a: " ++ show a
, "a': " ++ show a'
, "u: " ++ show u
, "b: " ++ show b
, "v: " ++ show v
]
) (approxEq mag a a')
.&&.
counterexample
(unlines
[ "u is not quite orthogonal:"
, "a: " ++ show a
, "u: " ++ show u
, "b: " ++ show b
, "v: " ++ show v
]
) (approxEq mag eye (u %* transpose u))
.&&.
counterexample
(unlines
[ "v is not quite orthogonal:"
, "a: " ++ show a
, "u: " ++ show u
, "b: " ++ show b
, "v: " ++ show v
]
) (approxEq mag eye (v %* transpose v))
.&&.
counterexample
(unlines
[ "b is not upper-bidiagonal"
, "a: " ++ show a
, "u: " ++ show u
, "b: " ++ show b
, "v: " ++ show v
]
) (getAll $ iwfoldMap @t @'[n,m]
(\(Idx i :* Idx j :* U) x -> All (j == i || j == i + 1 || x == 0))
b
)
.&&.
counterexample
(unlines
[ "Incorrect determinant carried out for U"
, "a: " ++ show a
, "u: " ++ show u
, "bdUDet: " ++ show bdUDet
, "det u: " ++ show (det u)
]
) (approxEq mag bdUDet (det u))
.&&.
counterexample
(unlines
[ "Incorrect determinant carried out for V"
, "a: " ++ show a
, "v: " ++ show v
, "bdVDet: " ++ show bdVDet
, "det v: " ++ show (det v)
]
) (approxEq mag bdVDet (det v))
where
mag = fromIntegral (totalDim $ dims `inSpaceOf` a) ^ (2 :: Int) :: Scalar t
a' = u %* b %* transpose v
b = biDiag dims bdAlpha bdBeta
u = bdU
v = bdV
prop_bidiagonalSimple :: Property
prop_bidiagonalSimple = once . conjoin $ map prop_bidiagonal xs
where
mkM :: Dims [n,m] -> [Double] -> DataFrame Double '[XN 1, XN 1]
mkM ds
| Just (XDims ds'@Dims) <- constrainDims ds :: Maybe (Dims '[XN 1, XN 1])
= XFrame . fromFlatList ds' 0
mkM _ = error "prop_qrSimple: bad dims"
variants :: Num a => [a] -> [[a]]
variants as = rotateList as ++ rotateList (map negate as)
xs :: [DataFrame Double '[XN 1, XN 1]]
xs = join
[ [mkM $ D2 :* D2 :* U, mkM $ D5 :* D2 :* U, mkM $ D3 :* D7 :* U]
<*> [repeat 0, repeat 1, repeat 2]
, mkM (D2 :* D2 :* U) <$> variants [3,2, 4,1]
, mkM (D3 :* D3 :* U) <$> variants [0,0,1, 3,2,0, 4,1,0]
, mkM (D4 :* D2 :* U) <$> variants [3,2, 4,1, 0,0, 0,2]
, mkM (D2 :* D3 :* U) <$> variants [3,2,0, 4,1,2]
, mkM (D2 :* D2 :* U) <$> variants [2, 0, 0, 0]
, mkM (D2 :* D2 :* U) <$> variants [4, 1, 0, 0]
, mkM (D2 :* D2 :* U) <$> variants [3, 1, -2, 0]
, [mkM $ D2 :* D3 :* U, mkM $ D3 :* D2 :* U]
<*> join
[ variants [2, 0, 0, 0, 0, 0]
, variants [4, 1, 0, 0, 0, 0]
, variants [3, 1, -2, 0, 0, 0]
, variants [3, 0, -2, 9, 0, 0]
]
]
prop_bidiagonal :: DataFrame Double '[XN 1, XN 1] -> Property
prop_bidiagonal (XFrame x)
| n@D :* m@D :* U <- dims `inSpaceOf` x
, D <- minDim n m
= validateBidiagonal x (bidiagonalHouseholder x)
#if !MIN_VERSION_GLASGOW_HASKELL(8,10,0,0)
prop_bidiagonal _ = property False
#endif
return []
runTests :: Int -> IO Bool
runTests n = $forAllProperties
$ quickCheckWithResult stdArgs { maxSuccess = n }