1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.optim.univariate;
23
24 import org.hipparchus.analysis.UnivariateFunction;
25 import org.hipparchus.exception.LocalizedCoreFormats;
26 import org.hipparchus.exception.MathIllegalArgumentException;
27 import org.hipparchus.optim.nonlinear.scalar.GoalType;
28 import org.hipparchus.util.FastMath;
29 import org.hipparchus.util.Incrementor;
30
31
32
33
34
35
36
37 public class BracketFinder {
38
39 private static final double EPS_MIN = 1e-21;
40
41
42
43 private static final double GOLD = 1.618034;
44
45
46
47 private final double growLimit;
48
49
50
51 private final int maxEvaluations;
52
53
54
55 private int evaluations;
56
57
58
59 private double lo;
60
61
62
63 private double hi;
64
65
66
67 private double mid;
68
69
70
71 private double fLo;
72
73
74
75 private double fHi;
76
77
78
79 private double fMid;
80
81
82
83
84
85 public BracketFinder() {
86 this(100, 500);
87 }
88
89
90
91
92
93
94
95
96 public BracketFinder(double growLimit,
97 int maxEvaluations) {
98 if (growLimit <= 0) {
99 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
100 growLimit, 0);
101 }
102 if (maxEvaluations <= 0) {
103 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL_BOUND_EXCLUDED,
104 maxEvaluations, 0);
105 }
106
107 this.growLimit = growLimit;
108 this.maxEvaluations = maxEvaluations;
109 }
110
111
112
113
114
115
116
117
118
119
120
121 public void search(UnivariateFunction func,
122 GoalType goal,
123 double xA,
124 double xB) {
125 final FunctionEvaluator eval = new FunctionEvaluator(func);
126 final boolean isMinim = goal == GoalType.MINIMIZE;
127
128 double fA = eval.value(xA);
129 double fB = eval.value(xB);
130 if (isMinim ?
131 fA < fB :
132 fA > fB) {
133
134 double tmp = xA;
135 xA = xB;
136 xB = tmp;
137
138 tmp = fA;
139 fA = fB;
140 fB = tmp;
141 }
142
143 double xC = xB + GOLD * (xB - xA);
144 double fC = eval.value(xC);
145
146 while (isMinim ? fC < fB : fC > fB) {
147 double tmp1 = (xB - xA) * (fB - fC);
148 double tmp2 = (xB - xC) * (fB - fA);
149
150 double val = tmp2 - tmp1;
151 double denom = FastMath.abs(val) < EPS_MIN ? 2 * EPS_MIN : 2 * val;
152
153 double w = xB - ((xB - xC) * tmp2 - (xB - xA) * tmp1) / denom;
154 double wLim = xB + growLimit * (xC - xB);
155
156 double fW;
157 if ((w - xC) * (xB - w) > 0) {
158 fW = eval.value(w);
159 if (isMinim ?
160 fW < fC :
161 fW > fC) {
162 xA = xB;
163 xB = w;
164 fA = fB;
165 fB = fW;
166 break;
167 } else if (isMinim ?
168 fW > fB :
169 fW < fB) {
170 xC = w;
171 fC = fW;
172 break;
173 }
174 w = xC + GOLD * (xC - xB);
175 fW = eval.value(w);
176 } else if ((w - wLim) * (wLim - xC) >= 0) {
177 w = wLim;
178 fW = eval.value(w);
179 } else if ((w - wLim) * (xC - w) > 0) {
180 fW = eval.value(w);
181 if (isMinim ?
182 fW < fC :
183 fW > fC) {
184 xB = xC;
185 xC = w;
186 w = xC + GOLD * (xC - xB);
187 fB = fC;
188 fC =fW;
189 fW = eval.value(w);
190 }
191 } else {
192 w = xC + GOLD * (xC - xB);
193 fW = eval.value(w);
194 }
195
196 xA = xB;
197 fA = fB;
198 xB = xC;
199 fB = fC;
200 xC = w;
201 fC = fW;
202 }
203
204 lo = xA;
205 fLo = fA;
206 mid = xB;
207 fMid = fB;
208 hi = xC;
209 fHi = fC;
210
211 if (lo > hi) {
212 double tmp = lo;
213 lo = hi;
214 hi = tmp;
215
216 tmp = fLo;
217 fLo = fHi;
218 fHi = tmp;
219 }
220 }
221
222
223
224
225 public int getMaxEvaluations() {
226 return maxEvaluations;
227 }
228
229
230
231
232 public int getEvaluations() {
233 return evaluations;
234 }
235
236
237
238
239
240 public double getLo() {
241 return lo;
242 }
243
244
245
246
247 public double getFLo() {
248 return fLo;
249 }
250
251
252
253
254
255 public double getHi() {
256 return hi;
257 }
258
259
260
261
262
263 public double getFHi() {
264 return fHi;
265 }
266
267
268
269
270
271 public double getMid() {
272 return mid;
273 }
274
275
276
277
278 public double getFMid() {
279 return fMid;
280 }
281
282
283
284
285 private class FunctionEvaluator {
286
287 private final UnivariateFunction func;
288
289 private final Incrementor inc;
290
291
292
293
294 FunctionEvaluator(UnivariateFunction func) {
295 this.func = func;
296 inc = new Incrementor(maxEvaluations);
297 evaluations = 0;
298 }
299
300
301
302
303
304
305
306 double value(double x) {
307 inc.increment();
308 evaluations = inc.getCount();
309 return func.value(x);
310 }
311 }
312 }