-
Notifications
You must be signed in to change notification settings - Fork 0
/
fMinBracket.m
105 lines (85 loc) · 2.5 KB
/
fMinBracket.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
function [ax bx cx] = fMinBracket(fun, ax, bx)
%FMINBRACKET Routine for initially bracketing the minimum of a function
%
% [AX, BX, CX] = fMinBracket(FUN, LOW, HIGH)
% Return a triplet of values such that BX is between AX and CX, and
% FUN(BX) < min(FUN(AX), FUN(CX)
%
% Example
% fMinBracket
%
% Algorithm taken from Numerical Recipes in C, second ed., p. 400
%
%
% ------
% Author: David Legland
% e-mail: [email protected]
% Created: 2010-08-05, using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.
% gold ratio constant
GOLD = (1+sqrt(5))/2;
% evaluate function at bounds
fa = fun(ax);
fb = fun(bx);
% we want to go downhill in the direction a -> b
if fb>fa
dum = fa; fa = fb; fb = dum;
dum = ax; ax = bx; bx = dum;
end
% first guess of cx
cx = bx + GOLD*(bx-ax);
% corresponding function value
fc = fun(cx);
% Iterate until the middle point has value below the largest one
while fb > fc
% compute u using parabolic interpolation
r = (bx - ax) * (fb - fc);
q = (bx - cx) * (fb - fa);
% some trick to avoid 0 at denominator
denom = 2*sign(q - r)*max(abs(q - r), 1e-12);
u = bx - ((bx - cx)*q - (bx - ax)*r) / denom;
ulim = bx + 100 * (cx - bx);
% test different cases for relative location of u wrt ax and bx
if (bx - u) * (u - cx) > 0
% u is between b and c
fu = fun(u);
if fu < fc
% a minimum was found between b and c
ax = bx;
bx = u;
break;
elseif fu > fb
% a minimum was found between a and u
cx = u;
break;
else
% parabolic fit was not useful
u = cx + GOLD * (cx - bx);
fu = fun(u);
end
elseif (cx-u) * (u-ulim) > 0
% found minimum above c and below limit
fu = fun(u);
if fu < fc
bx = cx; cx = u; u = cx+GOLD*(cx-bx);
fb = fc; fc = fu; fu = fun(u);
end
elseif (u-ulim) * (ulim - cx) >= 0
% limit parabolic u to maximum allowed value
u = ulim;
fu = fun(u);
else
% reject parabolic u and use the default magnification
u = cx + GOLD * (cx - bx);
fu = fun(u);
end
% update for next iteration
ax = bx; bx = cx; cx = u;
fa = fb; fb = fc; fc = fu;
end % while
% end of iteration, just checkup that a < c
if ax > cx
tmp = ax;
ax = cx;
cx = tmp;
end