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