summaryrefslogtreecommitdiff
path: root/lib/GSL/Minimization.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/GSL/Minimization.hs')
-rw-r--r--lib/GSL/Minimization.hs211
1 files changed, 211 insertions, 0 deletions
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