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