summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2009-11-10 15:36:51 +0000
committerAlberto Ruiz <aruiz@um.es>2009-11-10 15:36:51 +0000
commite8939f7f7f9654bcf0ab9a0cd3720279117e2e29 (patch)
tree796671c2bc92e8f0af9db5a10b1583d5623981a3 /lib
parent8147f7fee65a9a8f27bbf12e79b616954fce948f (diff)
rankSVD, nullspaceSVD
Diffstat (limited to 'lib')
-rw-r--r--lib/Numeric/LinearAlgebra/Algorithms.hs63
1 files changed, 46 insertions, 17 deletions
diff --git a/lib/Numeric/LinearAlgebra/Algorithms.hs b/lib/Numeric/LinearAlgebra/Algorithms.hs
index e22246f..110619a 100644
--- a/lib/Numeric/LinearAlgebra/Algorithms.hs
+++ b/lib/Numeric/LinearAlgebra/Algorithms.hs
@@ -62,7 +62,9 @@ module Numeric.LinearAlgebra.Algorithms (
62-- * Util 62-- * Util
63 haussholder, 63 haussholder,
64 unpackQR, unpackHess, 64 unpackQR, unpackHess,
65 pinvTol 65 pinvTol,
66 rankSVD,
67 nullspaceSVD
66) where 68) where
67 69
68 70
@@ -248,18 +250,28 @@ full svdFun m = (u, d ,v) where
248economy :: Element t 250economy :: Element t
249 => (Matrix t -> (Matrix t, Vector Double, Matrix t)) -> Matrix t -> (Matrix t, Vector Double, Matrix t) 251 => (Matrix t -> (Matrix t, Vector Double, Matrix t)) -> Matrix t -> (Matrix t, Vector Double, Matrix t)
250economy svdFun m = (u', subVector 0 d s, v') where 252economy svdFun m = (u', subVector 0 d s, v') where
251 (u,s,v) = svdFun m 253 r@(u,s,v) = svdFun m
252 sl@(g:_) = toList s 254 d = rankSVD (1*eps) m r `max` 1
253 s' = fromList . filter (>tol) $ sl
254 t = 1
255 tol = (fromIntegral (max r c) * g * t * eps)
256 r = rows m
257 c = cols m
258 d = dim s'
259 u' = takeColumns d u 255 u' = takeColumns d u
260 v' = takeColumns d v 256 v' = takeColumns d v
261 257
262 258
259-- | Numeric rank of a matrix from the SVD decomposition.
260rankSVD :: Element t
261 => Double -- ^ numeric zero (e.g. 1*'eps')
262 -> Matrix t -- ^ input matrix m
263 -> (Matrix t, Vector Double, Matrix t) -- ^ 'svd' of m
264 -> Int -- ^ rank of m
265rankSVD teps m (_,s,_) = k where
266 sl@(g:_) = toList s
267 r = rows m
268 c = cols m
269 tol = fromIntegral (max r c) * g * teps
270 s' = fromList . filter (>tol) $ sl
271 k = if g > teps
272 then dim s'
273 else 0
274
263-- | The machine precision of a Double: @eps = 2.22044604925031e-16@ (the value used by GNU-Octave). 275-- | The machine precision of a Double: @eps = 2.22044604925031e-16@ (the value used by GNU-Octave).
264eps :: Double 276eps :: Double
265eps = 2.22044604925031e-16 277eps = 2.22044604925031e-16
@@ -336,18 +348,36 @@ instance Normed (Matrix (Complex Double)) where
336----------------------------------------------------------------------- 348-----------------------------------------------------------------------
337 349
338-- | The nullspace of a matrix from its SVD decomposition. 350-- | The nullspace of a matrix from its SVD decomposition.
351nullspaceSVD :: Field t
352 => Either Double Int -- ^ Left \"numeric\" zero (eg. 1*'eps'),
353 -- or Right \"theoretical\" matrix rank.
354 -> Matrix t -- ^ input matrix m
355 -> (Matrix t, Vector Double, Matrix t) -- ^ 'svd' of m
356 -> [Vector t] -- ^ list of unitary vectors spanning the nullspace
357nullspaceSVD hint a z@(_,_,v) = vs where
358 r = rows a
359 c = cols a
360 tol = case hint of
361 Left t -> t
362 _ -> eps
363 k = case hint of
364 Right t -> t
365 _ -> rankSVD tol a z
366 nsol = c - k
367 vs = drop k (toColumns v)
368
369
370-- | The nullspace of a matrix. See also 'nullspaceSVD'.
339nullspacePrec :: Field t 371nullspacePrec :: Field t
340 => Double -- ^ relative tolerance in 'eps' units 372 => Double -- ^ relative tolerance in 'eps' units
341 -> Matrix t -- ^ input matrix 373 -> Matrix t -- ^ input matrix
342 -> [Vector t] -- ^ list of unitary vectors spanning the nullspace 374 -> [Vector t] -- ^ list of unitary vectors spanning the nullspace
343nullspacePrec t m = ns where 375nullspacePrec t m = ns where
344 (_,s,v) = svd m 376 r@(_,_,v) = svd m
345 sl@(g:_) = toList s 377 k = rankSVD (t*eps) m r
346 tol = (fromIntegral (max (rows m) (cols m)) * g * t * eps) 378 ns = drop k $ toRows $ ctrans v
347 rank' = length (filter (> g*tol) sl)
348 ns = drop rank' $ toRows $ ctrans v
349 379
350-- | The nullspace of a matrix, assumed to be one-dimensional, with default tolerance (shortcut for @last . nullspacePrec 1@). 380-- | The nullspace of a matrix, assumed to be one-dimensional, with default tolerance 1*'eps'.
351nullVector :: Field t => Matrix t -> Vector t 381nullVector :: Field t => Matrix t -> Vector t
352nullVector = last . nullspacePrec 1 382nullVector = last . nullspacePrec 1
353 383
@@ -436,8 +466,7 @@ rcond m = last s / head s
436 466
437-- | Number of linearly independent rows or columns. 467-- | Number of linearly independent rows or columns.
438rank :: Field t => Matrix t -> Int 468rank :: Field t => Matrix t -> Int
439rank m | pnorm PNorm1 m < eps = 0 469rank m = rankSVD eps m (svd m)
440 | otherwise = dim s where (_,s,_) = economy svd m
441 470
442{- 471{-
443expm' m = case diagonalize (complex m) of 472expm' m = case diagonalize (complex m) of