summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2007-06-16 15:52:07 +0000
committerAlberto Ruiz <aruiz@um.es>2007-06-16 15:52:07 +0000
commitb2af660f87a55dd15f4519b21e66837ec811dc25 (patch)
treef48a2dc5b1d996595e7cd69fbbff6397d3e7b600
parentcc2c8c39dc088dcace0d2749cfe9180bf5fdbfd2 (diff)
Fourier, minimization, polySolve
-rw-r--r--HSSL.cabal8
-rw-r--r--examples/tests.hs33
-rw-r--r--lib/Data/Packed/Internal/Matrix.hs8
-rw-r--r--lib/Data/Packed/Matrix.hs23
-rw-r--r--lib/GSL/Fourier.hs46
-rw-r--r--lib/GSL/Minimization.hs211
-rw-r--r--lib/GSL/Polynomials.hs54
7 files changed, 377 insertions, 6 deletions
diff --git a/HSSL.cabal b/HSSL.cabal
index 21d98fe..2bd30bc 100644
--- a/HSSL.cabal
+++ b/HSSL.cabal
@@ -24,9 +24,11 @@ Exposed-modules: Data.Packed.Internal, Data.Packed.Internal.Common,
24 Data.Packed.Internal.Tensor, 24 Data.Packed.Internal.Tensor,
25 LAPACK, 25 LAPACK,
26 GSL.Vector, 26 GSL.Vector,
27 GSL.Differentiation, 27 GSL.Differentiation, GSL.Integration,
28 GSL.Integration, 28 GSL.Special,
29 GSL.Special 29 GSL.Fourier,
30 GSL.Polynomials,
31 GSL.Minimization
30Other-modules: 32Other-modules:
31C-sources: lib/Data/Packed/Internal/aux.c, 33C-sources: lib/Data/Packed/Internal/aux.c,
32 lib/LAPACK/lapack-aux.c, 34 lib/LAPACK/lapack-aux.c,
diff --git a/examples/tests.hs b/examples/tests.hs
index 3b1d878..22c4674 100644
--- a/examples/tests.hs
+++ b/examples/tests.hs
@@ -12,11 +12,14 @@ import GSL.Vector
12import GSL.Integration 12import GSL.Integration
13import GSL.Differentiation 13import GSL.Differentiation
14import GSL.Special 14import GSL.Special
15import GSL.Fourier
16import GSL.Polynomials
15import LAPACK 17import LAPACK
16import Test.QuickCheck 18import Test.QuickCheck
17import Test.HUnit 19import Test.HUnit
18import Complex 20import Complex
19 21
22
20{- 23{-
21-- Bravo por quickCheck! 24-- Bravo por quickCheck!
22 25
@@ -244,6 +247,29 @@ pinvSVDR m = linearSolveSVDR Nothing m (ident (rows m))
244 247
245pinvSVDC m = linearSolveSVDC Nothing m (ident (rows m)) 248pinvSVDC m = linearSolveSVDC Nothing m (ident (rows m))
246 249
250--------------------------------------------------------------------
251
252polyEval cs x = foldr (\c ac->ac*x+c) 0 cs
253
254polySolveTest' p = length p <2 || last p == 0|| 1E-8 > maximum (map magnitude $ map (polyEval (map (:+0) p)) (polySolve p))
255 where l1 |~~| l2 = eps > aproxL magnitude l1 l2
256
257polySolveTest = assertBool "polySolve" (polySolveTest' [1,2,3,4])
258
259---------------------------------------------------------------------
260
261quad f a b = fst $ integrateQAGS 1E-9 100 f a b
262
263-- A multiple integral can be easily defined using partial application
264quad2 f a b g1 g2 = quad h a b
265 where h x = quad (f x) (g1 x) (g2 x)
266
267volSphere r = 8 * quad2 (\x y -> sqrt (r*r-x*x-y*y))
268 0 r (const 0) (\x->sqrt (r*r-x*x))
269
270integrateTest = assertBool "integrate" (abs (volSphere 2.5 - 4/3*pi*2.5^3) < eps)
271
272
247--------------------------------------------------------------------- 273---------------------------------------------------------------------
248 274
249arit1 u = vectorMapValR PowVS 2 (vectorMapR Sin u) 275arit1 u = vectorMapValR PowVS 2 (vectorMapR Sin u)
@@ -271,6 +297,8 @@ exponentialTest = do
271tests = TestList 297tests = TestList
272 [ TestCase $ besselTest 298 [ TestCase $ besselTest
273 , TestCase $ exponentialTest 299 , TestCase $ exponentialTest
300 , TestCase $ polySolveTest
301 , TestCase $ integrateTest
274 ] 302 ]
275 303
276---------------------------------------------------------------------- 304----------------------------------------------------------------------
@@ -315,9 +343,12 @@ main = do
315 quickCheck arit2 343 quickCheck arit2
316 putStrLn "--------- GSL ------" 344 putStrLn "--------- GSL ------"
317 runTestTT tests 345 runTestTT tests
346 quickCheck $ \v -> ifft (fft v) ~~ v
318 347
319kk = (2><2) 348kk = (2><2)
320 [ 1.0, 0.0 349 [ 1.0, 0.0
321 , -1.5, 1.0 ::Double] 350 , -1.5, 1.0 ::Double]
322 351
323v = 11 # [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0::Double] \ No newline at end of file 352v = 11 # [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0::Double]
353
354pol = [14.125,-7.666666666666667,-14.3,-13.0,-7.0,-9.6,4.666666666666666,13.0,0.5] \ No newline at end of file
diff --git a/lib/Data/Packed/Internal/Matrix.hs b/lib/Data/Packed/Internal/Matrix.hs
index 2c0acdf..fccf8bb 100644
--- a/lib/Data/Packed/Internal/Matrix.hs
+++ b/lib/Data/Packed/Internal/Matrix.hs
@@ -281,3 +281,11 @@ fromColumns m = trans . fromRows $ m
281-- | Creates a list of vectors from the columns of a matrix 281-- | Creates a list of vectors from the columns of a matrix
282toColumns :: Field t => Matrix t -> [Vector t] 282toColumns :: Field t => Matrix t -> [Vector t]
283toColumns m = toRows . trans $ m 283toColumns m = toRows . trans $ m
284
285
286-- | Reads a matrix position.
287(@@>) :: Field t => Matrix t -> (Int,Int) -> t
288infixl 9 @@>
289m@M {rows = r, cols = c} @@> (i,j)
290 | i<0 || i>=r || j<0 || j>=c = error "matrix indexing out of range"
291 | otherwise = cdat m `at` (i*c+j)
diff --git a/lib/Data/Packed/Matrix.hs b/lib/Data/Packed/Matrix.hs
index 6ea76c0..ec5744d 100644
--- a/lib/Data/Packed/Matrix.hs
+++ b/lib/Data/Packed/Matrix.hs
@@ -14,7 +14,7 @@
14 14
15module Data.Packed.Matrix ( 15module Data.Packed.Matrix (
16 Matrix(rows,cols), Field, 16 Matrix(rows,cols), Field,
17 toLists, (><), (>|<), 17 toLists, (><), (>|<), (@@>),
18 trans, 18 trans,
19 reshape, 19 reshape,
20 fromRows, toRows, fromColumns, toColumns, 20 fromRows, toRows, fromColumns, toColumns,
@@ -22,7 +22,9 @@ module Data.Packed.Matrix (
22 flipud, fliprl, 22 flipud, fliprl,
23 liftMatrix, liftMatrix2, 23 liftMatrix, liftMatrix2,
24 multiply, 24 multiply,
25 subMatrix, diag, takeDiag, diagRect, ident 25 subMatrix,
26 takeRows, dropRows, takeColumns, dropColumns,
27 diag, takeDiag, diagRect, ident
26) where 28) where
27 29
28import Data.Packed.Internal 30import Data.Packed.Internal
@@ -69,3 +71,20 @@ r >|< c = f where
69 | otherwise = error $ "inconsistent list size = " 71 | otherwise = error $ "inconsistent list size = "
70 ++show (dim v) ++"in ("++show r++"><"++show c++")" 72 ++show (dim v) ++"in ("++show r++"><"++show c++")"
71 where v = fromList l 73 where v = fromList l
74
75----------------------------------------------------------------
76
77-- | Creates a matrix with the first n rows of another matrix
78takeRows :: Field t => Int -> Matrix t -> Matrix t
79takeRows n mat = subMatrix (0,0) (n, cols mat) mat
80-- | Creates a copy of a matrix without the first n rows
81dropRows :: Field t => Int -> Matrix t -> Matrix t
82dropRows n mat = subMatrix (n,0) (rows mat - n, cols mat) mat
83-- |Creates a matrix with the first n columns of another matrix
84takeColumns :: Field t => Int -> Matrix t -> Matrix t
85takeColumns n mat = subMatrix (0,0) (rows mat, n) mat
86-- | Creates a copy of a matrix without the first n columns
87dropColumns :: Field t => Int -> Matrix t -> Matrix t
88dropColumns n mat = subMatrix (0,n) (rows mat, cols mat - n) mat
89
90----------------------------------------------------------------
diff --git a/lib/GSL/Fourier.hs b/lib/GSL/Fourier.hs
new file mode 100644
index 0000000..c8c79f0
--- /dev/null
+++ b/lib/GSL/Fourier.hs
@@ -0,0 +1,46 @@
1{-# OPTIONS_GHC -fglasgow-exts #-}
2-----------------------------------------------------------------------------
3{- |
4Module : GSL.Fourier
5Copyright : (c) Alberto Ruiz 2006
6License : GPL-style
7
8Maintainer : Alberto Ruiz (aruiz at um dot es)
9Stability : provisional
10Portability : uses ffi
11
12Fourier Transform.
13
14<http://www.gnu.org/software/gsl/manual/html_node/Fast-Fourier-Transforms.html#Fast-Fourier-Transforms>
15
16-}
17-----------------------------------------------------------------------------
18module GSL.Fourier (
19 fft,
20 ifft
21) where
22
23import Data.Packed.Internal
24import Complex
25import Foreign
26
27genfft code v = unsafePerformIO $ do
28 r <- createVector (dim v)
29 c_fft code // vec v // vec r // check "fft" [v]
30 return r
31
32foreign import ccall "gsl-aux.h fft" c_fft :: Int -> Complex Double :> Complex Double :> IO Int
33
34
35{- | Fast 1D Fourier transform of a 'Vector' @(@'Complex' 'Double'@)@ using /gsl_fft_complex_forward/. It uses the same scaling conventions as GNU Octave.
36
37@> fft ('GSL.Matrix.fromList' [1,2,3,4])
38vector (4) [10.0 :+ 0.0,(-2.0) :+ 2.0,(-2.0) :+ 0.0,(-2.0) :+ (-2.0)]@
39
40-}
41fft :: Vector (Complex Double) -> Vector (Complex Double)
42fft = genfft 0
43
44-- | The inverse of 'fft', using /gsl_fft_complex_inverse/.
45ifft :: Vector (Complex Double) -> Vector (Complex Double)
46ifft = genfft 1
diff --git a/lib/GSL/Minimization.hs b/lib/GSL/Minimization.hs
new file mode 100644
index 0000000..bc228a7
--- /dev/null
+++ b/lib/GSL/Minimization.hs
@@ -0,0 +1,211 @@
1{-# OPTIONS_GHC -fglasgow-exts #-}
2-----------------------------------------------------------------------------
3{- |
4Module : GSL.Minimization
5Copyright : (c) Alberto Ruiz 2006
6License : GPL-style
7
8Maintainer : Alberto Ruiz (aruiz at um dot es)
9Stability : provisional
10Portability : uses ffi
11
12Minimization of a multidimensional function Minimization of a multidimensional function using some of the algorithms described in:
13
14<http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html>
15
16-}
17-----------------------------------------------------------------------------
18module GSL.Minimization (
19 minimizeConjugateGradient,
20 minimizeNMSimplex
21) where
22
23
24import Data.Packed.Internal
25import Data.Packed.Matrix
26import Foreign
27import Complex
28
29
30-------------------------------------------------------------------------
31
32{- | The method of Nelder and Mead, implemented by /gsl_multimin_fminimizer_nmsimplex/. The gradient of the function is not required. This is the example in the GSL manual:
33
34@minimize f xi = minimizeNMSimplex f xi (replicate (length xi) 1) 1e-2 100
35\
36f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30
37\
38main = do
39 let (s,p) = minimize f [5,7]
40 print s
41 print p
42\
43\> main
44[0.9920430849306285,1.9969168063253164]
450. 512.500 1.082 6.500 5.
46 1. 290.625 1.372 5.250 4.
47 2. 290.625 1.372 5.250 4.
48 3. 252.500 1.372 5.500 1.
49 4. 101.406 1.823 2.625 3.500
50 5. 101.406 1.823 2.625 3.500
51 6. 60. 1.823 0. 3.
52 7. 42.275 1.303 2.094 1.875
53 8. 42.275 1.303 2.094 1.875
54 9. 35.684 1.026 0.258 1.906
5510. 35.664 0.804 0.588 2.445
5611. 30.680 0.467 1.258 2.025
5712. 30.680 0.356 1.258 2.025
5813. 30.539 0.285 1.093 1.849
5914. 30.137 0.168 0.883 2.004
6015. 30.137 0.123 0.883 2.004
6116. 30.090 0.100 0.958 2.060
6217. 30.005 6.051e-2 1.022 2.004
6318. 30.005 4.249e-2 1.022 2.004
6419. 30.005 4.249e-2 1.022 2.004
6520. 30.005 2.742e-2 1.022 2.004
6621. 30.005 2.119e-2 1.022 2.004
6722. 30.001 1.530e-2 0.992 1.997
6823. 30.001 1.259e-2 0.992 1.997
6924. 30.001 7.663e-3 0.992 1.997@
70
71The path to the solution can be graphically shown by means of:
72
73@'GSL.Plot.mplot' $ drop 3 ('toColumns' p)@
74
75-}
76minimizeNMSimplex :: ([Double] -> Double) -- ^ function to minimize
77 -> [Double] -- ^ starting point
78 -> [Double] -- ^ sizes of the initial search box
79 -> Double -- ^ desired precision of the solution
80 -> Int -- ^ maximum number of iterations allowed
81 -> ([Double], Matrix Double)
82 -- ^ solution vector, and the optimization trajectory followed by the algorithm
83minimizeNMSimplex f xi sz tol maxit = unsafePerformIO $ do
84 let xiv = fromList xi
85 szv = fromList sz
86 n = dim xiv
87 fp <- mkVecfun (iv (f.toList))
88 rawpath <- createMIO maxit (n+3)
89 (c_minimizeNMSimplex fp tol maxit // vec xiv // vec szv)
90 "minimizeNMSimplex" [xiv,szv]
91 let it = round (rawpath @@> (maxit-1,0))
92 path = takeRows it rawpath
93 [sol] = toLists $ dropRows (it-1) path
94 freeHaskellFunPtr fp
95 return (drop 3 sol, path)
96
97
98foreign import ccall "gsl-aux.h minimize"
99 c_minimizeNMSimplex:: FunPtr (Int -> Ptr Double -> Double) -> Double -> Int
100 -> Double :> Double :> Double ::> IO Int
101
102----------------------------------------------------------------------------------
103
104{- | The Fletcher-Reeves conjugate gradient algorithm /gsl_multimin_fminimizer_conjugate_fr/. This is the example in the GSL manual:
105
106@minimize = minimizeConjugateGradient 1E-2 1E-4 1E-3 30
107f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30
108\
109df [x,y] = [20*(x-1), 40*(y-2)]
110\
111main = do
112 let (s,p) = minimize f df [5,7]
113 print s
114 print p
115\
116\> main
117[1.0,2.0]
118 0. 687.848 4.996 6.991
119 1. 683.555 4.989 6.972
120 2. 675.013 4.974 6.935
121 3. 658.108 4.944 6.861
122 4. 625.013 4.885 6.712
123 5. 561.684 4.766 6.415
124 6. 446.467 4.528 5.821
125 7. 261.794 4.053 4.632
126 8. 75.498 3.102 2.255
127 9. 67.037 2.852 1.630
12810. 45.316 2.191 1.762
12911. 30.186 0.869 2.026
13012. 30. 1. 2.@
131
132The path to the solution can be graphically shown by means of:
133
134@'GSL.Plot.mplot' $ drop 2 ('toColumns' p)@
135
136-}
137minimizeConjugateGradient ::
138 Double -- ^ initial step size
139 -> Double -- ^ minimization parameter
140 -> Double -- ^ desired precision of the solution (gradient test)
141 -> Int -- ^ maximum number of iterations allowed
142 -> ([Double] -> Double) -- ^ function to minimize
143 -> ([Double] -> [Double]) -- ^ gradient
144 -> [Double] -- ^ starting point
145 -> ([Double], Matrix Double) -- ^ solution vector, and the optimization trajectory followed by the algorithm
146minimizeConjugateGradient istep minimpar tol maxit f df xi = unsafePerformIO $ do
147 let xiv = fromList xi
148 n = dim xiv
149 f' = f . toList
150 df' = (fromList . df . toList)
151 fp <- mkVecfun (iv f')
152 dfp <- mkVecVecfun (aux_vTov df')
153 rawpath <- createMIO maxit (n+2)
154 (c_minimizeConjugateGradient fp dfp istep minimpar tol maxit // vec xiv)
155 "minimizeDerivV" [xiv]
156 let it = round (rawpath @@> (maxit-1,0))
157 path = takeRows it rawpath
158 sol = toList $ cdat $ dropColumns 2 $ dropRows (it-1) path
159 freeHaskellFunPtr fp
160 freeHaskellFunPtr dfp
161 return (sol,path)
162
163
164foreign import ccall "gsl-aux.h minimizeWithDeriv"
165 c_minimizeConjugateGradient :: FunPtr (Int -> Ptr Double -> Double)
166 -> FunPtr (Int -> Ptr Double -> Ptr Double -> IO ())
167 -> Double -> Double -> Double -> Int
168 -> Double :> Double ::> IO Int
169
170---------------------------------------------------------------------
171iv :: (Vector Double -> Double) -> (Int -> Ptr Double -> Double)
172iv f n p = f (createV n copy "iv" []) where
173 copy n q = do
174 copyArray q p n
175 return 0
176
177-- | conversion of Haskell functions into function pointers that can be used in the C side
178foreign import ccall "wrapper"
179 mkVecfun :: (Int -> Ptr Double -> Double)
180 -> IO( FunPtr (Int -> Ptr Double -> Double))
181
182-- | another required conversion
183foreign import ccall "wrapper"
184 mkVecVecfun :: (Int -> Ptr Double -> Ptr Double -> IO ())
185 -> IO (FunPtr (Int -> Ptr Double -> Ptr Double->IO()))
186
187aux_vTov :: (Vector Double -> Vector Double) -> (Int -> Ptr Double -> Ptr Double -> IO())
188aux_vTov f n p r = g where
189 V {fptr = pr, ptr = p} = f x
190 x = createV n copy "aux_vTov" []
191 copy n q = do
192 copyArray q p n
193 return 0
194 g = withForeignPtr pr $ \_ -> copyArray r p n
195
196--------------------------------------------------------------------
197
198createV n fun msg ptrs = unsafePerformIO $ do
199 r <- createVector n
200 fun // vec r // check msg ptrs
201 return r
202
203createM r c fun msg ptrs = unsafePerformIO $ do
204 r <- createMatrix RowMajor r c
205 fun // mat cdat r // check msg ptrs
206 return r
207
208createMIO r c fun msg ptrs = do
209 r <- createMatrix RowMajor r c
210 fun // mat cdat r // check msg ptrs
211 return r
diff --git a/lib/GSL/Polynomials.hs b/lib/GSL/Polynomials.hs
new file mode 100644
index 0000000..d7db9a3
--- /dev/null
+++ b/lib/GSL/Polynomials.hs
@@ -0,0 +1,54 @@
1{-# OPTIONS_GHC -fglasgow-exts #-}
2-----------------------------------------------------------------------------
3{- |
4Module : GSL.Polynomials
5Copyright : (c) Alberto Ruiz 2006
6License : GPL-style
7
8Maintainer : Alberto Ruiz (aruiz at um dot es)
9Stability : provisional
10Portability : uses ffi
11
12Polynomials.
13
14<http://www.gnu.org/software/gsl/manual/html_node/General-Polynomial-Equations.html#General-Polynomial-Equations>
15
16-}
17-----------------------------------------------------------------------------
18module GSL.Polynomials (
19 polySolve
20) where
21
22import Data.Packed.Internal
23import Complex
24import Foreign
25
26{- | Solution of general polynomial equations, using /gsl_poly_complex_solve/. For example,
27 the three solutions of x^3 + 8 = 0
28
29@\> polySolve [8,0,0,1]
30[(-1.9999999999999998) :+ 0.0,
31 1.0 :+ 1.732050807568877,
32 1.0 :+ (-1.732050807568877)]@
33
34The example in the GSL manual: To find the roots of x^5 -1 = 0:
35
36@\> polySolve [-1, 0, 0, 0, 0, 1]
37[(-0.8090169943749475) :+ 0.5877852522924731,
38(-0.8090169943749475) :+ (-0.5877852522924731),
390.30901699437494734 :+ 0.9510565162951536,
400.30901699437494734 :+ (-0.9510565162951536),
411.0 :+ 0.0]@
42
43-}
44polySolve :: [Double] -> [Complex Double]
45polySolve = toList . polySolve' . fromList
46
47polySolve' :: Vector Double -> Vector (Complex Double)
48polySolve' v | dim v > 1 = unsafePerformIO $ do
49 r <- createVector (dim v-1)
50 c_polySolve // vec v // vec r // check "polySolve" [v]
51 return r
52 | otherwise = error "polySolve on a polynomial of degree zero"
53
54foreign import ccall "gsl-aux.h polySolve" c_polySolve:: Double :> Complex Double :> IO Int