1   /* Copyright 2002-2025 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS 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    *   http://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  package org.orekit.estimation.measurements.gnss;
18  
19  import org.hipparchus.linear.MatrixUtils;
20  import org.hipparchus.linear.RealMatrix;
21  import org.hipparchus.random.RandomGenerator;
22  import org.hipparchus.random.Well19937a;
23  import org.hipparchus.util.FastMath;
24  import org.hipparchus.util.MathArrays;
25  import org.hipparchus.util.MathArrays.Position;
26  import org.junit.jupiter.api.Assertions;
27  import org.junit.jupiter.api.Test;
28  
29  import java.io.FileNotFoundException;
30  import java.io.UnsupportedEncodingException;
31  import java.util.Arrays;
32  
33  public class IntegerBootstrappingTest {
34  
35  
36      /** test the resolution for the tiberius example. */
37      @Test
38      public void testJoostenTiberiusFAQ() {
39          // this test corresponds to the "LAMBDA: FAQs" paper by Peter Joosten and Christian Tiberius
40  
41          final double[] floatAmbiguities = new double[] {
42              5.450, 3.100, 2.970
43          };
44          final int[] indirection = new int[] { 0, 1, 2 };
45          final RealMatrix covariance = MatrixUtils.createRealMatrix(new double[][] {
46              { 6.290, 5.978, 0.544 },
47              { 5.978, 6.292, 2.340 },
48              { 0.544, 2.340, 6.288 }
49          });
50  
51          final IntegerBootstrapping bootstrap = new IntegerBootstrapping(0.8);
52          IntegerLeastSquareSolution[] solutions = bootstrap.solveILS(1, floatAmbiguities, indirection, covariance);
53          if (solutions.length != 0) {
54              Assertions.assertTrue(solutions.length == 1);
55          }
56      }
57  
58      @Test
59      public void testRandomProblems() throws FileNotFoundException, UnsupportedEncodingException {
60          RandomGenerator random = new Well19937a(0x1c68f36088a9133al);
61          int[] count = new int[3];
62          for (int k = 0; k < 10000; ++k) {
63              // generate random test data
64              final int        n           = FastMath.max(2, 1 + random.nextInt(20));
65              final RealMatrix covariance  = createRandomSymmetricPositiveDefiniteMatrix(n, random);
66              final int[]      indirection = createRandomIndirectionArray(n, random);
67  
68              // perform decomposition test
69              ++ count[doTestILS(random, indirection, covariance)];
70          }
71  
72          Assertions.assertEquals(  50, count[0]);
73          Assertions.assertEquals(9950, count[1]);
74  
75      }
76  
77      @Test
78      public void testEquals() {
79          // Initialize comparator
80          final IntegerLeastSquareComparator comparator = new IntegerLeastSquareComparator();
81          // Verify
82          Assertions.assertEquals(0,  comparator.compare(new IntegerLeastSquareSolution(new long[] { 1l, 2l, 3l}, 4.0), new IntegerLeastSquareSolution(new long[] { 9l, 9l, 9l}, 4.0)));
83          Assertions.assertEquals(-1, comparator.compare(new IntegerLeastSquareSolution(new long[] { 1l, 2l, 3l}, 4.0), new IntegerLeastSquareSolution(new long[] { 9l, 9l, 9l}, 9.0)));
84      }
85  
86      private int doTestILS(final RandomGenerator random,
87                            final int[] indirection, final RealMatrix covariance) {
88          final double[] floatAmbiguities = new double[indirection.length];
89          for (int i = 0; i < floatAmbiguities.length; ++i) {
90              floatAmbiguities[i] = 2 * random.nextDouble() - 1.0;
91          }
92          IntegerBootstrapping bootstrap = new IntegerBootstrapping(0.3);
93          final IntegerLeastSquareSolution[] solutions =
94                          bootstrap.solveILS(1, floatAmbiguities, indirection, covariance);
95  
96          // check solution exist if and only if its probability great enough
97          if (solutions.length != 0) {
98              Assertions.assertTrue(1 / (solutions[0].getSquaredDistance()) > 0.3);
99          }
100 
101         return solutions.length;
102 
103     }
104 
105     protected RealMatrix createRandomSymmetricPositiveDefiniteMatrix(final int n, final RandomGenerator random) {
106         final RealMatrix matrix = MatrixUtils.createRealMatrix(n, n);
107         for (int i = 0; i < n; ++i) {
108             for (int j = 0; j < n; ++j) {
109                 matrix.setEntry(i, j, 20 * random.nextDouble() - 10);
110             }
111         }
112         return matrix.transposeMultiply(matrix);
113     }
114 
115     RealMatrix filterCovariance(final RealMatrix covariance, int[] indirection) {
116         RealMatrix filtered = MatrixUtils.createRealMatrix(indirection.length, indirection.length);
117         for (int i = 0; i < indirection.length; ++i) {
118             for (int j = 0; j <= i; ++j) {
119                 filtered.setEntry(i, j, covariance.getEntry(indirection[i], indirection[j]));
120                 filtered.setEntry(j, i, covariance.getEntry(indirection[i], indirection[j]));
121             }
122         }
123         return filtered;
124     }
125 
126     protected int[] createRandomIndirectionArray(final int n, final RandomGenerator random) {
127         final int[] all = new int[n];
128         for (int i = 0; i < all.length; ++i) {
129             all[i] = i;
130         }
131         MathArrays.shuffle(all, 0, Position.TAIL, random);
132         return Arrays.copyOf(all, FastMath.max(2, 1 + random.nextInt(n)));
133     }
134 
135 
136 
137 }