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.analysis.solvers;
23
24 import org.hipparchus.exception.MathIllegalArgumentException;
25 import org.hipparchus.exception.MathIllegalStateException;
26 import org.hipparchus.util.FastMath;
27
28
29
30
31
32
33
34
35
36
37
38 public class RiddersSolver extends AbstractUnivariateSolver {
39
40 private static final double DEFAULT_ABSOLUTE_ACCURACY = 1e-6;
41
42
43
44
45 public RiddersSolver() {
46 this(DEFAULT_ABSOLUTE_ACCURACY);
47 }
48
49
50
51
52
53 public RiddersSolver(double absoluteAccuracy) {
54 super(absoluteAccuracy);
55 }
56
57
58
59
60
61
62 public RiddersSolver(double relativeAccuracy,
63 double absoluteAccuracy) {
64 super(relativeAccuracy, absoluteAccuracy);
65 }
66
67
68
69
70 @Override
71 protected double doSolve()
72 throws MathIllegalArgumentException, MathIllegalStateException {
73 double min = getMin();
74 double max = getMax();
75
76
77
78 double x1 = min;
79 double y1 = computeObjectiveValue(x1);
80 double x2 = max;
81 double y2 = computeObjectiveValue(x2);
82
83
84 if (y1 == 0) {
85 return min;
86 }
87 if (y2 == 0) {
88 return max;
89 }
90 verifyBracketing(min, max);
91
92 final double absoluteAccuracy = getAbsoluteAccuracy();
93 final double functionValueAccuracy = getFunctionValueAccuracy();
94 final double relativeAccuracy = getRelativeAccuracy();
95
96 double oldx = Double.POSITIVE_INFINITY;
97 while (true) {
98
99 final double x3 = 0.5 * (x1 + x2);
100 final double y3 = computeObjectiveValue(x3);
101 if (FastMath.abs(y3) <= functionValueAccuracy) {
102 return x3;
103 }
104 final double delta = 1 - (y1 * y2) / (y3 * y3);
105 final double correction = (FastMath.signum(y2) * FastMath.signum(y3)) *
106 (x3 - x1) / FastMath.sqrt(delta);
107 final double x = x3 - correction;
108 final double y = computeObjectiveValue(x);
109
110
111 final double tolerance = FastMath.max(relativeAccuracy * FastMath.abs(x), absoluteAccuracy);
112 if (FastMath.abs(x - oldx) <= tolerance) {
113 return x;
114 }
115 if (FastMath.abs(y) <= functionValueAccuracy) {
116 return x;
117 }
118
119
120
121 if (correction > 0.0) {
122 if (FastMath.signum(y1) + FastMath.signum(y) == 0.0) {
123 x2 = x;
124 y2 = y;
125 } else {
126 x1 = x;
127 x2 = x3;
128 y1 = y;
129 y2 = y3;
130 }
131 } else {
132 if (FastMath.signum(y2) + FastMath.signum(y) == 0.0) {
133 x1 = x;
134 y1 = y;
135 } else {
136 x1 = x3;
137 x2 = x;
138 y1 = y3;
139 y2 = y;
140 }
141 }
142 oldx = x;
143 }
144 }
145 }