diff options
Diffstat (limited to 'lib/LinearAlgebra/Algorithms.hs')
-rw-r--r-- | lib/LinearAlgebra/Algorithms.hs | 227 |
1 files changed, 226 insertions, 1 deletions
diff --git a/lib/LinearAlgebra/Algorithms.hs b/lib/LinearAlgebra/Algorithms.hs index 680612f..126549a 100644 --- a/lib/LinearAlgebra/Algorithms.hs +++ b/lib/LinearAlgebra/Algorithms.hs | |||
@@ -1,3 +1,4 @@ | |||
1 | {-# OPTIONS_GHC -fglasgow-exts #-} | ||
1 | ----------------------------------------------------------------------------- | 2 | ----------------------------------------------------------------------------- |
2 | {- | | 3 | {- | |
3 | Module : LinearAlgebra.Algorithms | 4 | Module : LinearAlgebra.Algorithms |
@@ -13,5 +14,229 @@ Portability : uses ffi | |||
13 | ----------------------------------------------------------------------------- | 14 | ----------------------------------------------------------------------------- |
14 | 15 | ||
15 | module LinearAlgebra.Algorithms ( | 16 | module LinearAlgebra.Algorithms ( |
16 | 17 | mXm, mXv, vXm, | |
18 | inv, | ||
19 | pinv, | ||
20 | pinvTol, | ||
21 | pinvTolg, | ||
22 | Normed(..), NormType(..), | ||
23 | det, | ||
24 | eps, i | ||
17 | ) where | 25 | ) where |
26 | |||
27 | |||
28 | import Data.Packed.Internal | ||
29 | import Data.Packed.Matrix | ||
30 | import GSL.Matrix | ||
31 | import GSL.Vector | ||
32 | import LAPACK | ||
33 | import Complex | ||
34 | |||
35 | {- | Machine precision of a Double. | ||
36 | |||
37 | >> eps | ||
38 | > 2.22044604925031e-16 | ||
39 | |||
40 | (The value used by GNU-Octave) | ||
41 | |||
42 | -} | ||
43 | eps :: Double | ||
44 | eps = 2.22044604925031e-16 | ||
45 | |||
46 | {- | The imaginary unit | ||
47 | |||
48 | @> 'ident' 3 \<\> i | ||
49 | 1.i 0. 0. | ||
50 | 0. 1.i 0. | ||
51 | 0. 0. 1.i@ | ||
52 | |||
53 | -} | ||
54 | i :: Complex Double | ||
55 | i = 0:+1 | ||
56 | |||
57 | |||
58 | -- | matrix product | ||
59 | mXm :: (Num t, Field t) => Matrix t -> Matrix t -> Matrix t | ||
60 | mXm = multiply RowMajor | ||
61 | |||
62 | -- | matrix - vector product | ||
63 | mXv :: (Num t, Field t) => Matrix t -> Vector t -> Vector t | ||
64 | mXv m v = flatten $ m `mXm` (asColumn v) | ||
65 | |||
66 | -- | vector - matrix product | ||
67 | vXm :: (Num t, Field t) => Vector t -> Matrix t -> Vector t | ||
68 | vXm v m = flatten $ (asRow v) `mXm` m | ||
69 | |||
70 | |||
71 | |||
72 | -- | Pseudoinverse of a real matrix | ||
73 | -- | ||
74 | -- @dispR 3 $ pinv (fromLists [[1,2], | ||
75 | -- [3,4], | ||
76 | -- [5,6]]) | ||
77 | --matrix (2x3) | ||
78 | -- -1.333 | -0.333 | 0.667 | ||
79 | -- 1.083 | 0.333 | -0.417@ | ||
80 | -- | ||
81 | |||
82 | pinv :: Matrix Double -> Matrix Double | ||
83 | pinv m = pinvTol 1 m | ||
84 | --pinv m = linearSolveSVDR Nothing m (ident (rows m)) | ||
85 | |||
86 | {- -| Pseudoinverse of a real matrix with the default tolerance used by GNU-Octave: the singular values less than max (rows, colums) * greatest singular value * 'eps' are ignored. See 'pinvTol'. | ||
87 | |||
88 | @\> let m = 'fromLists' [[ 1, 2] | ||
89 | ,[ 5, 8] | ||
90 | ,[10,-5]] | ||
91 | \> pinv m | ||
92 | 9.353e-3 4.539e-2 7.637e-2 | ||
93 | 2.231e-2 8.993e-2 -4.719e-2 | ||
94 | \ | ||
95 | \> m \<\> pinv m \<\> m | ||
96 | 1. 2. | ||
97 | 5. 8. | ||
98 | 10. -5.@ | ||
99 | |||
100 | -} | ||
101 | --pinvg :: Matrix Double -> Matrix Double | ||
102 | pinvg m = pinvTolg 1 m | ||
103 | |||
104 | {- | Pseudoinverse of a real matrix with the desired tolerance, expressed as a | ||
105 | multiplicative factor of the default tolerance used by GNU-Octave (see 'pinv'). | ||
106 | |||
107 | @\> let m = 'fromLists' [[1,0, 0] | ||
108 | ,[0,1, 0] | ||
109 | ,[0,0,1e-10]] | ||
110 | \ | ||
111 | \> 'pinv' m | ||
112 | 1. 0. 0. | ||
113 | 0. 1. 0. | ||
114 | 0. 0. 10000000000. | ||
115 | \ | ||
116 | \> pinvTol 1E8 m | ||
117 | 1. 0. 0. | ||
118 | 0. 1. 0. | ||
119 | 0. 0. 1.@ | ||
120 | |||
121 | -} | ||
122 | pinvTol :: Double -> Matrix Double -> Matrix Double | ||
123 | pinvTol t m = v' `mXm` diag s' `mXm` trans u' where | ||
124 | (u,s,v) = svdR' m | ||
125 | sl@(g:_) = toList s | ||
126 | s' = fromList . map rec $ sl | ||
127 | rec x = if x < g*tol then 1 else 1/x | ||
128 | tol = (fromIntegral (max (rows m) (cols m)) * g * t * eps) | ||
129 | r = rows m | ||
130 | c = cols m | ||
131 | d = dim s | ||
132 | u' = takeColumns d u | ||
133 | v' = takeColumns d v | ||
134 | |||
135 | |||
136 | pinvTolg :: Double -> Matrix Double -> Matrix Double | ||
137 | pinvTolg t m = v `mXm` diag s' `mXm` trans u where | ||
138 | (u,s,v) = svdg m | ||
139 | sl@(g:_) = toList s | ||
140 | s' = fromList . map rec $ sl | ||
141 | rec x = if x < g*tol then 1 else 1/x | ||
142 | tol = (fromIntegral (max (rows m) (cols m)) * g * t * eps) | ||
143 | |||
144 | |||
145 | |||
146 | {- | Inverse of a square matrix. | ||
147 | |||
148 | inv m = 'linearSolveR' m ('ident' ('rows' m)) | ||
149 | |||
150 | @\>inv ('fromLists' [[1,4] | ||
151 | ,[0,2]]) | ||
152 | 1. -2. | ||
153 | 0. 0.500@ | ||
154 | -} | ||
155 | inv :: Matrix Double -> Matrix Double | ||
156 | inv m = if rows m == cols m | ||
157 | then m `linearSolveR` ident (rows m) | ||
158 | else error "inv of nonsquare matrix" | ||
159 | |||
160 | |||
161 | {- - | Shortcut for the 2-norm ('pnorm' 2) | ||
162 | |||
163 | @ > norm $ 'hilb' 5 | ||
164 | 1.5670506910982311 | ||
165 | @ | ||
166 | |||
167 | @\> norm $ 'fromList' [1,-1,'i',-'i'] | ||
168 | 2.0@ | ||
169 | |||
170 | -} | ||
171 | |||
172 | |||
173 | |||
174 | {- | Determinant of a square matrix, computed from the LU decomposition. | ||
175 | |||
176 | @\> det ('fromLists' [[7,2],[3,8]]) | ||
177 | 50.0@ | ||
178 | |||
179 | -} | ||
180 | det :: Matrix Double -> Double | ||
181 | det m = s * (product $ toList $ takeDiag $ u) | ||
182 | where (_,u,_,s) = luR m | ||
183 | |||
184 | --------------------------------------------------------------------------- | ||
185 | |||
186 | norm2 :: Vector Double -> Double | ||
187 | norm2 = toScalarR Norm2 | ||
188 | |||
189 | norm1 :: Vector Double -> Double | ||
190 | norm1 = toScalarR AbsSum | ||
191 | |||
192 | vectorMax :: Vector Double -> Double | ||
193 | vectorMax = toScalarR Max | ||
194 | vectorMin :: Vector Double -> Double | ||
195 | vectorMin = toScalarR Min | ||
196 | vectorMaxIndex :: Vector Double -> Int | ||
197 | vectorMaxIndex = round . toScalarR MaxIdx | ||
198 | vectorMinIndex :: Vector Double -> Int | ||
199 | vectorMinIndex = round . toScalarR MinIdx | ||
200 | |||
201 | data NormType = Infinity | PNorm1 | PNorm2 -- PNorm Int | ||
202 | |||
203 | pnormRV PNorm2 = norm2 | ||
204 | pnormRV PNorm1 = norm1 | ||
205 | pnormRV Infinity = vectorMax . vectorMapR Abs | ||
206 | --pnormRV _ = error "pnormRV not yet defined" | ||
207 | |||
208 | pnormCV PNorm2 = norm2 . asReal | ||
209 | pnormCV PNorm1 = norm1 . liftVector magnitude | ||
210 | pnormCV Infinity = vectorMax . liftVector magnitude | ||
211 | --pnormCV _ = error "pnormCV not yet defined" | ||
212 | |||
213 | pnormRM PNorm2 m = head (toList s) where (_,s,_) = svdR' m | ||
214 | pnormRM PNorm1 m = vectorMax $ constant 1 (rows m) `vXm` liftMatrix (vectorMapR Abs) m | ||
215 | pnormRM Infinity m = vectorMax $ liftMatrix (vectorMapR Abs) m `mXv` constant 1 (cols m) | ||
216 | --pnormRM _ _ = error "p norm not yet defined" | ||
217 | |||
218 | pnormCM PNorm2 m = head (toList s) where (_,s,_) = svdC' m | ||
219 | pnormCM PNorm1 m = vectorMax $ constant 1 (rows m) `vXm` liftMatrix (liftVector magnitude) m | ||
220 | pnormCM Infinity m = vectorMax $ liftMatrix (liftVector magnitude) m `mXv` constant 1 (cols m) | ||
221 | --pnormCM _ _ = error "p norm not yet defined" | ||
222 | |||
223 | -- -- | computes the p-norm of a matrix or vector (with the same definitions as GNU-octave). pnorm 0 denotes \\inf-norm. See also 'norm'. | ||
224 | --pnorm :: (Container t, Field a) => Int -> t a -> Double | ||
225 | --pnorm = pnormG | ||
226 | |||
227 | class Normed t where | ||
228 | pnorm :: NormType -> t -> Double | ||
229 | norm :: t -> Double | ||
230 | norm = pnorm PNorm2 | ||
231 | |||
232 | instance Normed (Vector Double) where | ||
233 | pnorm = pnormRV | ||
234 | |||
235 | instance Normed (Vector (Complex Double)) where | ||
236 | pnorm = pnormCV | ||
237 | |||
238 | instance Normed (Matrix Double) where | ||
239 | pnorm = pnormRM | ||
240 | |||
241 | instance Normed (Matrix (Complex Double)) where | ||
242 | pnorm = pnormCM | ||