summaryrefslogtreecommitdiff
path: root/lib/Numeric/GSL/Minimization.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric/GSL/Minimization.hs')
-rw-r--r--lib/Numeric/GSL/Minimization.hs213
1 files changed, 213 insertions, 0 deletions
diff --git a/lib/Numeric/GSL/Minimization.hs b/lib/Numeric/GSL/Minimization.hs
new file mode 100644
index 0000000..23ca51b
--- /dev/null
+++ b/lib/Numeric/GSL/Minimization.hs
@@ -0,0 +1,213 @@
1{-# OPTIONS_GHC -fglasgow-exts #-}
2-----------------------------------------------------------------------------
3{- |
4Module : Numeric.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 Numeric.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 -> TVVM
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 print "entro"
154 rawpath <- createMIO maxit (n+2)
155 (c_minimizeConjugateGradient fp dfp istep minimpar tol maxit // vec xiv)
156 "minimizeDerivV" [xiv]
157 print "salgo"
158 let it = round (rawpath @@> (maxit-1,0))
159 path = takeRows it rawpath
160 sol = toList $ cdat $ dropColumns 2 $ dropRows (it-1) path
161 freeHaskellFunPtr fp
162 freeHaskellFunPtr dfp
163 return (sol,path)
164
165
166foreign import ccall "gsl-aux.h minimizeWithDeriv"
167 c_minimizeConjugateGradient :: FunPtr (Int -> Ptr Double -> Double)
168 -> FunPtr (Int -> Ptr Double -> Ptr Double -> IO ())
169 -> Double -> Double -> Double -> Int
170 -> TVM
171
172---------------------------------------------------------------------
173iv :: (Vector Double -> Double) -> (Int -> Ptr Double -> Double)
174iv f n p = f (createV n copy "iv" []) where
175 copy n q = do
176 copyArray q p n
177 return 0
178
179-- | conversion of Haskell functions into function pointers that can be used in the C side
180foreign import ccall "wrapper"
181 mkVecfun :: (Int -> Ptr Double -> Double)
182 -> IO( FunPtr (Int -> Ptr Double -> Double))
183
184-- | another required conversion
185foreign import ccall "wrapper"
186 mkVecVecfun :: (Int -> Ptr Double -> Ptr Double -> IO ())
187 -> IO (FunPtr (Int -> Ptr Double -> Ptr Double->IO()))
188
189aux_vTov :: (Vector Double -> Vector Double) -> (Int -> Ptr Double -> Ptr Double -> IO())
190aux_vTov f n p r = g where
191 V {fptr = pr, ptr = t} = f x
192 x = createV n copy "aux_vTov" []
193 copy n q = do
194 copyArray q p n
195 return 0
196 g = withForeignPtr pr $ \_ -> copyArray r t n
197
198--------------------------------------------------------------------
199
200createV n fun msg ptrs = unsafePerformIO $ do
201 r <- createVector n
202 fun // vec r // check msg ptrs
203 return r
204
205createM r c fun msg ptrs = unsafePerformIO $ do
206 r <- createMatrix RowMajor r c
207 fun // mat cdat r // check msg ptrs
208 return r
209
210createMIO r c fun msg ptrs = do
211 r <- createMatrix RowMajor r c
212 fun // mat cdat r // check msg ptrs
213 return r