summaryrefslogtreecommitdiff
path: root/lib/LinearAlgebra/Algorithms.hs
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2007-06-25 07:32:56 +0000
committerAlberto Ruiz <aruiz@um.es>2007-06-25 07:32:56 +0000
commit1871acb835b4fc164bcff3f6e7467884b87fbd0f (patch)
treeac1028d40778bbae532c3915276b5af21ba5f5cb /lib/LinearAlgebra/Algorithms.hs
parent3d5d6f06598aac00906c93ac5358e68697c47fc7 (diff)
l.a. algorithms, etc.
Diffstat (limited to 'lib/LinearAlgebra/Algorithms.hs')
-rw-r--r--lib/LinearAlgebra/Algorithms.hs227
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{- |
3Module : LinearAlgebra.Algorithms 4Module : LinearAlgebra.Algorithms
@@ -13,5 +14,229 @@ Portability : uses ffi
13----------------------------------------------------------------------------- 14-----------------------------------------------------------------------------
14 15
15module LinearAlgebra.Algorithms ( 16module 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
28import Data.Packed.Internal
29import Data.Packed.Matrix
30import GSL.Matrix
31import GSL.Vector
32import LAPACK
33import 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-}
43eps :: Double
44eps = 2.22044604925031e-16
45
46{- | The imaginary unit
47
48@> 'ident' 3 \<\> i
491.i 0. 0.
50 0. 1.i 0.
51 0. 0. 1.i@
52
53-}
54i :: Complex Double
55i = 0:+1
56
57
58-- | matrix product
59mXm :: (Num t, Field t) => Matrix t -> Matrix t -> Matrix t
60mXm = multiply RowMajor
61
62-- | matrix - vector product
63mXv :: (Num t, Field t) => Matrix t -> Vector t -> Vector t
64mXv m v = flatten $ m `mXm` (asColumn v)
65
66-- | vector - matrix product
67vXm :: (Num t, Field t) => Vector t -> Matrix t -> Vector t
68vXm 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
82pinv :: Matrix Double -> Matrix Double
83pinv 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
929.353e-3 4.539e-2 7.637e-2
932.231e-2 8.993e-2 -4.719e-2
94\
95\> m \<\> pinv m \<\> m
96 1. 2.
97 5. 8.
9810. -5.@
99
100-}
101--pinvg :: Matrix Double -> Matrix Double
102pinvg m = pinvTolg 1 m
103
104{- | Pseudoinverse of a real matrix with the desired tolerance, expressed as a
105multiplicative 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
1121. 0. 0.
1130. 1. 0.
1140. 0. 10000000000.
115\
116\> pinvTol 1E8 m
1171. 0. 0.
1180. 1. 0.
1190. 0. 1.@
120
121-}
122pinvTol :: Double -> Matrix Double -> Matrix Double
123pinvTol 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
136pinvTolg :: Double -> Matrix Double -> Matrix Double
137pinvTolg 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
148inv m = 'linearSolveR' m ('ident' ('rows' m))
149
150@\>inv ('fromLists' [[1,4]
151 ,[0,2]])
1521. -2.
1530. 0.500@
154-}
155inv :: Matrix Double -> Matrix Double
156inv 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
1641.5670506910982311
165@
166
167@\> norm $ 'fromList' [1,-1,'i',-'i']
1682.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]])
17750.0@
178
179-}
180det :: Matrix Double -> Double
181det m = s * (product $ toList $ takeDiag $ u)
182 where (_,u,_,s) = luR m
183
184---------------------------------------------------------------------------
185
186norm2 :: Vector Double -> Double
187norm2 = toScalarR Norm2
188
189norm1 :: Vector Double -> Double
190norm1 = toScalarR AbsSum
191
192vectorMax :: Vector Double -> Double
193vectorMax = toScalarR Max
194vectorMin :: Vector Double -> Double
195vectorMin = toScalarR Min
196vectorMaxIndex :: Vector Double -> Int
197vectorMaxIndex = round . toScalarR MaxIdx
198vectorMinIndex :: Vector Double -> Int
199vectorMinIndex = round . toScalarR MinIdx
200
201data NormType = Infinity | PNorm1 | PNorm2 -- PNorm Int
202
203pnormRV PNorm2 = norm2
204pnormRV PNorm1 = norm1
205pnormRV Infinity = vectorMax . vectorMapR Abs
206--pnormRV _ = error "pnormRV not yet defined"
207
208pnormCV PNorm2 = norm2 . asReal
209pnormCV PNorm1 = norm1 . liftVector magnitude
210pnormCV Infinity = vectorMax . liftVector magnitude
211--pnormCV _ = error "pnormCV not yet defined"
212
213pnormRM PNorm2 m = head (toList s) where (_,s,_) = svdR' m
214pnormRM PNorm1 m = vectorMax $ constant 1 (rows m) `vXm` liftMatrix (vectorMapR Abs) m
215pnormRM Infinity m = vectorMax $ liftMatrix (vectorMapR Abs) m `mXv` constant 1 (cols m)
216--pnormRM _ _ = error "p norm not yet defined"
217
218pnormCM PNorm2 m = head (toList s) where (_,s,_) = svdC' m
219pnormCM PNorm1 m = vectorMax $ constant 1 (rows m) `vXm` liftMatrix (liftVector magnitude) m
220pnormCM 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
227class Normed t where
228 pnorm :: NormType -> t -> Double
229 norm :: t -> Double
230 norm = pnorm PNorm2
231
232instance Normed (Vector Double) where
233 pnorm = pnormRV
234
235instance Normed (Vector (Complex Double)) where
236 pnorm = pnormCV
237
238instance Normed (Matrix Double) where
239 pnorm = pnormRM
240
241instance Normed (Matrix (Complex Double)) where
242 pnorm = pnormCM