summaryrefslogtreecommitdiff
path: root/lib/Numeric/LinearAlgebra/Algorithms.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric/LinearAlgebra/Algorithms.hs')
-rw-r--r--lib/Numeric/LinearAlgebra/Algorithms.hs132
1 files changed, 51 insertions, 81 deletions
diff --git a/lib/Numeric/LinearAlgebra/Algorithms.hs b/lib/Numeric/LinearAlgebra/Algorithms.hs
index 7e258de..0f3ff0e 100644
--- a/lib/Numeric/LinearAlgebra/Algorithms.hs
+++ b/lib/Numeric/LinearAlgebra/Algorithms.hs
@@ -1,5 +1,8 @@
1{-# LANGUAGE FlexibleContexts, FlexibleInstances #-} 1{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
2{-# LANGUAGE CPP #-} 2{-# LANGUAGE CPP #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
4{-# LANGUAGE UndecidableInstances #-}
5{-# LANGUAGE TypeFamilies #-}
3----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
4{- | 7{- |
5Module : Numeric.LinearAlgebra.Algorithms 8Module : Numeric.LinearAlgebra.Algorithms
@@ -58,10 +61,9 @@ module Numeric.LinearAlgebra.Algorithms (
58 nullspacePrec, 61 nullspacePrec,
59 nullVector, 62 nullVector,
60 nullspaceSVD, 63 nullspaceSVD,
61-- * Norms
62 Normed(..), NormType(..),
63-- * Misc 64-- * Misc
64 eps, i, 65 eps, peps, i,
66 Normed(..), NormType(..),
65-- * Util 67-- * Util
66 haussholder, 68 haussholder,
67 unpackQR, unpackHess, 69 unpackQR, unpackHess,
@@ -72,17 +74,15 @@ module Numeric.LinearAlgebra.Algorithms (
72 74
73 75
74import Data.Packed.Internal hiding ((//)) 76import Data.Packed.Internal hiding ((//))
75--import Data.Packed.Vector
76import Data.Packed.Matrix 77import Data.Packed.Matrix
77import Data.Complex 78import Data.Complex
78import Numeric.GSL.Vector
79import Numeric.LinearAlgebra.LAPACK as LAPACK 79import Numeric.LinearAlgebra.LAPACK as LAPACK
80import Numeric.LinearAlgebra.Linear 80import Numeric.LinearAlgebra.Linear
81import Data.List(foldl1') 81import Data.List(foldl1')
82import Data.Array 82import Data.Array
83 83
84-- | Auxiliary typeclass used to define generic computations for both real and complex matrices. 84-- | Auxiliary typeclass used to define generic computations for both real and complex matrices.
85class (AutoReal t, Prod t, Linear Vector t, Linear Matrix t) => Field t where 85class (Product t, Linear Vector t, Linear Matrix t) => Field t where
86 svd' :: Matrix t -> (Matrix t, Vector Double, Matrix t) 86 svd' :: Matrix t -> (Matrix t, Vector Double, Matrix t)
87 thinSVD' :: Matrix t -> (Matrix t, Vector Double, Matrix t) 87 thinSVD' :: Matrix t -> (Matrix t, Vector Double, Matrix t)
88 sv' :: Matrix t -> Vector Double 88 sv' :: Matrix t -> Vector Double
@@ -172,6 +172,9 @@ thinSVD = {-# SCC "thinSVD" #-} thinSVD'
172singularValues :: Field t => Matrix t -> Vector Double 172singularValues :: Field t => Matrix t -> Vector Double
173singularValues = {-# SCC "singularValues" #-} sv' 173singularValues = {-# SCC "singularValues" #-} sv'
174 174
175instance (Field t, RealOf t ~ Double) => Norm2 Matrix t where
176 norm2 m = singularValues m @> 0
177
175-- | A version of 'svd' which returns an appropriate diagonal matrix with the singular values. 178-- | A version of 'svd' which returns an appropriate diagonal matrix with the singular values.
176-- 179--
177-- If @(u,d,v) = fullSVD m@ then @m == u \<> d \<> trans v@. 180-- If @(u,d,v) = fullSVD m@ then @m == u \<> d \<> trans v@.
@@ -379,80 +382,16 @@ ranksv teps maxdim s = k where
379eps :: Double 382eps :: Double
380eps = 2.22044604925031e-16 383eps = 2.22044604925031e-16
381 384
382peps :: RealFloat x => x -> x 385
383peps x = 2.0**(fromIntegral $ 1-floatDigits x) 386-- | 1 + 0.5*peps == 1, 1 + 0.6*peps /= 1
387peps :: RealFloat x => x
388peps = x where x = 2.0**(fromIntegral $ 1-floatDigits x)
384 389
385 390
386-- | The imaginary unit: @i = 0.0 :+ 1.0@ 391-- | The imaginary unit: @i = 0.0 :+ 1.0@
387i :: Complex Double 392i :: Complex Double
388i = 0:+1 393i = 0:+1
389 394
390---------------------------------------------------------------------------
391
392norm2 :: Vector Double -> Double
393norm2 = toScalarR Norm2
394
395norm1 :: Vector Double -> Double
396norm1 = toScalarR AbsSum
397
398data NormType = Infinity | PNorm1 | PNorm2 -- PNorm Int
399
400pnormRV PNorm2 = norm2
401pnormRV PNorm1 = norm1
402pnormRV Infinity = vectorMax . vectorMapR Abs
403--pnormRV _ = error "pnormRV not yet defined"
404
405pnormCV PNorm2 = norm2 . asReal
406pnormCV PNorm1 = norm1 . mapVector magnitude
407pnormCV Infinity = vectorMax . mapVector magnitude
408--pnormCV _ = error "pnormCV not yet defined"
409
410pnormRM PNorm2 m = singularValues m @> 0
411pnormRM PNorm1 m = vectorMax $ constant 1 (rows m) `vXm` liftMatrix (vectorMapR Abs) m
412pnormRM Infinity m = vectorMax $ liftMatrix (vectorMapR Abs) m `mXv` constant 1 (cols m)
413--pnormRM _ _ = error "p norm not yet defined"
414
415pnormCM PNorm2 m = singularValues m @> 0
416pnormCM PNorm1 m = vectorMax $ constant 1 (rows m) `vXm` liftMatrix (mapVector magnitude) m
417pnormCM Infinity m = vectorMax $ liftMatrix (mapVector magnitude) m `mXv` constant 1 (cols m)
418--pnormCM _ _ = error "p norm not yet defined"
419
420-- | Objects which have a p-norm.
421-- Using it you can define convenient shortcuts:
422--
423-- @norm2 x = pnorm PNorm2 x@
424--
425-- @frobenius m = norm2 . flatten $ m@
426class Normed t where
427 pnorm :: NormType -> t -> Double
428
429instance Normed (Vector Double) where
430 pnorm = pnormRV
431
432instance Normed (Vector (Complex Double)) where
433 pnorm = pnormCV
434
435instance Normed (Matrix Double) where
436 pnorm = pnormRM
437
438instance Normed (Matrix (Complex Double)) where
439 pnorm = pnormCM
440
441-----------------------------------------------------------------------
442-- to be optimized
443
444instance Normed (Vector Float) where
445 pnorm t = pnorm t . double
446
447instance Normed (Vector (Complex Float)) where
448 pnorm t = pnorm t . double
449
450instance Normed (Matrix Float) where
451 pnorm t = pnorm t . double
452
453instance Normed (Matrix (Complex Float)) where
454 pnorm t = pnorm t . double
455
456----------------------------------------------------------------------- 395-----------------------------------------------------------------------
457 396
458-- | The nullspace of a matrix from its SVD decomposition. 397-- | The nullspace of a matrix from its SVD decomposition.
@@ -588,8 +527,8 @@ diagonalize m = if rank v == n
588-- 527--
589-- @logm = matFunc log@ 528-- @logm = matFunc log@
590-- 529--
591matFunc :: (Field t) => (Complex Double -> Complex Double) -> Matrix t -> Matrix (Complex Double) 530matFunc :: (Complex Double -> Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)
592matFunc f m = case diagonalize (complex'' m) of 531matFunc f m = case diagonalize m of
593 Just (l,v) -> v `mXm` diag (mapVector f l) `mXm` inv v 532 Just (l,v) -> v `mXm` diag (mapVector f l) `mXm` inv v
594 Nothing -> error "Sorry, matFunc requires a diagonalizable matrix" 533 Nothing -> error "Sorry, matFunc requires a diagonalizable matrix"
595 534
@@ -607,7 +546,7 @@ epslist = [ (fromIntegral k, golubeps k k) | k <- [1..]]
607geps delta = head [ k | (k,g) <- epslist, g<delta] 546geps delta = head [ k | (k,g) <- epslist, g<delta]
608 547
609expGolub m = iterate msq f !! j 548expGolub m = iterate msq f !! j
610 where j = max 0 $ floor $ log2 $ pnorm Infinity m 549 where j = max 0 $ floor $ log2 $ normInf m
611 log2 x = log x / log 2 550 log2 x = log x / log 2
612 a = m */ fromIntegral ((2::Int)^j) 551 a = m */ fromIntegral ((2::Int)^j)
613 q = geps eps -- 7 steps 552 q = geps eps -- 7 steps
@@ -630,7 +569,7 @@ expGolub m = iterate msq f !! j
630{- | Matrix exponential. It uses a direct translation of Algorithm 11.3.1 in Golub & Van Loan, 569{- | Matrix exponential. It uses a direct translation of Algorithm 11.3.1 in Golub & Van Loan,
631 based on a scaled Pade approximation. 570 based on a scaled Pade approximation.
632-} 571-}
633expm :: (Normed (Matrix t), Field t) => Matrix t -> Matrix t 572expm :: (Norm Vector t, Field t) => Matrix t -> Matrix t
634expm = expGolub 573expm = expGolub
635 574
636-------------------------------------------------------------- 575--------------------------------------------------------------
@@ -646,11 +585,11 @@ It only works with invertible matrices that have a real solution. For diagonaliz
646 [ 2.0, 2.25 585 [ 2.0, 2.25
647 , 0.0, 2.0 ]@ 586 , 0.0, 2.0 ]@
648-} 587-}
649sqrtm :: (Normed (Matrix t), Field t) => Matrix t -> Matrix t 588sqrtm :: (Norm Vector t, Field t) => Matrix t -> Matrix t
650sqrtm = sqrtmInv 589sqrtm = sqrtmInv
651 590
652sqrtmInv x = fst $ fixedPoint $ iterate f (x, ident (rows x)) 591sqrtmInv x = fst $ fixedPoint $ iterate f (x, ident (rows x))
653 where fixedPoint (a:b:rest) | pnorm PNorm1 (fst a |-| fst b) < eps = a 592 where fixedPoint (a:b:rest) | norm1 (fst a |-| fst b) < peps = a
654 | otherwise = fixedPoint (b:rest) 593 | otherwise = fixedPoint (b:rest)
655 fixedPoint _ = error "fixedpoint with impossible inputs" 594 fixedPoint _ = error "fixedpoint with impossible inputs"
656 f (y,z) = (0.5 .* (y |+| inv z), 595 f (y,z) = (0.5 .* (y |+| inv z),
@@ -691,4 +630,35 @@ luFact (l_u,perm) | r <= c = (l ,u ,p, s)
691 (|+|) = add 630 (|+|) = add
692 (|*|) = mul 631 (|*|) = mul
693 632
694-------------------------------------------------- 633---------------------------------------------------------------------------
634
635data NormType = Infinity | PNorm1 | PNorm2
636
637-- | Old class
638class Normed t where
639 pnorm :: NormType -> t -> Double
640
641instance Norm Vector t => Normed (Vector t) where
642 pnorm PNorm1 = realToFrac . norm1
643 pnorm PNorm2 = realToFrac . normFrob
644 pnorm Infinity = realToFrac . normInf
645
646instance Normed (Matrix Double) where
647 pnorm PNorm1 = norm1
648 pnorm PNorm2 = norm2
649 pnorm Infinity = normInf
650
651instance Normed (Matrix (Complex Double)) where
652 pnorm PNorm1 = norm1
653 pnorm PNorm2 = norm2
654 pnorm Infinity = normInf
655
656instance Normed (Matrix Float) where
657 pnorm PNorm1 = realToFrac . norm1
658 pnorm PNorm2 = norm2 . double -- not yet optimized for Float
659 pnorm Infinity = realToFrac . normInf
660
661instance Normed (Matrix (Complex Float)) where
662 pnorm PNorm1 = realToFrac . norm1
663 pnorm PNorm2 = norm2 . double -- not yet optimized for Float
664 pnorm Infinity = realToFrac . normInf