diff options
Diffstat (limited to 'lib/Numeric/GSL/Minimization.hs')
-rw-r--r-- | lib/Numeric/GSL/Minimization.hs | 213 |
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 | {- | | ||
4 | Module : Numeric.GSL.Minimization | ||
5 | Copyright : (c) Alberto Ruiz 2006 | ||
6 | License : GPL-style | ||
7 | |||
8 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
9 | Stability : provisional | ||
10 | Portability : uses ffi | ||
11 | |||
12 | Minimization 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 | ----------------------------------------------------------------------------- | ||
18 | module Numeric.GSL.Minimization ( | ||
19 | minimizeConjugateGradient, | ||
20 | minimizeNMSimplex | ||
21 | ) where | ||
22 | |||
23 | |||
24 | import Data.Packed.Internal | ||
25 | import Data.Packed.Matrix | ||
26 | import Foreign | ||
27 | import 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 | \ | ||
36 | f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30 | ||
37 | \ | ||
38 | main = do | ||
39 | let (s,p) = minimize f [5,7] | ||
40 | print s | ||
41 | print p | ||
42 | \ | ||
43 | \> main | ||
44 | [0.9920430849306285,1.9969168063253164] | ||
45 | 0. 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 | ||
55 | 10. 35.664 0.804 0.588 2.445 | ||
56 | 11. 30.680 0.467 1.258 2.025 | ||
57 | 12. 30.680 0.356 1.258 2.025 | ||
58 | 13. 30.539 0.285 1.093 1.849 | ||
59 | 14. 30.137 0.168 0.883 2.004 | ||
60 | 15. 30.137 0.123 0.883 2.004 | ||
61 | 16. 30.090 0.100 0.958 2.060 | ||
62 | 17. 30.005 6.051e-2 1.022 2.004 | ||
63 | 18. 30.005 4.249e-2 1.022 2.004 | ||
64 | 19. 30.005 4.249e-2 1.022 2.004 | ||
65 | 20. 30.005 2.742e-2 1.022 2.004 | ||
66 | 21. 30.005 2.119e-2 1.022 2.004 | ||
67 | 22. 30.001 1.530e-2 0.992 1.997 | ||
68 | 23. 30.001 1.259e-2 0.992 1.997 | ||
69 | 24. 30.001 7.663e-3 0.992 1.997@ | ||
70 | |||
71 | The path to the solution can be graphically shown by means of: | ||
72 | |||
73 | @'GSL.Plot.mplot' $ drop 3 ('toColumns' p)@ | ||
74 | |||
75 | -} | ||
76 | minimizeNMSimplex :: ([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 | ||
83 | minimizeNMSimplex 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 | |||
98 | foreign 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 | ||
107 | f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30 | ||
108 | \ | ||
109 | df [x,y] = [20*(x-1), 40*(y-2)] | ||
110 | \ | ||
111 | main = 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 | ||
128 | 10. 45.316 2.191 1.762 | ||
129 | 11. 30.186 0.869 2.026 | ||
130 | 12. 30. 1. 2.@ | ||
131 | |||
132 | The path to the solution can be graphically shown by means of: | ||
133 | |||
134 | @'GSL.Plot.mplot' $ drop 2 ('toColumns' p)@ | ||
135 | |||
136 | -} | ||
137 | minimizeConjugateGradient :: | ||
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 | ||
146 | minimizeConjugateGradient 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 | |||
166 | foreign 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 | --------------------------------------------------------------------- | ||
173 | iv :: (Vector Double -> Double) -> (Int -> Ptr Double -> Double) | ||
174 | iv 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 | ||
180 | foreign import ccall "wrapper" | ||
181 | mkVecfun :: (Int -> Ptr Double -> Double) | ||
182 | -> IO( FunPtr (Int -> Ptr Double -> Double)) | ||
183 | |||
184 | -- | another required conversion | ||
185 | foreign import ccall "wrapper" | ||
186 | mkVecVecfun :: (Int -> Ptr Double -> Ptr Double -> IO ()) | ||
187 | -> IO (FunPtr (Int -> Ptr Double -> Ptr Double->IO())) | ||
188 | |||
189 | aux_vTov :: (Vector Double -> Vector Double) -> (Int -> Ptr Double -> Ptr Double -> IO()) | ||
190 | aux_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 | |||
200 | createV n fun msg ptrs = unsafePerformIO $ do | ||
201 | r <- createVector n | ||
202 | fun // vec r // check msg ptrs | ||
203 | return r | ||
204 | |||
205 | createM 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 | |||
210 | createMIO r c fun msg ptrs = do | ||
211 | r <- createMatrix RowMajor r c | ||
212 | fun // mat cdat r // check msg ptrs | ||
213 | return r | ||