module Numeric.LinearAlgebra.Tests.Properties (
dist, (|~|), (~:), Aprox((:~)),
zeros, ones,
square,
unitary,
hermitian,
wellCond,
positiveDefinite,
upperTriang,
upperHessenberg,
luProp,
invProp,
pinvProp,
detProp,
nullspaceProp,
svdProp1, svdProp2,
eigProp, eigSHProp,
qrProp,
hessProp,
schurProp1, schurProp2,
cholProp,
expmDiagProp,
multProp1, multProp2,
linearSolveProp
) where
import Numeric.LinearAlgebra
#include "quickCheckCompat.h"
dist :: (Normed t, Num t) => t -> t -> Double
dist a b = r
where norm = pnorm Infinity
na = norm a
nb = norm b
nab = norm (ab)
mx = max na nb
mn = min na nb
r = if mn < eps
then mx
else nab/mx
infixl 4 |~|
a |~| b = a :~10~: b
data Aprox a = (:~) a Int
(~:) :: (Normed a, Num a) => Aprox a -> a -> Bool
a :~n~: b = dist a b < 10^^(n)
square m = rows m == cols m
unitary m = square m && m <> ctrans m |~| ident (rows m)
hermitian m = square m && m |~| ctrans m
wellCond m = rcond m > 1/100
positiveDefinite m = minimum (toList e) > 0
where (e,_v) = eigSH m
upperTriang m = rows m == 1 || down == z
where down = fromList $ concat $ zipWith drop [1..] (toLists (ctrans m))
z = constant 0 (dim down)
upperHessenberg m = rows m < 3 || down == z
where down = fromList $ concat $ zipWith drop [2..] (toLists (ctrans m))
z = constant 0 (dim down)
zeros (r,c) = reshape c (constant 0 (r*c))
ones (r,c) = zeros (r,c) + 1
luProp m = m |~| p <> l <> u && f (det p) |~| f s
where (l,u,p,s) = lu m
f x = fromList [x]
invProp m = m <> inv m |~| ident (rows m)
pinvProp m = m <> p <> m |~| m
&& p <> m <> p |~| p
&& hermitian (m<>p)
&& hermitian (p<>m)
where p = pinv m
detProp m = s d1 |~| s d2
where d1 = det m
d2 = det' * det q
det' = product $ toList $ takeDiag r
(q,r) = qr m
s x = fromList [x]
nullspaceProp m = null nl `trivial` (null nl || m <> n |~| zeros (r,c))
where nl = nullspacePrec 1 m
n = fromColumns nl
r = rows m
c = cols m rank m
svdProp1 m = u <> real d <> trans v |~| m
&& unitary u && unitary v
where (u,d,v) = full svd m
svdProp2 m = (m |~| 0) `trivial` ((m |~| 0) || u <> real (diag s) <> trans v |~| m)
where (u,s,v) = economy svd m
eigProp m = complex m <> v |~| v <> diag s
where (s, v) = eig m
eigSHProp m = m <> v |~| v <> real (diag s)
&& unitary v
&& m |~| v <> real (diag s) <> ctrans v
where (s, v) = eigSH m
qrProp m = q <> r |~| m && unitary q && upperTriang r
where (q,r) = qr m
hessProp m = m |~| p <> h <> ctrans p && unitary p && upperHessenberg h
where (p,h) = hess m
schurProp1 m = m |~| u <> s <> ctrans u && unitary u && upperTriang s
where (u,s) = schur m
schurProp2 m = m |~| u <> s <> ctrans u && unitary u && upperHessenberg s
where (u,s) = schur m
cholProp m = m |~| ctrans c <> c && upperTriang c
where c = chol m
expmDiagProp m = expm (logm m) :~ 7 ~: complex m
where logm = matFunc log
mulH a b = fromLists [[ doth ai bj | bj <- toColumns b] | ai <- toRows a ]
where doth u v = sum $ zipWith (*) (toList u) (toList v)
multProp1 (a,b) = a <> b |~| mulH a b
multProp2 (a,b) = ctrans (a <> b) |~| ctrans b <> ctrans a
linearSolveProp f m = f m m |~| ident (rows m)