1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.math4.legacy.field.linalg;
19
20 import org.junit.Test;
21 import org.junit.Assert;
22 import org.apache.commons.numbers.fraction.Fraction;
23 import org.apache.commons.numbers.field.FractionField;
24 import org.apache.commons.math4.legacy.linear.SingularMatrixException;
25 import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
26
27 public class FieldLUDecompositionTest {
28 private final int[][] testData = {
29 { 1, 2, 3 },
30 { 2, 5, 3 },
31 { 1, 0, 8 }
32 };
33 private final int[][] testDataMinus = {
34 { -1, -2, -3 },
35 { -2, -5, -3 },
36 { -1, 0, -8 }
37 };
38 private final int[][] luData = {
39 { 2, 3, 3 },
40 { 2, 3, 7 },
41 { 6, 6, 8 }
42 };
43 private final int[][] luData2 = {
44 { 2, 3, 3 },
45 { 0, 5, 7 },
46 { 6, 9, 8 }
47 };
48
49
50 private int[][] singular = {
51 { 2, 3 },
52 { 2, 3 }
53 };
54 private final int[][] bigSingular = {
55 { 1, 2, 3, 4 },
56 { 2, 5, 3, 4 },
57 { 7, 3, 256, 1930 },
58 { 3, 7, 6, 8 }
59 };
60
61 @Test
62 public void testDimensions() {
63 FieldDenseMatrix<Fraction> matrix = create(testData);
64 FieldLUDecomposition<Fraction> LU = FieldLUDecomposition.of(matrix);
65 Assert.assertEquals(testData.length, LU.getL().getRowDimension());
66 Assert.assertEquals(testData.length, LU.getU().getRowDimension());
67 Assert.assertEquals(testData.length, LU.getP().getRowDimension());
68 }
69
70 @Test
71 public void testPAEqualLU() {
72 FieldDenseMatrix<Fraction> matrix = create(testData);
73 FieldLUDecomposition<Fraction> lu = FieldLUDecomposition.of(matrix);
74 FieldDenseMatrix<Fraction> l = lu.getL();
75 FieldDenseMatrix<Fraction> u = lu.getU();
76 FieldDenseMatrix<Fraction> p = lu.getP();
77 Assert.assertEquals(p.multiply(matrix), l.multiply(u));
78
79 matrix = create(testDataMinus);
80 lu = FieldLUDecomposition.of(matrix);
81 l = lu.getL();
82 u = lu.getU();
83 p = lu.getP();
84 Assert.assertEquals(p.multiply(matrix), l.multiply(u));
85
86 matrix = FieldDenseMatrix.identity(FractionField.get(), 17);
87 lu = FieldLUDecomposition.of(matrix);
88 l = lu.getL();
89 u = lu.getU();
90 p = lu.getP();
91 Assert.assertEquals(p.multiply(matrix), l.multiply(u));
92 }
93
94
95 @Test
96 public void testLLowerTriangular() {
97 FieldDenseMatrix<Fraction> matrix = create(testData);
98 FieldDenseMatrix<Fraction> l = FieldLUDecomposition.of(matrix).getL();
99 for (int i = 0; i < l.getRowDimension(); i++) {
100 Assert.assertEquals(Fraction.ONE, l.get(i, i));
101 for (int j = i + 1; j < l.getColumnDimension(); j++) {
102 Assert.assertEquals(Fraction.ZERO, l.get(i, j));
103 }
104 }
105 }
106
107
108 @Test
109 public void testUUpperTriangular() {
110 FieldDenseMatrix<Fraction> matrix = create(testData);
111 FieldDenseMatrix<Fraction> u = FieldLUDecomposition.of(matrix).getU();
112 for (int i = 0; i < u.getRowDimension(); i++) {
113 for (int j = 0; j < i; j++) {
114 Assert.assertEquals(Fraction.ZERO, u.get(i, j));
115 }
116 }
117 }
118
119
120 @Test
121 public void testPPermutation() {
122 FieldDenseMatrix<Fraction> matrix = create(testData);
123 FieldDenseMatrix<Fraction> p = FieldLUDecomposition.of(matrix).getP();
124
125 FieldDenseMatrix<Fraction> ppT = p.multiply(p.transpose());
126 FieldDenseMatrix<Fraction> id = FieldDenseMatrix.identity(FractionField.get(),
127 p.getRowDimension());
128 Assert.assertEquals(id, ppT);
129
130 for (int i = 0; i < p.getRowDimension(); i++) {
131 int zeroCount = 0;
132 int oneCount = 0;
133 int otherCount = 0;
134 for (int j = 0; j < p.getColumnDimension(); j++) {
135 final Fraction e = p.get(i, j);
136 if (e.equals(Fraction.ZERO)) {
137 ++zeroCount;
138 } else if (e.equals(Fraction.ONE)) {
139 ++oneCount;
140 } else {
141 ++otherCount;
142 }
143 }
144 Assert.assertEquals(p.getRowDimension() - 1, zeroCount);
145 Assert.assertEquals(1, oneCount);
146 Assert.assertEquals(0, otherCount);
147 }
148
149 for (int j = 0; j < p.getRowDimension(); j++) {
150 int zeroCount = 0;
151 int oneCount = 0;
152 int otherCount = 0;
153 for (int i = 0; i < p.getColumnDimension(); i++) {
154 final Fraction e = p.get(i, j);
155 if (e.equals(Fraction.ZERO)) {
156 ++zeroCount;
157 } else if (e.equals(Fraction.ONE)) {
158 ++oneCount;
159 } else {
160 ++otherCount;
161 }
162 }
163 Assert.assertEquals(p.getRowDimension() - 1, zeroCount);
164 Assert.assertEquals(1, oneCount);
165 Assert.assertEquals(0, otherCount);
166 }
167 }
168
169 @Test
170 public void testIsSingular1() {
171 FieldLUDecomposition<Fraction> lu = FieldLUDecomposition.of(create(testData));
172 Assert.assertFalse(lu.isSingular());
173 lu.getSolver();
174 }
175 @Test(expected=SingularMatrixException.class)
176 public void testIsSingular2() {
177 FieldLUDecomposition<Fraction> lu = FieldLUDecomposition.of(create(singular));
178 Assert.assertTrue(lu.isSingular());
179 lu.getSolver();
180 }
181 @Test(expected=SingularMatrixException.class)
182 public void testIsSingular3() {
183 FieldLUDecomposition<Fraction> lu = FieldLUDecomposition.of(create(bigSingular));
184 Assert.assertTrue(lu.isSingular());
185 lu.getSolver();
186 }
187
188 @Test
189 public void testMatricesValues1() {
190 FieldLUDecomposition<Fraction> lu = FieldLUDecomposition.of(create(testData));
191 FieldDenseMatrix<Fraction> lRef = create(new int[][] {
192 { 1, 0, 0 },
193 { 2, 1, 0 },
194 { 1, -2, 1 }
195 });
196 FieldDenseMatrix<Fraction> uRef = create(new int[][] {
197 { 1, 2, 3 },
198 { 0, 1, -3 },
199 { 0, 0, -1 }
200 });
201 FieldDenseMatrix<Fraction> pRef = create(new int[][] {
202 { 1, 0, 0 },
203 { 0, 1, 0 },
204 { 0, 0, 1 }
205 });
206 int[] pivotRef = { 0, 1, 2 };
207
208
209 FieldDenseMatrix<Fraction> l = lu.getL();
210 Assert.assertEquals(lRef, l);
211 FieldDenseMatrix<Fraction> u = lu.getU();
212 Assert.assertEquals(uRef, u);
213 FieldDenseMatrix<Fraction> p = lu.getP();
214 Assert.assertEquals(pRef, p);
215 int[] pivot = lu.getPivot();
216 for (int i = 0; i < pivotRef.length; ++i) {
217 Assert.assertEquals(pivotRef[i], pivot[i]);
218 }
219 }
220
221 @Test
222 public void testMatricesValues2() {
223 final FieldLUDecomposition<Fraction> lu = FieldLUDecomposition.of(create(luData));
224 final FieldDenseMatrix<Fraction> lRef = create(new int[][] {
225 { 1, 0, 0 },
226 { 3, 1, 0 },
227 { 1, 0, 1 }
228 });
229 final FieldDenseMatrix<Fraction> uRef = create(new int[][] {
230 { 2, 3, 3 },
231 { 0, -3, -1 },
232 { 0, 0, 4 }
233 });
234 final FieldDenseMatrix<Fraction> pRef = create(new int[][] {
235 { 1, 0, 0 },
236 { 0, 0, 1 },
237 { 0, 1, 0 }
238 });
239 int[] pivotRef = { 0, 2, 1 };
240
241
242 final FieldDenseMatrix<Fraction> l = lu.getL();
243 Assert.assertEquals(lRef, l);
244 final FieldDenseMatrix<Fraction> u = lu.getU();
245 Assert.assertEquals(uRef, u);
246 final FieldDenseMatrix<Fraction> p = lu.getP();
247 Assert.assertEquals(pRef, p);
248 int[] pivot = lu.getPivot();
249 for (int i = 0; i < pivotRef.length; i++) {
250 Assert.assertEquals(pivotRef[i], pivot[i]);
251 }
252 }
253
254 @Test(expected=DimensionMismatchException.class)
255 public void testSolveDimensionErrors() {
256 FieldLUDecomposition
257 .of(create(testData))
258 .getSolver()
259 .solve(create(new int[2][2]));
260 }
261
262 @Test
263 public void testSolve() {
264 final FieldDecompositionSolver<Fraction> solver = FieldLUDecomposition
265 .of(create(testData))
266 .getSolver();
267 final FieldDenseMatrix<Fraction> b = create(new int[][] {
268 { 1, 0 },
269 { 2, -5 },
270 { 3, 1 }
271 });
272 final FieldDenseMatrix<Fraction> xRef = create(new int[][] {
273 { 19, -71 },
274 { -6, 22 },
275 { -2, 9 }
276 });
277
278 final FieldDenseMatrix<Fraction> x = solver.solve(b);
279 for (int i = 0; i < x.getRowDimension(); i++){
280 for (int j = 0; j < x.getColumnDimension(); j++){
281 Assert.assertEquals("(" + i + ", " + j + ")",
282 xRef.get(i, j), x.get(i, j));
283 }
284 }
285 }
286
287 @Test
288 public void testDeterminant() {
289 Assert.assertEquals(-1, determinant(testData), 1e-15);
290 Assert.assertEquals(24, determinant(luData), 1e-14);
291 Assert.assertEquals(-10, determinant(luData2), 1e-14);
292 Assert.assertEquals(0, determinant(singular), 1e-15);
293 Assert.assertEquals(0, determinant(bigSingular), 1e-15);
294 }
295
296 private static double determinant(int[][] data) {
297 return FieldLUDecomposition.of(create(data)).getDeterminant().doubleValue();
298 }
299
300 private static FieldDenseMatrix<Fraction> create(final int[][] data) {
301 final int numRows = data.length;
302 final int numCols = data[0].length;
303 final FieldDenseMatrix<Fraction> m = FieldDenseMatrix
304 .create(FractionField.get(), numRows, numCols);
305
306 for (int i = 0; i < numRows; i++) {
307 for (int j = 0; j < numCols; j++) {
308 m.set(i, j, Fraction.of(data[i][j], 1));
309 }
310 }
311
312 return m;
313 }
314 }