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.RealFieldUnivariateFunction;
21 import org.apache.commons.math4.legacy.core.dfp.Dfp;
22 import org.apache.commons.math4.legacy.core.dfp.DfpField;
23 import org.apache.commons.math4.legacy.core.dfp.DfpMath;
24 import org.apache.commons.math4.legacy.exception.MathInternalError;
25 import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
26 import org.junit.Assert;
27 import org.junit.Before;
28 import org.junit.Test;
29
30
31
32
33
34 public final class FieldBracketingNthOrderBrentSolverTest {
35
36 @Test(expected=NumberIsTooSmallException.class)
37 public void testInsufficientOrder3() {
38 new FieldBracketingNthOrderBrentSolver<>(relativeAccuracy, absoluteAccuracy,
39 functionValueAccuracy, 1);
40 }
41
42 @Test
43 public void testConstructorOK() {
44 FieldBracketingNthOrderBrentSolver<Dfp> solver =
45 new FieldBracketingNthOrderBrentSolver<>(relativeAccuracy, absoluteAccuracy,
46 functionValueAccuracy, 2);
47 Assert.assertEquals(2, solver.getMaximalOrder());
48 }
49
50 @Test
51 public void testConvergenceOnFunctionAccuracy() {
52 FieldBracketingNthOrderBrentSolver<Dfp> solver =
53 new FieldBracketingNthOrderBrentSolver<>(relativeAccuracy, absoluteAccuracy,
54 field.newDfp(1.0e-20), 20);
55 RealFieldUnivariateFunction<Dfp> f = new RealFieldUnivariateFunction<Dfp>() {
56 @Override
57 public Dfp value(Dfp x) {
58 Dfp one = field.getOne();
59 Dfp oneHalf = one.divide(2);
60 Dfp xMo = x.subtract(one);
61 Dfp xMh = x.subtract(oneHalf);
62 Dfp xPh = x.add(oneHalf);
63 Dfp xPo = x.add(one);
64 return xMo.multiply(xMh).multiply(x).multiply(xPh).multiply(xPo);
65 }
66 };
67
68 Dfp result = solver.solve(20, f, field.newDfp(0.2), field.newDfp(0.9),
69 field.newDfp(0.4), AllowedSolution.BELOW_SIDE);
70 Assert.assertTrue(f.value(result).abs().lessThan(solver.getFunctionValueAccuracy()));
71 Assert.assertTrue(f.value(result).negativeOrNull());
72 Assert.assertTrue(result.subtract(field.newDfp(0.5)).subtract(solver.getAbsoluteAccuracy()).positiveOrNull());
73 result = solver.solve(20, f, field.newDfp(-0.9), field.newDfp(-0.2),
74 field.newDfp(-0.4), AllowedSolution.ABOVE_SIDE);
75 Assert.assertTrue(f.value(result).abs().lessThan(solver.getFunctionValueAccuracy()));
76 Assert.assertTrue(f.value(result).positiveOrNull());
77 Assert.assertTrue(result.add(field.newDfp(0.5)).subtract(solver.getAbsoluteAccuracy()).negativeOrNull());
78 }
79
80 @Test
81 public void testNeta() {
82
83
84
85
86
87 for (AllowedSolution allowed : AllowedSolution.values()) {
88 check(new RealFieldUnivariateFunction<Dfp>() {
89 @Override
90 public Dfp value(Dfp x) {
91 return DfpMath.sin(x).subtract(x.divide(2));
92 }
93 }, 200, -2.0, 2.0, allowed);
94
95 check(new RealFieldUnivariateFunction<Dfp>() {
96 @Override
97 public Dfp value(Dfp x) {
98 return DfpMath.pow(x, 5).add(x).subtract(field.newDfp(10000));
99 }
100 }, 200, -5.0, 10.0, allowed);
101
102 check(new RealFieldUnivariateFunction<Dfp>() {
103 @Override
104 public Dfp value(Dfp x) {
105 return x.sqrt().subtract(field.getOne().divide(x)).subtract(field.newDfp(3));
106 }
107 }, 200, 0.001, 10.0, allowed);
108
109 check(new RealFieldUnivariateFunction<Dfp>() {
110 @Override
111 public Dfp value(Dfp x) {
112 return DfpMath.exp(x).add(x).subtract(field.newDfp(20));
113 }
114 }, 200, -5.0, 5.0, allowed);
115
116 check(new RealFieldUnivariateFunction<Dfp>() {
117 @Override
118 public Dfp value(Dfp x) {
119 return DfpMath.log(x).add(x.sqrt()).subtract(field.newDfp(5));
120 }
121 }, 200, 0.001, 10.0, allowed);
122
123 check(new RealFieldUnivariateFunction<Dfp>() {
124 @Override
125 public Dfp value(Dfp x) {
126 return x.subtract(field.getOne()).multiply(x).multiply(x).subtract(field.getOne());
127 }
128 }, 200, -0.5, 1.5, allowed);
129 }
130 }
131
132 private void check(RealFieldUnivariateFunction<Dfp> f, int maxEval, double min, double max,
133 AllowedSolution allowedSolution) {
134 FieldBracketingNthOrderBrentSolver<Dfp> solver =
135 new FieldBracketingNthOrderBrentSolver<>(relativeAccuracy, absoluteAccuracy,
136 functionValueAccuracy, 20);
137 Dfp xResult = solver.solve(maxEval, f, field.newDfp(min), field.newDfp(max),
138 allowedSolution);
139 Dfp yResult = f.value(xResult);
140 boolean increasing;
141 switch (allowedSolution) {
142 case ANY_SIDE :
143 Assert.assertTrue(yResult.abs().lessThan(functionValueAccuracy.multiply(2)));
144 break;
145 case LEFT_SIDE :
146 increasing = f.value(xResult).add(absoluteAccuracy).greaterThan(yResult);
147 Assert.assertTrue(increasing ? yResult.negativeOrNull() : yResult.positiveOrNull());
148 break;
149 case RIGHT_SIDE :
150 increasing = f.value(xResult).add(absoluteAccuracy).greaterThan(yResult);
151 Assert.assertTrue(increasing ? yResult.positiveOrNull() : yResult.negativeOrNull());
152 break;
153 case BELOW_SIDE :
154 Assert.assertTrue(yResult.negativeOrNull());
155 break;
156 case ABOVE_SIDE :
157 Assert.assertTrue(yResult.positiveOrNull());
158 break;
159 default :
160
161 throw new MathInternalError(null);
162 }
163 }
164
165 @Before
166 public void setUp() {
167 field = new DfpField(50);
168 absoluteAccuracy = field.newDfp(1.0e-45);
169 relativeAccuracy = field.newDfp(1.0e-45);
170 functionValueAccuracy = field.newDfp(1.0e-45);
171 }
172
173 private DfpField field;
174 private Dfp absoluteAccuracy;
175 private Dfp relativeAccuracy;
176 private Dfp functionValueAccuracy;
177 }