comparison scripts/optimization/fminbnd.m @ 15706:242e9efd4315

Added Display option for fminbnd()
author Júlio Hoffimann <julio.hoffimann@gmail.com>
date Sun, 02 Sep 2012 16:21:48 -0300
parents e0525ecf156e
children 7eff3032d144
comparison
equal deleted inserted replaced
15705:a3189d329906 15706:242e9efd4315
19 ## Author: Jaroslav Hajek <highegg@gmail.com> 19 ## Author: Jaroslav Hajek <highegg@gmail.com>
20 20
21 ## -*- texinfo -*- 21 ## -*- texinfo -*-
22 ## @deftypefn {Function File} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fminbnd (@var{fun}, @var{a}, @var{b}, @var{options}) 22 ## @deftypefn {Function File} {[@var{x}, @var{fval}, @var{info}, @var{output}] =} fminbnd (@var{fun}, @var{a}, @var{b}, @var{options})
23 ## Find a minimum point of a univariate function. 23 ## Find a minimum point of a univariate function.
24 ## 24 ##
25 ## @var{fun} should be a function handle or name. @var{a}, @var{b} specify a 25 ## @var{fun} should be a function handle or name. @var{a}, @var{b} specify a
26 ## starting interval. @var{options} is a structure specifying additional 26 ## starting interval. @var{options} is a structure specifying additional
27 ## options. Currently, @code{fminbnd} recognizes these options: 27 ## options. Currently, @code{fminbnd} recognizes these options:
28 ## "FunValCheck", "OutputFcn", "TolX", "MaxIter", "MaxFunEvals". For a 28 ## "FunValCheck", "OutputFcn", "TolX", "MaxIter", "MaxFunEvals". For a
29 ## description of these options, see @ref{doc-optimset,,optimset}. 29 ## description of these options, see @ref{doc-optimset,,optimset}.
72 72
73 if (ischar (fun)) 73 if (ischar (fun))
74 fun = str2func (fun, "global"); 74 fun = str2func (fun, "global");
75 endif 75 endif
76 76
77 ## TODO 77 displ = optimget (options, "Display", "notify");
78 ## displev = optimget (options, "Display", "notify");
79 funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on"); 78 funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on");
80 outfcn = optimget (options, "OutputFcn"); 79 outfcn = optimget (options, "OutputFcn");
81 tolx = optimget (options, "TolX", 1e-8); 80 tolx = optimget (options, "TolX", 1e-8);
82 maxiter = optimget (options, "MaxIter", Inf); 81 maxiter = optimget (options, "MaxIter", Inf);
83 maxfev = optimget (options, "MaxFunEvals", Inf); 82 maxfev = optimget (options, "MaxFunEvals", Inf);
98 v = a + c*(b-a); 97 v = a + c*(b-a);
99 w = x = v; 98 w = x = v;
100 e = 0; 99 e = 0;
101 fv = fw = fval = fun (x); 100 fv = fw = fval = fun (x);
102 nfev++; 101 nfev++;
102
103 ## Only for display purposes.
104 iter(1).funccount = nfev;
105 iter(1).x = x;
106 iter(1).fx = fval;
103 107
104 while (niter < maxiter && nfev < maxfev) 108 while (niter < maxiter && nfev < maxfev)
105 xm = 0.5*(a+b); 109 xm = 0.5*(a+b);
106 ## FIXME: the golden section search can actually get closer than sqrt(eps) 110 ## FIXME: the golden section search can actually get closer than sqrt(eps)
107 ## sometimes. Sometimes not, it depends on the function. This is the 111 ## sometimes. Sometimes not, it depends on the function. This is the
113 endif 117 endif
114 118
115 if (abs (e) > tol) 119 if (abs (e) > tol)
116 dogs = false; 120 dogs = false;
117 ## Try inverse parabolic step. 121 ## Try inverse parabolic step.
122 iter(niter+1).procedure = "parabolic";
123
118 r = (x - w)*(fval - fv); 124 r = (x - w)*(fval - fv);
119 q = (x - v)*(fval - fw); 125 q = (x - v)*(fval - fw);
120 p = (x - v)*q - (x - w)*r; 126 p = (x - v)*q - (x - w)*r;
121 q = 2*(q - r); 127 q = 2*(q - r);
122 p *= -sign (q); 128 p *= -sign (q);
139 else 145 else
140 dogs = true; 146 dogs = true;
141 endif 147 endif
142 if (dogs) 148 if (dogs)
143 ## Default to golden section step. 149 ## Default to golden section step.
150
151 ## WARNING: This is also the "initial" procedure following
152 ## MATLAB nomenclature. After the loop we'll fix the string
153 ## for the first step.
154 iter(niter+1).procedure = "golden";
155
144 e = ifelse (x >= xm, a - x, b - x); 156 e = ifelse (x >= xm, a - x, b - x);
145 d = c * e; 157 d = c * e;
146 endif 158 endif
147 159
148 ## f must not be evaluated too close to x. 160 ## f must not be evaluated too close to x.
149 u = x + max (abs (d), tol) * (sign (d) + (d == 0)); 161 u = x + max (abs (d), tol) * (sign (d) + (d == 0));
150 162 fu = fun (u);
151 fu = fun (u); 163
152 nfev++; 164 niter++;
153 niter++; 165
154 166 iter(niter).funccount = nfev++;
155 ## update a, b, v, w, and x 167 iter(niter).x = u;
156 168 iter(niter).fx = fu;
157 if (fu <= fval) 169
158 if (u < x) 170 ## update a, b, v, w, and x
159 b = x; 171
160 else 172 if (fu <= fval)
161 a = x; 173 if (u < x)
162 endif 174 b = x;
163 v = w; fv = fw; 175 else
164 w = x; fw = fval; 176 a = x;
165 x = u; fval = fu; 177 endif
166 else 178 v = w; fv = fw;
167 ## The following if-statement was originally executed even if fu == fval. 179 w = x; fw = fval;
168 if (u < x) 180 x = u; fval = fu;
169 a = u; 181 else
170 else 182 ## The following if-statement was originally executed even if fu == fval.
171 b = u; 183 if (u < x)
172 endif 184 a = u;
173 if (fu <= fw || w == x) 185 else
174 v = w; fv = fw; 186 b = u;
175 w = u; fw = fu; 187 endif
176 elseif (fu <= fv || v == x || v == w) 188 if (fu <= fw || w == x)
177 v = u; 189 v = w; fv = fw;
178 fv = fu; 190 w = u; fw = fu;
179 endif 191 elseif (fu <= fv || v == x || v == w)
180 endif 192 v = u;
193 fv = fu;
194 endif
195 endif
181 196
182 ## If there's an output function, use it now. 197 ## If there's an output function, use it now.
183 if (outfcn) 198 if (outfcn)
184 optv.funccount = nfev; 199 optv.funccount = nfev;
185 optv.fval = fval; 200 optv.fval = fval;
188 info = -1; 203 info = -1;
189 break; 204 break;
190 endif 205 endif
191 endif 206 endif
192 endwhile 207 endwhile
208
209 ## Fix the first step procedure.
210 iter(1).procedure = "initial";
211
212 ## Handle the "Display" option
213 switch displ
214 case "iter"
215 print_formatted_table (iter);
216 print_exit_msg (info, struct("TolX", tolx, "fx", fval));
217 case "notify"
218 if (info == 0)
219 print_exit_msg (info, struct("fx",fval));
220 endif
221 case "final"
222 print_exit_msg (info, struct("TolX", tolx, "fx", fval));
223 case "off"
224 "skip";
225 otherwise
226 warning ("unknown option for Display: '%s'", displ);
227 endswitch
193 228
194 output.iterations = niter; 229 output.iterations = niter;
195 output.funcCount = nfev; 230 output.funcCount = nfev;
196 output.bracket = [a, b]; 231 output.bracket = [a, b];
197 ## FIXME: bracketf possibly unavailable. 232 ## FIXME: bracketf possibly unavailable.
208 elseif (isnan (fx)) 243 elseif (isnan (fx))
209 error ("fminbnd:isnan", "fminbnd: NaN value encountered"); 244 error ("fminbnd:isnan", "fminbnd: NaN value encountered");
210 endif 245 endif
211 endfunction 246 endfunction
212 247
248 ## A hack for printing a formatted table
249 function print_formatted_table (table)
250 printf ("\n Func-count x f(x) Procedure\n");
251 for row=table
252 printf("%5.5s %7.7s %8.8s\t%s\n",
253 int2str (row.funccount), num2str (row.x,"%.5f"),
254 num2str (row.fx,"%.6f"), row.procedure);
255 endfor
256 printf ("\n");
257 endfunction
258
259 ## Print either a success termination message or bad news
260 function print_exit_msg (info, opt=struct())
261 printf ("");
262 switch info
263 case 1
264 printf ("Optimization terminated:\n");
265 printf (" the current x satisfies the termination criteria using OPTIONS.TolX of %e\n", opt.TolX);
266 case 0
267 printf ("Exiting: Maximum number of iterations has been exceeded\n");
268 printf (" - increase MaxIter option.\n");
269 printf (" Current function value: %.6f\n", opt.fx);
270 case -1
271 "FIXME"; ## FIXME: what's the message MATLAB prints for this case?
272 otherwise
273 error ("internal error - fminbnd() is bug, sorry!");
274 endswitch
275 printf ("\n");
276 endfunction
277
213 278
214 %!shared opt0 279 %!shared opt0
215 %! opt0 = optimset ("tolx", 0); 280 %! opt0 = optimset ("tolx", 0);
216 %!assert (fminbnd (@cos, pi/2, 3*pi/2, opt0), pi, 10*sqrt (eps)) 281 %!assert (fminbnd (@cos, pi/2, 3*pi/2, opt0), pi, 10*sqrt (eps))
217 %!assert (fminbnd (@(x) (x - 1e-3)^4, -1, 1, opt0), 1e-3, 10e-3*sqrt (eps)) 282 %!assert (fminbnd (@(x) (x - 1e-3)^4, -1, 1, opt0), 1e-3, 10e-3*sqrt (eps))