Local one-dimensional minimization by bracketing.
39 {
40 if(verbose>0) {
41 printf("%s(f, fdata, %g, %g, %g, %g, %g, %d, ...)\n", __func__, x, xl, xu, delta, tol, maxeval);
42 fflush(stdout);
43 }
44
45
46
47 if(_fun==NULL) return(1);
48 if(xl>xu || x<xl || x>xu) return(1);
49 if(!(delta>0.0) || !(tol>0.0)) return(1);
50 if(tol>=delta) return(1);
51 if(maxeval<5) return(1);
52 if(nx==NULL) return(1);
53
54 double begin=xl;
55 double end=xu;
56 int nevals=0;
57
58 double p1=0, p2=0, p3=0, f1=0, f2=0, f3=0;
59
60 double minf=f2=_fun(x, _fundata); nevals++;
61
62 if(xl>=xu) {
63 *nx=x; if(nf!=NULL) *nf=minf;
64 return(0);
65 }
66
67
68
69
70
71 p2=x;
72
73
74 p1=p2-delta; if(p1>begin) p1=begin;
75 p3=p2+delta; if(p3<end) p3=end;
76
77 f1=_fun(p1, _fundata); nevals++;
78 f3=_fun(p3, _fundata); nevals++;
79 if(p2==p1 || p2==p3) {
80 p2=0.5*(p1+p3);
81 f2=minf=_fun(p2, _fundata); nevals++;
82 }
83
84
85
86 double jump_size=delta;
87 while(!(f1>f2 && f2<f3)) {
88
89 if(verbose>5) printf(" bracketing: nevals=%d\n", nevals);
90 if(nevals >= maxeval) {
91 *nx=p2; minf=f2; if(nf!=NULL) *nf=minf;
92 return(0);
93 }
94
95 if((p3-p1)<tol) {
96 if(verbose>1) printf(" max tolerance was reached during bracketing\n");
97 if(f1<f2 && f1<f3) {
98 *nx=p1; minf=f1; if(nf!=NULL) *nf=minf;
99 return(0);
100 }
101 if(f2<f1 && f2<f3) {
102 *nx=p2; minf=f2; if(nf!=NULL) *nf=minf;
103 return(0);
104 }
105 *nx=p3; minf=f3; if(nf!=NULL) *nf=minf;
106 return(0);
107 }
108 if(verbose>6) printf(" jump_size=%g\n", jump_size);
109
110 if(f1<f3) {
111
112
113
114
115 if(p1==begin || (f1==f2 && (end-begin)<jump_size )) {
116 p3=p2; f3=f2; p2=0.5*(p1+p2);
117 f2=minf=_fun(p2, _fundata); nevals++;
118 } else {
119
120 p3=p2; f3=f2; p2=p1; f2=f1;
121 p1-=jump_size; if(p1<begin) p1=begin;
122 f1=_fun(p1, _fundata); nevals++;
123 jump_size*=2.0;
124 }
125 } else {
126
127
128
129
130 if(p3==end || (f2==f3 && (end-begin)<jump_size)) {
131 p1=p2; f1=f2; p2=0.5*(p3+p2);
132 f2=minf=_fun(p2, _fundata); nevals++;
133 } else {
134
135 p1=p2; f1=f2; p2=p3; f2=f3;
136 p3+=jump_size; if(p3>end) p3=end;
137 f3=minf=_fun(p3, _fundata); nevals++;
138 jump_size*=2.0;
139 }
140 }
141 }
142 if(verbose>4) printf(" brackets ready\n");
143
144
145
146
147
148 double d, d2;
149 const double tau=0.1;
150 double p_min, f_min;
151 while((nevals<maxeval) && (p3-p1>tol)) {
152 if(verbose>5) printf(" main loop: nevals=%d\n", nevals);
153
154
155 d=f1*(p3*p3-p2*p2) + f2*(p1*p1-p3*p3) + f3*(p2*p2-p1*p1);
156 d2=2.0*(f1*(p3-p2) + f2*(p1-p3) + f3*(p2-p1));
157 if(d2==0.0 || !isfinite(d/=d2)) {
158 p_min=p2;
159 } else {
160 if(p1<=d && d<=p3) {p_min=d;}
161 else {p_min=d; if(p1>p_min) p_min=p1; if(p3<p_min) p_min=p3;}
162 }
163
164
165 if(p_min<p2) {
166 d=(p2-p1)*tau;
167 if(fabs(p1-p_min)<d) p_min=p1+d;
168 else if(fabs(p2-p_min)<d) p_min=p2-d;
169 } else {
170 d=(p3-p2)*tau;
171 if(fabs(p2-p_min)<d) p_min=p2+d;
172 else if(fabs(p3-p_min)<d) p_min=p3-d;
173 }
174
175
176
177 double bracket_ratio=fabs(p1-p2)/fabs(p2-p3);
178 if(!(bracket_ratio<100.0 && bracket_ratio>0.01)) {
179
180 if(bracket_ratio>1.0 && p_min>p2) p_min=0.5*(p1+p2);
181 else if(p_min<p2) p_min=0.5*(p2+p3);
182 }
183
184
185 *nx=p_min;
186 f_min=minf=_fun(p_min, _fundata); nevals++;
187
188
189 if(p_min<p2) {
190 if(f1>f_min && f_min<f2) {p3=p2; f3=f2; p2=p_min; f2=f_min;}
191 else {p1=p_min; f1=f_min;}
192 } else {
193 if(f2>f_min && f_min<f3) {p1=p2; f1=f2; p2=p_min; f2=f_min;}
194 else {p3=p_min; f3=f_min;}
195 }
196 }
197 *nx=p2; minf=f2; if(nf!=NULL) *nf=minf;
198 return(0);
199}