1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.analysis.solvers;
19
20 import org.apache.commons.math4.legacy.analysis.UnivariateFunction;
21 import org.apache.commons.math4.legacy.exception.ConvergenceException;
22 import org.apache.commons.math4.legacy.exception.MathInternalError;
23 import org.apache.commons.math4.core.jdkmath.JdkMath;
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 public abstract class BaseSecantSolver
49 extends AbstractUnivariateSolver
50 implements BracketedUnivariateSolver<UnivariateFunction> {
51
52
53 protected static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6;
54
55
56 private AllowedSolution allowed;
57
58
59 private final Method method;
60
61
62
63
64
65
66
67 protected BaseSecantSolver(final double absoluteAccuracy, final Method method) {
68 super(absoluteAccuracy);
69 this.allowed = AllowedSolution.ANY_SIDE;
70 this.method = method;
71 }
72
73
74
75
76
77
78
79
80 protected BaseSecantSolver(final double relativeAccuracy,
81 final double absoluteAccuracy,
82 final Method method) {
83 super(relativeAccuracy, absoluteAccuracy);
84 this.allowed = AllowedSolution.ANY_SIDE;
85 this.method = method;
86 }
87
88
89
90
91
92
93
94
95
96 protected BaseSecantSolver(final double relativeAccuracy,
97 final double absoluteAccuracy,
98 final double functionValueAccuracy,
99 final Method method) {
100 super(relativeAccuracy, absoluteAccuracy, functionValueAccuracy);
101 this.allowed = AllowedSolution.ANY_SIDE;
102 this.method = method;
103 }
104
105
106 @Override
107 public double solve(final int maxEval, final UnivariateFunction f,
108 final double min, final double max,
109 final AllowedSolution allowedSolution) {
110 return solve(maxEval, f, min, max, min + 0.5 * (max - min), allowedSolution);
111 }
112
113
114 @Override
115 public double solve(final int maxEval, final UnivariateFunction f,
116 final double min, final double max, final double startValue,
117 final AllowedSolution allowedSolution) {
118 this.allowed = allowedSolution;
119 return super.solve(maxEval, f, min, max, startValue);
120 }
121
122
123 @Override
124 public double solve(final int maxEval, final UnivariateFunction f,
125 final double min, final double max, final double startValue) {
126 return solve(maxEval, f, min, max, startValue, AllowedSolution.ANY_SIDE);
127 }
128
129
130
131
132
133
134
135 @Override
136 protected final double doSolve()
137 throws ConvergenceException {
138
139 double x0 = getMin();
140 double x1 = getMax();
141 double f0 = computeObjectiveValue(x0);
142 double f1 = computeObjectiveValue(x1);
143
144
145
146
147 if (f0 == 0.0) {
148 return x0;
149 }
150 if (f1 == 0.0) {
151 return x1;
152 }
153
154
155 verifyBracketing(x0, x1);
156
157
158 final double ftol = getFunctionValueAccuracy();
159 final double atol = getAbsoluteAccuracy();
160 final double rtol = getRelativeAccuracy();
161
162
163
164 boolean inverted = false;
165
166
167 while (true) {
168
169 final double x = x1 - ((f1 * (x1 - x0)) / (f1 - f0));
170 final double fx = computeObjectiveValue(x);
171
172
173
174
175 if (fx == 0.0) {
176 return x;
177 }
178
179
180 if (f1 * fx < 0) {
181
182
183 x0 = x1;
184 f0 = f1;
185 inverted = !inverted;
186 } else {
187 switch (method) {
188 case ILLINOIS:
189 f0 *= 0.5;
190 break;
191 case PEGASUS:
192 f0 *= f1 / (f1 + fx);
193 break;
194 case REGULA_FALSI:
195
196
197 if (x == x1) {
198 throw new ConvergenceException();
199 }
200 break;
201 default:
202
203 throw new MathInternalError();
204 }
205 }
206
207 x1 = x;
208 f1 = fx;
209
210
211
212
213 if (JdkMath.abs(f1) <= ftol) {
214 switch (allowed) {
215 case ANY_SIDE:
216 return x1;
217 case LEFT_SIDE:
218 if (inverted) {
219 return x1;
220 }
221 break;
222 case RIGHT_SIDE:
223 if (!inverted) {
224 return x1;
225 }
226 break;
227 case BELOW_SIDE:
228 if (f1 <= 0) {
229 return x1;
230 }
231 break;
232 case ABOVE_SIDE:
233 if (f1 >= 0) {
234 return x1;
235 }
236 break;
237 default:
238 throw new MathInternalError();
239 }
240 }
241
242
243
244 if (JdkMath.abs(x1 - x0) < JdkMath.max(rtol * JdkMath.abs(x1),
245 atol)) {
246 switch (allowed) {
247 case ANY_SIDE:
248 return x1;
249 case LEFT_SIDE:
250 return inverted ? x1 : x0;
251 case RIGHT_SIDE:
252 return inverted ? x0 : x1;
253 case BELOW_SIDE:
254 return (f1 <= 0) ? x1 : x0;
255 case ABOVE_SIDE:
256 return (f1 >= 0) ? x1 : x0;
257 default:
258 throw new MathInternalError();
259 }
260 }
261 }
262 }
263
264
265 protected enum Method {
266
267
268
269
270
271 REGULA_FALSI,
272
273
274 ILLINOIS,
275
276
277 PEGASUS;
278 }
279 }