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