diff options
Diffstat (limited to 'lib/LinearAlgebra/Algorithms.hs')
-rw-r--r-- | lib/LinearAlgebra/Algorithms.hs | 125 |
1 files changed, 55 insertions, 70 deletions
diff --git a/lib/LinearAlgebra/Algorithms.hs b/lib/LinearAlgebra/Algorithms.hs index 162426f..a67f822 100644 --- a/lib/LinearAlgebra/Algorithms.hs +++ b/lib/LinearAlgebra/Algorithms.hs | |||
@@ -9,106 +9,114 @@ Maintainer : Alberto Ruiz (aruiz at um dot es) | |||
9 | Stability : provisional | 9 | Stability : provisional |
10 | Portability : uses ffi | 10 | Portability : uses ffi |
11 | 11 | ||
12 | A simple interface to the available matrix computations. We have defined some generic functions | 12 | A generic interface for a number of essential functions. Using it some higher level algorithms |
13 | on both real and complex matrices in such a way that higher level algorithms and | 13 | and testing properties can be written for both real and complex matrices. |
14 | testing properties are valid for both base types. | ||
15 | 14 | ||
16 | In any case the specific functions for particular base types can also be explicitly | 15 | In any case, the specific functions for particular base types can also be explicitly |
17 | imported from the LAPACK and GSL.Matrix modules. | 16 | imported from the LAPACK and GSL.Matrix modules. |
18 | 17 | ||
19 | -} | 18 | -} |
20 | ----------------------------------------------------------------------------- | 19 | ----------------------------------------------------------------------------- |
21 | 20 | ||
22 | module LinearAlgebra.Algorithms ( | 21 | module LinearAlgebra.Algorithms ( |
23 | -- * Basic Linear Algebra | 22 | -- * Linear Systems |
24 | scale, | 23 | linearSolve, |
25 | add, | 24 | inv, pinv, |
26 | multiply, dot, outer, | 25 | pinvTol, det, |
27 | linearSolve, linearSolveSVD, | ||
28 | -- * Matrix factorizations | 26 | -- * Matrix factorizations |
29 | svd, lu, eig, eigSH, | 27 | -- ** Singular value decomposition |
30 | qr, chol, | 28 | svd, |
31 | -- * Utilities | 29 | full, economy, |
32 | Normed(..), NormType(..), | 30 | -- ** Eigensystems |
33 | det,inv,pinv,full,economy, | 31 | eig, LinearAlgebra.Algorithms.eigS, LinearAlgebra.Algorithms.eigH, |
34 | pinvTol, | 32 | -- ** Other |
35 | -- pinvTolg, | 33 | LinearAlgebra.Algorithms.qr, chol, |
34 | -- * Nullspace | ||
36 | nullspacePrec, | 35 | nullspacePrec, |
37 | nullVector, | 36 | nullVector, |
38 | -- * Conversions | ||
39 | toComplex, fromComplex, | ||
40 | comp, real, complex, | ||
41 | conj, ctrans, | ||
42 | -- * Misc | 37 | -- * Misc |
43 | eps, i, | 38 | eps, i, |
44 | scaleRecip, | 39 | ctrans, |
45 | addConstant, | 40 | Normed(..), NormType(..), |
46 | sub, | 41 | GenMat(linearSolveSVD,lu,eigSH) |
47 | mul, | ||
48 | divide, | ||
49 | ) where | 42 | ) where |
50 | 43 | ||
51 | 44 | ||
52 | import Data.Packed.Internal hiding (fromComplex, toComplex, comp, conj) | 45 | import Data.Packed.Internal hiding (fromComplex, toComplex, comp, conj) |
53 | import Data.Packed.Matrix | 46 | import Data.Packed |
54 | import GSL.Matrix | 47 | import GSL.Matrix |
55 | import GSL.Vector | 48 | import GSL.Vector |
56 | import LAPACK | 49 | import LAPACK |
57 | import Complex | 50 | import Complex |
58 | import LinearAlgebra.Linear | 51 | import LinearAlgebra.Linear |
59 | 52 | ||
60 | -- | Base types for which some optimized matrix computations are available | 53 | -- | matrix computations available for both real and complex matrices |
61 | class (Linear Matrix t) => Optimized t where | 54 | class (Linear Matrix t) => GenMat t where |
62 | svd :: Matrix t -> (Matrix t, Vector Double, Matrix t) | 55 | svd :: Matrix t -> (Matrix t, Vector Double, Matrix t) |
63 | lu :: Matrix t -> (Matrix t, Matrix t, [Int], t) | 56 | lu :: Matrix t -> (Matrix t, Matrix t, [Int], t) |
64 | linearSolve :: Matrix t -> Matrix t -> Matrix t | 57 | linearSolve :: Matrix t -> Matrix t -> Matrix t |
65 | linearSolveSVD :: Matrix t -> Matrix t -> Matrix t | 58 | linearSolveSVD :: Matrix t -> Matrix t -> Matrix t |
66 | ctrans :: Matrix t -> Matrix t | ||
67 | eig :: Matrix t -> (Vector (Complex Double), Matrix (Complex Double)) | 59 | eig :: Matrix t -> (Vector (Complex Double), Matrix (Complex Double)) |
68 | eigSH :: Matrix t -> (Vector Double, Matrix t) | 60 | eigSH :: Matrix t -> (Vector Double, Matrix t) |
69 | chol :: Matrix t -> Matrix t | 61 | chol :: Matrix t -> Matrix t |
62 | -- | conjugate transpose | ||
63 | ctrans :: Matrix t -> Matrix t | ||
70 | 64 | ||
71 | instance Optimized Double where | 65 | instance GenMat Double where |
72 | svd = svdR | 66 | svd = svdR |
73 | lu = luR | 67 | lu = luR |
74 | linearSolve = linearSolveR | 68 | linearSolve = linearSolveR |
75 | linearSolveSVD = linearSolveSVDR Nothing | 69 | linearSolveSVD = linearSolveSVDR Nothing |
76 | ctrans = trans | 70 | ctrans = trans |
77 | eig = eigR | 71 | eig = eigR |
78 | eigSH = eigS | 72 | eigSH = LAPACK.eigS |
79 | chol = cholR | 73 | chol = cholR |
80 | 74 | ||
81 | instance Optimized (Complex Double) where | 75 | instance GenMat (Complex Double) where |
82 | svd = svdC | 76 | svd = svdC |
83 | lu = luC | 77 | lu = luC |
84 | linearSolve = linearSolveC | 78 | linearSolve = linearSolveC |
85 | linearSolveSVD = linearSolveSVDC Nothing | 79 | linearSolveSVD = linearSolveSVDC Nothing |
86 | ctrans = conjTrans | 80 | ctrans = conjTrans |
87 | eig = eigC | 81 | eig = eigC |
88 | eigSH = eigH | 82 | eigSH = LAPACK.eigH |
89 | chol = error "cholC not yet implemented" -- waiting for GSL-1.10 | 83 | chol = error "cholC not yet implemented" -- waiting for GSL-1.10 |
90 | 84 | ||
85 | -- | eigensystem of a symmetric matrix | ||
86 | eigS :: Matrix Double -> (Vector Double, Matrix Double) | ||
87 | eigS = LAPACK.eigS | ||
88 | |||
89 | -- | eigensystem of a hermitian matrix | ||
90 | eigH :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double)) | ||
91 | eigH = LAPACK.eigH | ||
92 | |||
93 | qr :: Matrix Double -> (Matrix Double, Matrix Double) | ||
94 | qr = GSL.Matrix.qr | ||
95 | |||
91 | square m = rows m == cols m | 96 | square m = rows m == cols m |
92 | 97 | ||
93 | det :: Optimized t => Matrix t -> t | 98 | det :: GenMat t => Matrix t -> t |
94 | det m | square m = s * (product $ toList $ takeDiag $ u) | 99 | det m | square m = s * (product $ toList $ takeDiag $ u) |
95 | | otherwise = error "det of nonsquare matrix" | 100 | | otherwise = error "det of nonsquare matrix" |
96 | where (_,u,_,s) = lu m | 101 | where (_,u,_,s) = lu m |
97 | 102 | ||
98 | inv :: Optimized t => Matrix t -> Matrix t | 103 | inv :: GenMat t => Matrix t -> Matrix t |
99 | inv m | square m = m `linearSolve` ident (rows m) | 104 | inv m | square m = m `linearSolve` ident (rows m) |
100 | | otherwise = error "inv of nonsquare matrix" | 105 | | otherwise = error "inv of nonsquare matrix" |
101 | 106 | ||
102 | pinv :: Optimized t => Matrix t -> Matrix t | 107 | pinv :: GenMat t => Matrix t -> Matrix t |
103 | pinv m = linearSolveSVD m (ident (rows m)) | 108 | pinv m = linearSolveSVD m (ident (rows m)) |
104 | 109 | ||
105 | 110 | full :: Field t | |
111 | => (Matrix t -> (Matrix t, Vector Double, Matrix t)) -> Matrix t -> (Matrix t, Matrix Double, Matrix t) | ||
106 | full svd m = (u, d ,v) where | 112 | full svd m = (u, d ,v) where |
107 | (u,s,v) = svd m | 113 | (u,s,v) = svd m |
108 | d = diagRect s r c | 114 | d = diagRect s r c |
109 | r = rows m | 115 | r = rows m |
110 | c = cols m | 116 | c = cols m |
111 | 117 | ||
118 | economy :: Field t | ||
119 | => (Matrix t -> (Matrix t, Vector Double, Matrix t)) -> Matrix t -> (Matrix t, Vector Double, Matrix t) | ||
112 | economy svd m = (u', subVector 0 d s, v') where | 120 | economy svd m = (u', subVector 0 d s, v') where |
113 | (u,s,v) = svd m | 121 | (u,s,v) = svd m |
114 | sl@(g:_) = toList (complex s) | 122 | sl@(g:_) = toList (complex s) |
@@ -123,39 +131,25 @@ economy svd m = (u', subVector 0 d s, v') where | |||
123 | v' = takeColumns d v | 131 | v' = takeColumns d v |
124 | 132 | ||
125 | 133 | ||
126 | {- | Machine precision of a Double. | 134 | -- | The machine precision of a Double: @eps == 2.22044604925031e-16@ (the value used by GNU-Octave). |
127 | |||
128 | >> eps | ||
129 | > 2.22044604925031e-16 | ||
130 | |||
131 | (The value used by GNU-Octave) | ||
132 | |||
133 | -} | ||
134 | eps :: Double | 135 | eps :: Double |
135 | eps = 2.22044604925031e-16 | 136 | eps = 2.22044604925031e-16 |
136 | 137 | ||
137 | {- | The imaginary unit | 138 | -- | The imaginary unit: @i == 0.0 :+ 1.0@ |
138 | |||
139 | @> 'ident' 3 \<\> i | ||
140 | 1.i 0. 0. | ||
141 | 0. 1.i 0. | ||
142 | 0. 0. 1.i@ | ||
143 | |||
144 | -} | ||
145 | i :: Complex Double | 139 | i :: Complex Double |
146 | i = 0:+1 | 140 | i = 0:+1 |
147 | 141 | ||
148 | 142 | ||
149 | -- | matrix product | 143 | -- | matrix product |
150 | mXm :: (Num t, Optimized t) => Matrix t -> Matrix t -> Matrix t | 144 | mXm :: (Num t, GenMat t) => Matrix t -> Matrix t -> Matrix t |
151 | mXm = multiply | 145 | mXm = multiply |
152 | 146 | ||
153 | -- | matrix - vector product | 147 | -- | matrix - vector product |
154 | mXv :: (Num t, Optimized t) => Matrix t -> Vector t -> Vector t | 148 | mXv :: (Num t, GenMat t) => Matrix t -> Vector t -> Vector t |
155 | mXv m v = flatten $ m `mXm` (asColumn v) | 149 | mXv m v = flatten $ m `mXm` (asColumn v) |
156 | 150 | ||
157 | -- | vector - matrix product | 151 | -- | vector - matrix product |
158 | vXm :: (Num t, Optimized t) => Vector t -> Matrix t -> Vector t | 152 | vXm :: (Num t, GenMat t) => Vector t -> Matrix t -> Vector t |
159 | vXm v m = flatten $ (asRow v) `mXm` m | 153 | vXm v m = flatten $ (asRow v) `mXm` m |
160 | 154 | ||
161 | 155 | ||
@@ -167,15 +161,6 @@ norm2 = toScalarR Norm2 | |||
167 | norm1 :: Vector Double -> Double | 161 | norm1 :: Vector Double -> Double |
168 | norm1 = toScalarR AbsSum | 162 | norm1 = toScalarR AbsSum |
169 | 163 | ||
170 | vectorMax :: Vector Double -> Double | ||
171 | vectorMax = toScalarR Max | ||
172 | vectorMin :: Vector Double -> Double | ||
173 | vectorMin = toScalarR Min | ||
174 | vectorMaxIndex :: Vector Double -> Int | ||
175 | vectorMaxIndex = round . toScalarR MaxIdx | ||
176 | vectorMinIndex :: Vector Double -> Int | ||
177 | vectorMinIndex = round . toScalarR MinIdx | ||
178 | |||
179 | data NormType = Infinity | PNorm1 | PNorm2 -- PNorm Int | 164 | data NormType = Infinity | PNorm1 | PNorm2 -- PNorm Int |
180 | 165 | ||
181 | pnormRV PNorm2 = norm2 | 166 | pnormRV PNorm2 = norm2 |
@@ -199,7 +184,7 @@ pnormCM Infinity m = vectorMax $ liftMatrix (liftVector magnitude) m `mXv` const | |||
199 | --pnormCM _ _ = error "p norm not yet defined" | 184 | --pnormCM _ _ = error "p norm not yet defined" |
200 | 185 | ||
201 | -- -- | computes the p-norm of a matrix or vector (with the same definitions as GNU-octave). pnorm 0 denotes \\inf-norm. See also 'norm'. | 186 | -- -- | computes the p-norm of a matrix or vector (with the same definitions as GNU-octave). pnorm 0 denotes \\inf-norm. See also 'norm'. |
202 | --pnorm :: (Container t, Optimized a) => Int -> t a -> Double | 187 | --pnorm :: (Container t, GenMat a) => Int -> t a -> Double |
203 | --pnorm = pnormG | 188 | --pnorm = pnormG |
204 | 189 | ||
205 | class Normed t where | 190 | class Normed t where |
@@ -222,7 +207,7 @@ instance Normed (Matrix (Complex Double)) where | |||
222 | ----------------------------------------------------------------------- | 207 | ----------------------------------------------------------------------- |
223 | 208 | ||
224 | -- | The nullspace of a matrix from its SVD decomposition. | 209 | -- | The nullspace of a matrix from its SVD decomposition. |
225 | nullspacePrec :: Optimized t | 210 | nullspacePrec :: GenMat t |
226 | => Double -- ^ relative tolerance in 'eps' units | 211 | => Double -- ^ relative tolerance in 'eps' units |
227 | -> Matrix t -- ^ input matrix | 212 | -> Matrix t -- ^ input matrix |
228 | -> [Vector t] -- ^ list of unitary vectors spanning the nullspace | 213 | -> [Vector t] -- ^ list of unitary vectors spanning the nullspace |
@@ -235,12 +220,12 @@ nullspacePrec t m = ns where | |||
235 | ns = drop rank $ toRows $ ctrans v | 220 | ns = drop rank $ toRows $ ctrans v |
236 | 221 | ||
237 | -- | The nullspace of a matrix, assumed to be one-dimensional, with default tolerance (shortcut for @last . nullspacePrec 1@). | 222 | -- | The nullspace of a matrix, assumed to be one-dimensional, with default tolerance (shortcut for @last . nullspacePrec 1@). |
238 | nullVector :: Optimized t => Matrix t -> Vector t | 223 | nullVector :: GenMat t => Matrix t -> Vector t |
239 | nullVector = last . nullspacePrec 1 | 224 | nullVector = last . nullspacePrec 1 |
240 | 225 | ||
241 | ------------------------------------------------------------------------ | 226 | ------------------------------------------------------------------------ |
242 | 227 | ||
243 | {- | Pseudoinverse of a real matrix with the desired tolerance, expressed as a | 228 | {- Pseudoinverse of a real matrix with the desired tolerance, expressed as a |
244 | multiplicative factor of the default tolerance used by GNU-Octave (see 'pinv'). | 229 | multiplicative factor of the default tolerance used by GNU-Octave (see 'pinv'). |
245 | 230 | ||
246 | @\> let m = 'fromLists' [[1,0, 0] | 231 | @\> let m = 'fromLists' [[1,0, 0] |
@@ -258,7 +243,7 @@ multiplicative factor of the default tolerance used by GNU-Octave (see 'pinv'). | |||
258 | 0. 0. 1.@ | 243 | 0. 0. 1.@ |
259 | 244 | ||
260 | -} | 245 | -} |
261 | pinvTol :: Double -> Matrix Double -> Matrix Double | 246 | --pinvTol :: Double -> Matrix Double -> Matrix Double |
262 | pinvTol t m = v' `mXm` diag s' `mXm` trans u' where | 247 | pinvTol t m = v' `mXm` diag s' `mXm` trans u' where |
263 | (u,s,v) = svdR m | 248 | (u,s,v) = svdR m |
264 | sl@(g:_) = toList s | 249 | sl@(g:_) = toList s |