View Javadoc
1   /*
2    * Licensed to the Hipparchus project under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.hipparchus.analysis.differentiation;
19  
20  import org.hipparchus.exception.LocalizedCoreFormats;
21  import org.hipparchus.exception.MathIllegalArgumentException;
22  import org.hipparchus.linear.QRDecomposer;
23  import org.hipparchus.util.FastMath;
24  import org.junit.Assert;
25  import org.junit.Test;
26  
27  /**
28   * Test for class {@link TaylorMap}.
29   */
30  public class TaylorMapTest {
31  
32      @Test
33      public void testNullPoint() {
34          try {
35              new TaylorMap(null, new DerivativeStructure[2]);
36              Assert.fail("an exception should have been thrown");
37          } catch (MathIllegalArgumentException miae) {
38              Assert.assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
39              Assert.assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
40          }
41      }
42  
43      @Test
44      public void testDim0Point() {
45          try {
46              new TaylorMap(new double[0], new DerivativeStructure[2]);
47              Assert.fail("an exception should have been thrown");
48          } catch (MathIllegalArgumentException miae) {
49              Assert.assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
50              Assert.assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
51          }
52      }
53  
54      @Test
55      public void testNullFunctions() {
56          try {
57              new TaylorMap(new double[2], null);
58              Assert.fail("an exception should have been thrown");
59          } catch (MathIllegalArgumentException miae) {
60              Assert.assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
61              Assert.assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
62          }
63      }
64  
65      @Test
66      public void testNoFunctions() {
67          try {
68              new TaylorMap(new double[2], new DerivativeStructure[0]);
69              Assert.fail("an exception should have been thrown");
70          } catch (MathIllegalArgumentException miae) {
71              Assert.assertEquals(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, miae.getSpecifier());
72              Assert.assertEquals(0, ((Integer) miae.getParts()[0]).intValue());
73          }
74      }
75  
76      @Test
77      public void testIncompatiblePointAndFunctions() {
78          DSFactory factory = new DSFactory(6, 6);
79          DerivativeStructure[] functions = new DerivativeStructure[factory.getCompiler().getFreeParameters()];
80          for (int i = 0; i < functions.length; ++i) {
81              functions[i] = factory.constant(0);
82          }
83          try {
84              new TaylorMap(new double[functions.length - 1], functions);
85              Assert.fail("an exception should have been thrown");
86          } catch (MathIllegalArgumentException miae) {
87              Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
88              Assert.assertEquals(5, ((Integer) miae.getParts()[0]).intValue());
89              Assert.assertEquals(6, ((Integer) miae.getParts()[1]).intValue());
90          }
91      }
92  
93      @Test
94      public void testIncompatible() {
95          DSFactory factory = new DSFactory(6, 6);
96          DerivativeStructure[] functions = new DerivativeStructure[factory.getCompiler().getFreeParameters()];
97          for (int i = 0; i < functions.length - 1; ++i) {
98              functions[i] = factory.constant(0);
99          }
100         functions[functions.length - 1] = new DSFactory(factory.getCompiler().getFreeParameters(),
101                                                         factory.getCompiler().getOrder() - 1).
102                                           constant(1.0);
103         try {
104             new TaylorMap(new double[functions.length], functions);
105             Assert.fail("an exception should have been thrown");
106         } catch (MathIllegalArgumentException miae) {
107             Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
108             Assert.assertEquals(6, ((Integer) miae.getParts()[0]).intValue());
109             Assert.assertEquals(5, ((Integer) miae.getParts()[1]).intValue());
110         }
111     }
112 
113     @Test
114     public void testNbParameters() {
115         final int nbParameters = 6;
116         final int nbFunctions  = 3;
117         DSFactory factory = new DSFactory(nbParameters, 6);
118         DerivativeStructure[] functions = new DerivativeStructure[nbFunctions];
119         for (int i = 0; i < functions.length; ++i) {
120             functions[i] = factory.constant(0);
121         }
122         Assert.assertEquals(nbParameters,
123                             new TaylorMap(new double[nbParameters], functions).getFreeParameters());
124     }
125 
126     @Test
127     public void testNbFunctions() {
128         final int nbParameters = 6;
129         final int nbFunctions  = 3;
130         DSFactory factory = new DSFactory(nbParameters, 6);
131         DerivativeStructure[] functions = new DerivativeStructure[nbFunctions];
132         for (int i = 0; i < functions.length; ++i) {
133             functions[i] = factory.constant(0);
134         }
135         Assert.assertEquals(nbFunctions,
136                             new TaylorMap(new double[nbParameters], functions).getNbFunctions());
137     }
138 
139     @Test
140     public void testIdentity() {
141         final TaylorMap map = new TaylorMap(7, 3, 4);
142         for (int i = 0; i < map.getNbFunctions(); ++i) {
143 
144             final DerivativeStructure mi = map.getFunction(i);
145 
146             Assert.assertEquals(0.0, mi.getValue(), 1.0e-15);
147 
148             int[] orders = new int[7];
149             orders[i] = 1;
150             int expectedOne = mi.getFactory().getCompiler().getPartialDerivativeIndex(orders);
151 
152             for (int j = 0; j < mi.getFactory().getCompiler().getSize(); ++j) {
153                 Assert.assertEquals(j == expectedOne ? 1.0 : 0.0, mi.getAllDerivatives()[j], 1.0e-15);
154             }
155 
156         }
157     }
158 
159     @Test
160     public void testValue() {
161 
162         final DSFactory           factory = new DSFactory(2, 3);
163         final DerivativeStructure p0      = factory.variable(0,  1.0);
164         final DerivativeStructure p1      = factory.variable(1, -3.0);
165         final DerivativeStructure f0      = p0.sin();
166         final DerivativeStructure f1      = p0.add(p1);
167         final TaylorMap           map     = new TaylorMap(new double[] { p0.getValue(), p1.getValue() },
168                                                           new DerivativeStructure[] { f0, f1 });
169 
170         for (double dp0 = -0.1; dp0 < 0.1; dp0 += 0.01) {
171             for (double dp1 = -0.1; dp1 < 0.1; dp1 += 0.01) {
172                 Assert.assertEquals(f0.taylor(dp0, dp1), map.value(dp0, dp1)[0], 1.0e-15);
173                 Assert.assertEquals(f1.taylor(dp0, dp1), map.value(dp0, dp1)[1], 1.0e-15);
174             }
175         }
176 
177     }
178 
179     @Test
180     public void testCompose() {
181 
182         final DSFactory           factory2 = new DSFactory(2, 2);
183         final DSFactory           factory3 = new DSFactory(3, factory2.getCompiler().getOrder());
184         final DerivativeStructure p0       = factory2.variable(0,  1.0);
185         final DerivativeStructure p1       = factory2.variable(1, -3.0);
186         final DerivativeStructure g0       = p0.sin();
187         final DerivativeStructure g1       = p0.add(p1);
188         final DerivativeStructure g2       = p1.multiply(p0);
189         final DerivativeStructure f0       = factory3.variable(0,  g0.getValue()).
190                                              add(factory3.variable(1, g1.getValue()));
191         final DerivativeStructure f1       = factory3.variable(0,  g0.getValue()).
192                                              subtract(factory3.variable(1, g1.getValue())).
193                                              add(factory3.variable(2, g2.getValue()));
194         final TaylorMap           mapG     = new TaylorMap(new double[] { p0.getValue(), p1.getValue() },
195                                                            new DerivativeStructure[] { g0, g1, g2 });
196         final TaylorMap           mapF     = new TaylorMap(new double[] { g0.getValue(), g1.getValue(), g2.getValue() },
197                                                            new DerivativeStructure[] { f0, f1 });
198         final TaylorMap           composed = mapF.compose(mapG);
199 
200         for (double dp0 = -0.1; dp0 < 0.1; dp0 += 0.01) {
201             for (double dp1 = -0.1; dp1 < 0.1; dp1 += 0.01) {
202                 Assert.assertEquals(g0.taylor(dp0, dp1) + g1.taylor(dp0, dp1),
203                                     composed.value(dp0, dp1)[0],
204                                     1.0e-15);
205                 Assert.assertEquals(g0.taylor(dp0, dp1) - g1.taylor(dp0, dp1) + g2.taylor(dp0, dp1),
206                                     composed.value(dp0, dp1)[1],
207                                     1.0e-15);
208             }
209         }
210 
211         Assert.assertEquals(p0.getValue(), mapG.getPoint()[0],     1.0e-15);
212         Assert.assertEquals(p1.getValue(), mapG.getPoint()[1],     1.0e-15);
213         Assert.assertEquals(g0.getValue(), mapF.getPoint()[0],     1.0e-15);
214         Assert.assertEquals(g1.getValue(), mapF.getPoint()[1],     1.0e-15);
215         Assert.assertEquals(g2.getValue(), mapF.getPoint()[2],     1.0e-15);
216         Assert.assertEquals(p0.getValue(), composed.getPoint()[0], 1.0e-15);
217         Assert.assertEquals(p1.getValue(), composed.getPoint()[1], 1.0e-15);
218 
219         // the partial derivatives of f are only (∂f/∂g₀, ∂f/∂g₁, ∂f/∂g₂)
220         Assert.assertEquals(+1.0, mapF.getFunction(0).getPartialDerivative(1, 0, 0), 1.0e-15);
221         Assert.assertEquals(+1.0, mapF.getFunction(0).getPartialDerivative(0, 1, 0), 1.0e-15);
222         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 0, 1), 1.0e-15);
223         Assert.assertEquals(+1.0, mapF.getFunction(1).getPartialDerivative(1, 0, 0), 1.0e-15);
224         Assert.assertEquals(-1.0, mapF.getFunction(1).getPartialDerivative(0, 1, 0), 1.0e-15);
225         Assert.assertEquals(+1.0, mapF.getFunction(1).getPartialDerivative(0, 0, 1), 1.0e-15);
226 
227         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(2, 0, 0), 1.0e-15);
228         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(1, 1, 0), 1.0e-15);
229         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(1, 0, 1), 1.0e-15);
230         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 2, 0), 1.0e-15);
231         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 1, 1), 1.0e-15);
232         Assert.assertEquals( 0.0, mapF.getFunction(0).getPartialDerivative(0, 0, 2), 1.0e-15);
233         Assert.assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(2, 0, 0), 1.0e-15);
234         Assert.assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(1, 1, 0), 1.0e-15);
235         Assert.assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(1, 0, 1), 1.0e-15);
236         Assert.assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(0, 2, 0), 1.0e-15);
237         Assert.assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(0, 1, 1), 1.0e-15);
238         Assert.assertEquals( 0.0, mapF.getFunction(1).getPartialDerivative(0, 0, 2), 1.0e-15);
239 
240         // the partial derivatives of the composed map are (∂f/∂p₀, ∂f/∂p₁)
241         Assert.assertEquals(FastMath.cos(p0.getValue()) + 1.0,                 composed.getFunction(0).getPartialDerivative(1, 0), 1.0e-15);
242         Assert.assertEquals(+1.0,                                              composed.getFunction(0).getPartialDerivative(0, 1), 1.0e-15);
243         Assert.assertEquals(FastMath.cos(p0.getValue()) - 1.0 + p1.getValue(), composed.getFunction(1).getPartialDerivative(1, 0), 1.0e-15);
244         Assert.assertEquals(-1.0 + p0.getValue(),                              composed.getFunction(1).getPartialDerivative(0, 1), 1.0e-15);
245         Assert.assertEquals(-FastMath.sin(p0.getValue()),                      composed.getFunction(0).getPartialDerivative(2, 0), 1.0e-15);
246         Assert.assertEquals( 0.0,                                              composed.getFunction(0).getPartialDerivative(1, 1), 1.0e-15);
247         Assert.assertEquals( 0.0,                                              composed.getFunction(0).getPartialDerivative(0, 2), 1.0e-15);
248         Assert.assertEquals(-FastMath.sin(p0.getValue()),                      composed.getFunction(1).getPartialDerivative(2, 0), 1.0e-15);
249         Assert.assertEquals(+1.0,                                              composed.getFunction(1).getPartialDerivative(1, 1), 1.0e-15);
250         Assert.assertEquals( 0.0,                                              composed.getFunction(1).getPartialDerivative(0, 2), 1.0e-15);
251 
252     }
253 
254     @Test
255     public void testInvertNonSquare() {
256         final DSFactory           factory   = new DSFactory(2, 2);
257         final DerivativeStructure p0        = factory.variable(0,  1.0);
258         final DerivativeStructure p1        = factory.variable(1, -3.0);
259         final TaylorMap           nonSquare = new TaylorMap(new double[] { p0.getValue(), p1.getValue() },
260                                                             new DerivativeStructure[] { p0, p1, p0.add(p1) });
261         Assert.assertEquals(2, nonSquare.getFreeParameters());
262         Assert.assertEquals(3, nonSquare.getNbFunctions());
263         try {
264             nonSquare.invert(new QRDecomposer(1.0e-10));
265             Assert.fail("an exception should have been thrown");
266         } catch (MathIllegalArgumentException miae) {
267             Assert.assertEquals(LocalizedCoreFormats.DIMENSIONS_MISMATCH, miae.getSpecifier());
268             Assert.assertEquals(3, ((Integer) miae.getParts()[0]).intValue());
269             Assert.assertEquals(2, ((Integer) miae.getParts()[1]).intValue());
270         }
271     }
272 
273     @Test
274     public void testInvertMonoDimensional() {
275         final DSFactory factory = new DSFactory(1, 6);
276         for (double x = 0.0; x < 3.0; x += 0.01) {
277             final DerivativeStructure xDS = factory.variable(0, x);
278             final TaylorMap expMap = new TaylorMap(new double[] { xDS.getValue() },
279                                                    new DerivativeStructure[]  { xDS.exp() });
280             final TaylorMap inverse = expMap.invert(new QRDecomposer(1.0e-10));
281             final DerivativeStructure log = factory.variable(0, expMap.getFunction(0).getValue()).log();
282             DerivativeStructureTest.checkEquals(log, inverse.getFunction(0), 4.7e-13);
283         }
284     }
285 
286     @Test
287     public void testInvertBiDimensional() {
288         final DSFactory factory = new DSFactory(2, 4);
289         for (double x = -2.0 + FastMath.scalb(1.0, -6); x < 2.0; x += FastMath.scalb(1.0, -5)) {
290             final DerivativeStructure xDS = factory.variable(0, x);
291             for (double y = -2.0 + FastMath.scalb(1.0, -6); y < 2.0; y += FastMath.scalb(1.0, -5)) {
292                 final DerivativeStructure yDS = factory.variable(1, y);
293                 final TaylorMap polarMap = new TaylorMap(new double[] { xDS.getValue(), yDS.getValue() },
294                                                          new DerivativeStructure[]  { FastMath.hypot(xDS, yDS), FastMath.atan2(yDS, xDS)});
295                 final TaylorMap cartMap  = polarMap.invert(new QRDecomposer(1.0e-10));
296                 final TaylorMap idMap    = cartMap.compose(polarMap);
297                 DerivativeStructureTest.checkEquals(xDS, idMap.getFunction(0), 2.8e-9);
298                 DerivativeStructureTest.checkEquals(yDS, idMap.getFunction(1), 2.8e-9);
299             }
300         }
301     }
302 
303 }