1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.linear;
19
20 import java.util.Random;
21
22 import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
23 import org.junit.Test;
24 import org.junit.Assert;
25
26 public class RRQRSolverTest {
27 private double[][] testData3x3NonSingular = {
28 { 12, -51, 4 },
29 { 6, 167, -68 },
30 { -4, 24, -41 }
31 };
32
33 private double[][] testData3x3Singular = {
34 { 1, 2, 2 },
35 { 2, 4, 6 },
36 { 4, 8, 12 }
37 };
38
39 private double[][] testData3x4 = {
40 { 12, -51, 4, 1 },
41 { 6, 167, -68, 2 },
42 { -4, 24, -41, 3 }
43 };
44
45 private double[][] testData4x3 = {
46 { 12, -51, 4 },
47 { 6, 167, -68 },
48 { -4, 24, -41 },
49 { -5, 34, 7 }
50 };
51
52
53 @Test
54 public void testRank() {
55 DecompositionSolver solver =
56 new RRQRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular), 1.0e-16).getSolver();
57 Assert.assertTrue(solver.isNonSingular());
58
59 solver = new RRQRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular), 1.0e-16).getSolver();
60 Assert.assertFalse(solver.isNonSingular());
61
62 solver = new RRQRDecomposition(MatrixUtils.createRealMatrix(testData3x4), 1.0e-16).getSolver();
63 Assert.assertTrue(solver.isNonSingular());
64
65 solver = new RRQRDecomposition(MatrixUtils.createRealMatrix(testData4x3), 1.0e-16).getSolver();
66 Assert.assertTrue(solver.isNonSingular());
67 }
68
69
70 @Test
71 public void testSolveDimensionErrors() {
72 DecompositionSolver solver =
73 new RRQRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular)).getSolver();
74 RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
75 try {
76 solver.solve(b);
77 Assert.fail("an exception should have been thrown");
78 } catch (MathIllegalArgumentException iae) {
79
80 }
81 try {
82 solver.solve(b.getColumnVector(0));
83 Assert.fail("an exception should have been thrown");
84 } catch (MathIllegalArgumentException iae) {
85
86 }
87 }
88
89
90 @Test
91 public void testSolveRankErrors() {
92 DecompositionSolver solver =
93 new RRQRDecomposition(MatrixUtils.createRealMatrix(testData3x3Singular), 1.0e-16).getSolver();
94 RealMatrix b = MatrixUtils.createRealMatrix(new double[3][2]);
95 try {
96 solver.solve(b);
97 Assert.fail("an exception should have been thrown");
98 } catch (SingularMatrixException iae) {
99
100 }
101 try {
102 solver.solve(b.getColumnVector(0));
103 Assert.fail("an exception should have been thrown");
104 } catch (SingularMatrixException iae) {
105
106 }
107 }
108
109
110 @Test
111 public void testSolve() {
112 RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
113 { -102, 12250 }, { 544, 24500 }, { 167, -36750 }
114 });
115 RealMatrix xRef = MatrixUtils.createRealMatrix(new double[][] {
116 { 1, 2515 }, { 2, 422 }, { -3, 898 }
117 });
118
119
120 RRQRDecomposition decomposition = new RRQRDecomposition(MatrixUtils.createRealMatrix(testData3x3NonSingular));
121 DecompositionSolver solver = decomposition.getSolver();
122
123
124 Assert.assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), 3.0e-16 * xRef.getNorm());
125
126
127 for (int i = 0; i < b.getColumnDimension(); ++i) {
128 final RealVector x = solver.solve(b.getColumnVector(i));
129 final double error = x.subtract(xRef.getColumnVector(i)).getNorm();
130 Assert.assertEquals(0, error, 3.0e-16 * xRef.getColumnVector(i).getNorm());
131 }
132
133
134 for (int i = 0; i < b.getColumnDimension(); ++i) {
135 ArrayRealVectorTest.RealVectorTestImpl v =
136 new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(i));
137 final RealVector x = solver.solve(v);
138 final double error = x.subtract(xRef.getColumnVector(i)).getNorm();
139 Assert.assertEquals(0, error, 3.0e-16 * xRef.getColumnVector(i).getNorm());
140 }
141 }
142
143 @Test
144 public void testOverdetermined() {
145 final Random r = new Random(5559252868205245L);
146 int p = (7 * BlockRealMatrix.BLOCK_SIZE) / 4;
147 int q = (5 * BlockRealMatrix.BLOCK_SIZE) / 4;
148 RealMatrix a = createTestMatrix(r, p, q);
149 RealMatrix xRef = createTestMatrix(r, q, BlockRealMatrix.BLOCK_SIZE + 3);
150
151
152 RealMatrix b = a.multiply(xRef);
153 final double noise = 0.001;
154 b.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() {
155 @Override
156 public double visit(int row, int column, double value) {
157 return value * (1.0 + noise * (2 * r.nextDouble() - 1));
158 }
159 });
160
161
162 RealMatrix x = new RRQRDecomposition(a).getSolver().solve(b);
163 Assert.assertEquals(0, x.subtract(xRef).getNorm(), 0.01 * noise * p * q);
164 }
165
166 @Test
167 public void testUnderdetermined() {
168 final Random r = new Random(42185006424567123L);
169 int p = (5 * BlockRealMatrix.BLOCK_SIZE) / 4;
170 int q = (7 * BlockRealMatrix.BLOCK_SIZE) / 4;
171 RealMatrix a = createTestMatrix(r, p, q);
172 RealMatrix xRef = createTestMatrix(r, q, BlockRealMatrix.BLOCK_SIZE + 3);
173 RealMatrix b = a.multiply(xRef);
174 RRQRDecomposition rrqrd = new RRQRDecomposition(a);
175 RealMatrix x = rrqrd.getSolver().solve(b);
176
177
178 Assert.assertTrue(x.subtract(xRef).getNorm() / (p * q) > 0.01);
179
180
181 RealMatrix permuted = rrqrd.getP().transpose().multiply(x);
182 Assert.assertEquals(0.0, permuted.getSubMatrix(p, q - 1, 0, permuted.getColumnDimension() - 1).getNorm(), 0);
183 }
184
185 private RealMatrix createTestMatrix(final Random r, final int rows, final int columns) {
186 RealMatrix m = MatrixUtils.createRealMatrix(rows, columns);
187 m.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() {
188 @Override
189 public double visit(int row, int column, double value) {
190 return 2.0 * r.nextDouble() - 1.0;
191 }
192 });
193 return m;
194 }
195 }