View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) 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 ASF 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  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  
23  package org.hipparchus.linear;
24  
25  import org.hipparchus.util.FastMath;
26  import org.junit.jupiter.api.Test;
27  
28  import static org.junit.jupiter.api.Assertions.assertEquals;
29  import static org.junit.jupiter.api.Assertions.assertFalse;
30  import static org.junit.jupiter.api.Assertions.assertTrue;
31  
32  class BiDiagonalTransformerTest {
33  
34      private double[][] testSquare = {
35              { 24.0 / 25.0, 43.0 / 25.0 },
36              { 57.0 / 25.0, 24.0 / 25.0 }
37      };
38  
39      private double[][] testNonSquare = {
40          {  -540.0 / 625.0,  963.0 / 625.0, -216.0 / 625.0 },
41          { -1730.0 / 625.0, -744.0 / 625.0, 1008.0 / 625.0 },
42          {  -720.0 / 625.0, 1284.0 / 625.0, -288.0 / 625.0 },
43          {  -360.0 / 625.0,  192.0 / 625.0, 1756.0 / 625.0 },
44      };
45  
46      @Test
47      void testDimensions() {
48          checkdimensions(MatrixUtils.createRealMatrix(testSquare));
49          checkdimensions(MatrixUtils.createRealMatrix(testNonSquare));
50          checkdimensions(MatrixUtils.createRealMatrix(testNonSquare).transpose());
51      }
52  
53      private void checkdimensions(RealMatrix matrix) {
54          final int m = matrix.getRowDimension();
55          final int n = matrix.getColumnDimension();
56          BiDiagonalTransformer transformer = new BiDiagonalTransformer(matrix);
57          assertEquals(m, transformer.getU().getRowDimension());
58          assertEquals(m, transformer.getU().getColumnDimension());
59          assertEquals(m, transformer.getB().getRowDimension());
60          assertEquals(n, transformer.getB().getColumnDimension());
61          assertEquals(n, transformer.getV().getRowDimension());
62          assertEquals(n, transformer.getV().getColumnDimension());
63  
64      }
65  
66      @Test
67      void testAEqualUSVt() {
68          checkAEqualUSVt(MatrixUtils.createRealMatrix(testSquare));
69          checkAEqualUSVt(MatrixUtils.createRealMatrix(testNonSquare));
70          checkAEqualUSVt(MatrixUtils.createRealMatrix(testNonSquare).transpose());
71      }
72  
73      private void checkAEqualUSVt(RealMatrix matrix) {
74          BiDiagonalTransformer transformer = new BiDiagonalTransformer(matrix);
75          RealMatrix u = transformer.getU();
76          RealMatrix b = transformer.getB();
77          RealMatrix v = transformer.getV();
78          double norm = u.multiply(b).multiplyTransposed(v).subtract(matrix).getNorm1();
79          assertEquals(0, norm, 1.0e-14);
80      }
81  
82      @Test
83      void testUOrthogonal() {
84          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getU());
85          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getU());
86          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getU());
87      }
88  
89      @Test
90      void testVOrthogonal() {
91          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getV());
92          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getV());
93          checkOrthogonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getV());
94      }
95  
96      private void checkOrthogonal(RealMatrix m) {
97          RealMatrix mTm = m.transposeMultiply(m);
98          RealMatrix id  = MatrixUtils.createRealIdentityMatrix(mTm.getRowDimension());
99          assertEquals(0, mTm.subtract(id).getNorm1(), 1.0e-14);
100     }
101 
102     @Test
103     void testBBiDiagonal() {
104         checkBiDiagonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).getB());
105         checkBiDiagonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).getB());
106         checkBiDiagonal(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).getB());
107     }
108 
109     private void checkBiDiagonal(RealMatrix m) {
110         final int rows = m.getRowDimension();
111         final int cols = m.getColumnDimension();
112         for (int i = 0; i < rows; ++i) {
113             for (int j = 0; j < cols; ++j) {
114                 if (rows < cols) {
115                     if ((i < j) || (i > j + 1)) {
116                         assertEquals(0, m.getEntry(i, j), 1.0e-16);
117                     }
118                 } else {
119                     if ((i < j - 1) || (i > j)) {
120                         assertEquals(0, m.getEntry(i, j), 1.0e-16);
121                     }
122                 }
123             }
124         }
125     }
126 
127     @Test
128     void testSingularMatrix() {
129        BiDiagonalTransformer transformer =
130             new BiDiagonalTransformer(MatrixUtils.createRealMatrix(new double[][] {
131                 { 1.0, 2.0, 3.0 },
132                 { 2.0, 3.0, 4.0 },
133                 { 3.0, 5.0, 7.0 }
134             }));
135        final double s3  = FastMath.sqrt(3.0);
136        final double s14 = FastMath.sqrt(14.0);
137        final double s1553 = FastMath.sqrt(1553.0);
138        RealMatrix uRef = MatrixUtils.createRealMatrix(new double[][] {
139            {  -1.0 / s14,  5.0 / (s3 * s14),  1.0 / s3 },
140            {  -2.0 / s14, -4.0 / (s3 * s14),  1.0 / s3 },
141            {  -3.0 / s14,  1.0 / (s3 * s14), -1.0 / s3 }
142        });
143        RealMatrix bRef = MatrixUtils.createRealMatrix(new double[][] {
144            { -s14, s1553 / s14,   0.0 },
145            {  0.0, -87 * s3 / (s14 * s1553), -s3 * s14 / s1553 },
146            {  0.0, 0.0, 0.0 }
147        });
148        RealMatrix vRef = MatrixUtils.createRealMatrix(new double[][] {
149            { 1.0,   0.0,         0.0        },
150            { 0.0,  -23 / s1553,  32 / s1553 },
151            { 0.0,  -32 / s1553, -23 / s1553 }
152        });
153 
154        // check values against known references
155        RealMatrix u = transformer.getU();
156        assertEquals(0, u.subtract(uRef).getNorm1(), 1.0e-14);
157        RealMatrix b = transformer.getB();
158        assertEquals(0, b.subtract(bRef).getNorm1(), 1.0e-14);
159        RealMatrix v = transformer.getV();
160        assertEquals(0, v.subtract(vRef).getNorm1(), 1.0e-14);
161 
162        // check the same cached instance is returned the second time
163        assertTrue(u == transformer.getU());
164        assertTrue(b == transformer.getB());
165        assertTrue(v == transformer.getV());
166 
167     }
168 
169     @Test
170     void testMatricesValues() {
171        BiDiagonalTransformer transformer =
172             new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare));
173        final double s17 = FastMath.sqrt(17.0);
174         RealMatrix uRef = MatrixUtils.createRealMatrix(new double[][] {
175                 {  -8 / (5 * s17), 19 / (5 * s17) },
176                 { -19 / (5 * s17), -8 / (5 * s17) }
177         });
178         RealMatrix bRef = MatrixUtils.createRealMatrix(new double[][] {
179                 { -3 * s17 / 5, 32 * s17 / 85 },
180                 {      0.0,     -5 * s17 / 17 }
181         });
182         RealMatrix vRef = MatrixUtils.createRealMatrix(new double[][] {
183                 { 1.0,  0.0 },
184                 { 0.0, -1.0 }
185         });
186 
187         // check values against known references
188         RealMatrix u = transformer.getU();
189         assertEquals(0, u.subtract(uRef).getNorm1(), 1.0e-14);
190         RealMatrix b = transformer.getB();
191         assertEquals(0, b.subtract(bRef).getNorm1(), 1.0e-14);
192         RealMatrix v = transformer.getV();
193         assertEquals(0, v.subtract(vRef).getNorm1(), 1.0e-14);
194 
195         // check the same cached instance is returned the second time
196         assertTrue(u == transformer.getU());
197         assertTrue(b == transformer.getB());
198         assertTrue(v == transformer.getV());
199 
200     }
201 
202     @Test
203     void testUpperOrLower() {
204         assertTrue(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testSquare)).isUpperBiDiagonal());
205         assertTrue(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare)).isUpperBiDiagonal());
206         assertFalse(new BiDiagonalTransformer(MatrixUtils.createRealMatrix(testNonSquare).transpose()).isUpperBiDiagonal());
207     }
208 
209 }