1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.hipparchus.analysis.differentiation;
19
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.Field;
22 import org.hipparchus.exception.LocalizedCoreFormats;
23 import org.hipparchus.exception.MathIllegalArgumentException;
24 import org.hipparchus.linear.FieldQRDecomposer;
25 import org.hipparchus.util.Binary64Field;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.MathArrays;
28 import org.junit.jupiter.api.Test;
29
30 import java.lang.reflect.Array;
31
32 import static org.junit.jupiter.api.Assertions.assertEquals;
33 import static org.junit.jupiter.api.Assertions.fail;
34
35
36
37
38 class FieldTaylorMapTest {
39
40 @Test
41 void testNullPoint() {
42 doTestNullPoint(Binary64Field.getInstance());
43 }
44
45 @Test
46 void testDim0Point() {
47 doTestDim0Point(Binary64Field.getInstance());
48 }
49
50 @Test
51 void testNullFunctions() {
52 doTestNullFunctions(Binary64Field.getInstance());
53 }
54
55 @Test
56 void testNoFunctions() {
57 doTestNoFunctions(Binary64Field.getInstance());
58 }
59
60 @Test
61 void testIncompatiblePointAndFunctions() {
62 doTestIncompatiblePointAndFunctions(Binary64Field.getInstance());
63 }
64
65 @Test
66 void testIncompatible() {
67 doTestIncompatible(Binary64Field.getInstance());
68 }
69
70 @Test
71 void testNbParameters() {
72 doTestNbParameters(Binary64Field.getInstance());
73 }
74
75 @Test
76 void testNbFunctions() {
77 doTestNbFunctions(Binary64Field.getInstance());
78 }
79
80 @Test
81 void testIdentity() {
82 doTestIdentity(Binary64Field.getInstance());
83 }
84
85 @Test
86 void testValue() {
87 doTestValue(Binary64Field.getInstance());
88 }
89
90 @Test
91 void testCompose() {
92 doTestCompose(Binary64Field.getInstance());
93 }
94
95 @Test
96 void testInvertNonSquare() {
97 doTestInvertNonSquare(Binary64Field.getInstance());
98 }
99
100 @Test
101 void testInvertMonoDimensional() {
102 doTestInvertMonoDimensional(Binary64Field.getInstance());
103 }
104
105 @Test
106 void testInvertBiDimensional() {
107 doTestInvertBiDimensional(Binary64Field.getInstance());
108 }
109
110 @SuppressWarnings("unchecked")
111 private <T extends CalculusFieldElement<T>> void doTestNullPoint(final Field<T> field) {
112 try {
113 new FieldTaylorMap<>(null, (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 2));
114 fail("an exception should have been thrown");
115 } catch (MathIllegalArgumentException miae) {
116 assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
117 assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
118 }
119 }
120
121 @SuppressWarnings("unchecked")
122 private <T extends CalculusFieldElement<T>> void doTestDim0Point(final Field<T> field) {
123 try {
124 new FieldTaylorMap<>(MathArrays.buildArray(field, 0), (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 2));
125 fail("an exception should have been thrown");
126 } catch (MathIllegalArgumentException miae) {
127 assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
128 assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
129 }
130 }
131
132 private <T extends CalculusFieldElement<T>> void doTestNullFunctions(final Field<T> field) {
133 try {
134 new FieldTaylorMap<>(MathArrays.buildArray(field, 2), null);
135 fail("an exception should have been thrown");
136 } catch (MathIllegalArgumentException miae) {
137 assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
138 assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
139 }
140 }
141
142 @SuppressWarnings("unchecked")
143 private <T extends CalculusFieldElement<T>> void doTestNoFunctions(final Field<T> field) {
144 try {
145 new FieldTaylorMap<>(MathArrays.buildArray(field, 2), (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 0));
146 fail("an exception should have been thrown");
147 } catch (MathIllegalArgumentException miae) {
148 assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
149 assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
150 }
151 }
152
153 private <T extends CalculusFieldElement<T>> void doTestIncompatiblePointAndFunctions(final Field<T> field) {
154 FDSFactory<T> factory = new FDSFactory<>(field, 6, 6);
155 @SuppressWarnings("unchecked")
156 FieldDerivativeStructure<T>[] functions = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class,
157 factory.getCompiler().getFreeParameters());
158 for (int i = 0; i < functions.length; ++i) {
159 functions[i] = factory.constant(0);
160 }
161 try {
162 new FieldTaylorMap<>(MathArrays.buildArray(field, functions.length - 1), functions);
163 fail("an exception should have been thrown");
164 } catch (MathIllegalArgumentException miae) {
165 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
166 assertEquals(5, ((Integer) miae.getParts()[0]).intValue());
167 assertEquals(6, ((Integer) miae.getParts()[1]).intValue());
168 }
169 }
170
171 private <T extends CalculusFieldElement<T>> void doTestIncompatible(final Field<T> field) {
172 FDSFactory<T> factory = new FDSFactory<>(field, 6, 6);
173 @SuppressWarnings("unchecked")
174 FieldDerivativeStructure<T>[] functions = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class,
175 factory.getCompiler().getFreeParameters());
176 for (int i = 0; i < functions.length - 1; ++i) {
177 functions[i] = factory.constant(0);
178 }
179 functions[functions.length - 1] = new FDSFactory<>(field,
180 factory.getCompiler().getFreeParameters(),
181 factory.getCompiler().getOrder() - 1).
182 constant(1.0);
183 try {
184 new FieldTaylorMap<>(MathArrays.buildArray(field, functions.length), functions);
185 fail("an exception should have been thrown");
186 } catch (MathIllegalArgumentException miae) {
187 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
188 assertEquals(6, ((Integer) miae.getParts()[0]).intValue());
189 assertEquals(5, ((Integer) miae.getParts()[1]).intValue());
190 }
191 }
192
193 private <T extends CalculusFieldElement<T>> void doTestNbParameters(final Field<T> field) {
194 final int nbParameters = 6;
195 final int nbFunctions = 3;
196 FDSFactory<T> factory = new FDSFactory<>(field, nbParameters, 6);
197 @SuppressWarnings("unchecked")
198 FieldDerivativeStructure<T>[] functions = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class,
199 nbFunctions);
200 for (int i = 0; i < functions.length; ++i) {
201 functions[i] = factory.constant(0);
202 }
203 assertEquals(nbParameters,
204 new FieldTaylorMap<>(MathArrays.buildArray(field, nbParameters), functions).getFreeParameters());
205 }
206
207 private <T extends CalculusFieldElement<T>> void doTestNbFunctions(final Field<T> field) {
208 final int nbParameters = 6;
209 final int nbFunctions = 3;
210 FDSFactory<T> factory = new FDSFactory<>(field, nbParameters, 6);
211 @SuppressWarnings("unchecked")
212 FieldDerivativeStructure<T>[] functions = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class,
213 nbFunctions);
214 for (int i = 0; i < functions.length; ++i) {
215 functions[i] = factory.constant(0);
216 }
217 assertEquals(nbFunctions,
218 new FieldTaylorMap<>(MathArrays.buildArray(field, nbParameters), functions).getNbFunctions());
219 }
220
221 private <T extends CalculusFieldElement<T>> void doTestIdentity(final Field<T> field) {
222 final FieldTaylorMap<T> map = new FieldTaylorMap<>(field, 7, 3, 4);
223 for (int i = 0; i < map.getNbFunctions(); ++i) {
224
225 final FieldDerivativeStructure<T> mi = map.getFunction(i);
226
227 assertEquals(0.0, mi.getValue().getReal(), 1.0e-15);
228
229 int[] orders = new int[7];
230 orders[i] = 1;
231 int expectedOne = mi.getFactory().getCompiler().getPartialDerivativeIndex(orders);
232
233 for (int j = 0; j < mi.getFactory().getCompiler().getSize(); ++j) {
234 assertEquals(j == expectedOne ? 1.0 : 0.0, mi.getAllDerivatives()[j].getReal(), 1.0e-15);
235 }
236
237 }
238 }
239
240 @SuppressWarnings("unchecked")
241 private <T extends CalculusFieldElement<T>> void doTestValue(final Field<T> field) {
242
243 final FDSFactory<T> factory = new FDSFactory<>(field, 2, 3);
244 final FieldDerivativeStructure<T> p0 = factory.variable(0, field.getZero().newInstance( 1.0));
245 final FieldDerivativeStructure<T> p1 = factory.variable(1, field.getZero().newInstance(-3.0));
246 final FieldDerivativeStructure<T> f0 = p0.sin();
247 final FieldDerivativeStructure<T> f1 = p0.add(p1);
248 final T[] p = MathArrays.buildArray(field, 2);
249 p[0] = p0.getValue();
250 p[1] = p1.getValue();
251 final FieldDerivativeStructure<T>[] f = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 2);
252 f[0] = f0;
253 f[1] = f1;
254 final FieldTaylorMap<T> map = new FieldTaylorMap<>(p, f);
255
256 for (double dp0 = -0.1; dp0 < 0.1; dp0 += 0.01) {
257 final T dp0T = field.getZero().newInstance(dp0);
258 for (double dp1 = -0.1; dp1 < 0.1; dp1 += 0.01) {
259 final T dp1T = field.getZero().newInstance(dp1);
260 assertEquals(f0.taylor(dp0, dp1).getReal(), map.value(dp0, dp1)[0].getReal(), 1.0e-15);
261 assertEquals(f1.taylor(dp0, dp1).getReal(), map.value(dp0, dp1)[1].getReal(), 1.0e-15);
262 assertEquals(f0.taylor(dp0, dp1).getReal(), map.value(dp0T, dp1T)[0].getReal(), 1.0e-15);
263 assertEquals(f1.taylor(dp0, dp1).getReal(), map.value(dp0T, dp1T)[1].getReal(), 1.0e-15);
264 }
265 }
266
267 }
268
269 private <T extends CalculusFieldElement<T>> void doTestCompose(final Field<T> field) {
270
271 final FDSFactory<T> factory2 = new FDSFactory<>(field, 2, 2);
272 final FDSFactory<T> factory3 = new FDSFactory<>(field, 3, factory2.getCompiler().getOrder());
273 final FieldDerivativeStructure<T> p0 = factory2.variable(0, 1.0);
274 final FieldDerivativeStructure<T> p1 = factory2.variable(1, -3.0);
275 final FieldDerivativeStructure<T> g0 = p0.sin();
276 final FieldDerivativeStructure<T> g1 = p0.add(p1);
277 final FieldDerivativeStructure<T> g2 = p1.multiply(p0);
278 final FieldDerivativeStructure<T> f0 = factory3.variable(0, g0.getValue()).
279 add(factory3.variable(1, g1.getValue()));
280 final FieldDerivativeStructure<T> f1 = factory3.variable(0, g0.getValue()).
281 subtract(factory3.variable(1, g1.getValue())).
282 add(factory3.variable(2, g2.getValue()));
283 final T[] p = MathArrays.buildArray(field, 2);
284 p[0] = p0.getValue();
285 p[1] = p1.getValue();
286 @SuppressWarnings("unchecked")
287 final FieldDerivativeStructure<T>[] g = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 3);
288 g[0] = g0;
289 g[1] = g1;
290 g[2] = g2;
291 final T[] gT = MathArrays.buildArray(field, 3);
292 gT[0] = g0.getValue();
293 gT[1] = g1.getValue();
294 gT[2] = g2.getValue();
295 @SuppressWarnings("unchecked")
296 final FieldDerivativeStructure<T>[] f = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 2);
297 f[0] = f0;
298 f[1] = f1;
299 final FieldTaylorMap<T> mapG = new FieldTaylorMap<>(p, g);
300 final FieldTaylorMap<T> mapF = new FieldTaylorMap<>(gT, f);
301 final FieldTaylorMap<T> composed = mapF.compose(mapG);
302
303 for (double dp0 = -0.1; dp0 < 0.1; dp0 += 0.01) {
304 for (double dp1 = -0.1; dp1 < 0.1; dp1 += 0.01) {
305 assertEquals(g0.taylor(dp0, dp1).add(g1.taylor(dp0, dp1)).getReal(),
306 composed.value(dp0, dp1)[0].getReal(),
307 1.0e-15);
308 assertEquals(g0.taylor(dp0, dp1).subtract(g1.taylor(dp0, dp1)).add(g2.taylor(dp0, dp1)).getReal(),
309 composed.value(dp0, dp1)[1].getReal(),
310 1.0e-15);
311 }
312 }
313
314 assertEquals(p0.getValue().getReal(), mapG.getPoint()[0].getReal(), 1.0e-15);
315 assertEquals(p1.getValue().getReal(), mapG.getPoint()[1].getReal(), 1.0e-15);
316 assertEquals(g0.getValue().getReal(), mapF.getPoint()[0].getReal(), 1.0e-15);
317 assertEquals(g1.getValue().getReal(), mapF.getPoint()[1].getReal(), 1.0e-15);
318 assertEquals(g2.getValue().getReal(), mapF.getPoint()[2].getReal(), 1.0e-15);
319 assertEquals(p0.getValue().getReal(), composed.getPoint()[0].getReal(), 1.0e-15);
320 assertEquals(p1.getValue().getReal(), composed.getPoint()[1].getReal(), 1.0e-15);
321
322
323 assertEquals(+1.0, mapF.getFunction(0).getPartialDerivative(1, 0, 0).getReal(), 1.0e-15);
324 assertEquals(+1.0, mapF.getFunction(0).getPartialDerivative(0, 1, 0).getReal(), 1.0e-15);
325 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 0, 1).getReal(), 1.0e-15);
326 assertEquals(+1.0, mapF.getFunction(1).getPartialDerivative(1, 0, 0).getReal(), 1.0e-15);
327 assertEquals(-1.0, mapF.getFunction(1).getPartialDerivative(0, 1, 0).getReal(), 1.0e-15);
328 assertEquals(+1.0, mapF.getFunction(1).getPartialDerivative(0, 0, 1).getReal(), 1.0e-15);
329
330 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(2, 0, 0).getReal(), 1.0e-15);
331 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(1, 1, 0).getReal(), 1.0e-15);
332 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(1, 0, 1).getReal(), 1.0e-15);
333 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 2, 0).getReal(), 1.0e-15);
334 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 1, 1).getReal(), 1.0e-15);
335 assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 0, 2).getReal(), 1.0e-15);
336 assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(2, 0, 0).getReal(), 1.0e-15);
337 assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(1, 1, 0).getReal(), 1.0e-15);
338 assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(1, 0, 1).getReal(), 1.0e-15);
339 assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(0, 2, 0).getReal(), 1.0e-15);
340 assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(0, 1, 1).getReal(), 1.0e-15);
341 assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(0, 0, 2).getReal(), 1.0e-15);
342
343
344 assertEquals(FastMath.cos(p0.getValue()).getReal() + 1.0, composed.getFunction(0).getPartialDerivative(1, 0).getReal(), 1.0e-15);
345 assertEquals(+1.0, composed.getFunction(0).getPartialDerivative(0, 1).getReal(), 1.0e-15);
346 assertEquals(FastMath.cos(p0.getValue()).getReal() - 1.0 + p1.getValue().getReal(), composed.getFunction(1).getPartialDerivative(1, 0).getReal(), 1.0e-15);
347 assertEquals(-1.0 + p0.getValue().getReal(), composed.getFunction(1).getPartialDerivative(0, 1).getReal(), 1.0e-15);
348 assertEquals(-FastMath.sin(p0.getValue()).getReal(), composed.getFunction(0).getPartialDerivative(2, 0).getReal(), 1.0e-15);
349 assertEquals( 0.0, composed.getFunction(0).getPartialDerivative(1, 1).getReal(), 1.0e-15);
350 assertEquals( 0.0, composed.getFunction(0).getPartialDerivative(0, 2).getReal(), 1.0e-15);
351 assertEquals(-FastMath.sin(p0.getValue()).getReal(), composed.getFunction(1).getPartialDerivative(2, 0).getReal(), 1.0e-15);
352 assertEquals(+1.0, composed.getFunction(1).getPartialDerivative(1, 1).getReal(), 1.0e-15);
353 assertEquals( 0.0, composed.getFunction(1).getPartialDerivative(0, 2).getReal(), 1.0e-15);
354
355 }
356
357 private <T extends CalculusFieldElement<T>> void doTestInvertNonSquare(final Field<T> field) {
358 final FDSFactory<T> factory = new FDSFactory<>(field, 2, 2);
359 final FieldDerivativeStructure<T> p0 = factory.variable(0, 1.0);
360 final FieldDerivativeStructure<T> p1 = factory.variable(1, -3.0);
361 final T[] p = MathArrays.buildArray(field, 2);
362 p[0] = p0.getValue();
363 p[1] = p1.getValue();
364 @SuppressWarnings("unchecked")
365 final FieldDerivativeStructure<T>[] f = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 3);
366 f[0] = p0;
367 f[1] = p1;
368 f[2] = p0.add(p1);
369 final FieldTaylorMap<T> nonSquare = new FieldTaylorMap<>(p, f);
370 assertEquals(2, nonSquare.getFreeParameters());
371 assertEquals(3, nonSquare.getNbFunctions());
372 try {
373 nonSquare.invert(new FieldQRDecomposer<>(field.getZero().newInstance(1.0e-10)));
374 fail("an exception should have been thrown");
375 } catch (MathIllegalArgumentException miae) {
376 assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
377 assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
378 assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
379 }
380 }
381
382 private <T extends CalculusFieldElement<T>> void doTestInvertMonoDimensional(final Field<T> field) {
383 final FDSFactory<T> factory = new FDSFactory<>(field, 1, 6);
384 for (double x = 0.0; x < 3.0; x += 0.01) {
385 final FieldDerivativeStructure<T> xDS = factory.variable(0, x);
386 final T[] p = MathArrays.buildArray(field, 1);
387 p[0] = xDS.getValue();
388 @SuppressWarnings("unchecked")
389 final FieldDerivativeStructure<T>[] f = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 1);
390 f[0] = xDS.exp();
391 final FieldTaylorMap<T> expMap = new FieldTaylorMap<>(p, f);
392 final FieldTaylorMap<T> inverse = expMap.invert(new FieldQRDecomposer<>(field.getZero().newInstance(1.0e-10)));
393 final FieldDerivativeStructure<T> log = factory.variable(0, expMap.getFunction(0).getValue()).log();
394 FieldDerivativeStructureAbstractTest.checkEquals(log, inverse.getFunction(0), 4.7e-13);
395 }
396 }
397
398 private <T extends CalculusFieldElement<T>> void doTestInvertBiDimensional(final Field<T> field) {
399 final FDSFactory<T> factory = new FDSFactory<>(field, 2, 4);
400 for (double x = -2.0 + FastMath.scalb(1.0, -6); x < 2.0; x += FastMath.scalb(1.0, -5)) {
401 final FieldDerivativeStructure<T> xDS = factory.variable(0, x);
402 for (double y = -2.0 + FastMath.scalb(1.0, -6); y < 2.0; y += FastMath.scalb(1.0, -5)) {
403 final FieldDerivativeStructure<T> yDS = factory.variable(1, y);
404 final T[] p = MathArrays.buildArray(field, 2);
405 p[0] = xDS.getValue();
406 p[1] = yDS.getValue();
407 @SuppressWarnings("unchecked")
408 final FieldDerivativeStructure<T>[] f = (FieldDerivativeStructure<T>[]) Array.newInstance(FieldDerivativeStructure.class, 2);
409 f[0] = FastMath.hypot(xDS, yDS);
410 f[1] = FastMath.atan2(yDS, xDS);
411 final FieldTaylorMap<T> polarMap = new FieldTaylorMap<>(p, f);
412 final FieldTaylorMap<T> cartMap = polarMap.invert(new FieldQRDecomposer<>(field.getZero().newInstance(1.0e-10)));
413 final FieldTaylorMap<T> idMap = cartMap.compose(polarMap);
414 FieldDerivativeStructureAbstractTest.checkEquals(xDS, idMap.getFunction(0), 2.8e-9);
415 FieldDerivativeStructureAbstractTest.checkEquals(yDS, idMap.getFunction(1), 2.8e-9);
416 }
417 }
418 }
419
420 }