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.legacy.exception.MathIllegalArgumentException;
21  import org.junit.Test;
22  import org.junit.Assert;
23  
24  public class LUSolverTest {
25      private double[][] testData = {
26              { 1.0, 2.0, 3.0},
27              { 2.0, 5.0, 3.0},
28              { 1.0, 0.0, 8.0}
29      };
30      private double[][] luData = {
31              { 2.0, 3.0, 3.0 },
32              { 0.0, 5.0, 7.0 },
33              { 6.0, 9.0, 8.0 }
34      };
35  
36      // singular matrices
37      private double[][] singular = {
38              { 2.0, 3.0 },
39              { 2.0, 3.0 }
40      };
41      private double[][] bigSingular = {
42              { 1.0, 2.0,   3.0,    4.0 },
43              { 2.0, 5.0,   3.0,    4.0 },
44              { 7.0, 3.0, 256.0, 1930.0 },
45              { 3.0, 7.0,   6.0,    8.0 }
46      }; // 4th row = 1st + 2nd
47  
48      /** test threshold impact */
49      @Test
50      public void testThreshold() {
51          final RealMatrix matrix = MatrixUtils.createRealMatrix(new double[][] {
52                                                         { 1.0, 2.0, 3.0},
53                                                         { 2.0, 5.0, 3.0},
54                                                         { 4.000001, 9.0, 9.0}
55                                                       });
56          Assert.assertFalse(new LUDecomposition(matrix, 1.0e-5).getSolver().isNonSingular());
57          Assert.assertTrue(new LUDecomposition(matrix, 1.0e-10).getSolver().isNonSingular());
58      }
59  
60      /** test singular */
61      @Test
62      public void testSingular() {
63          DecompositionSolver solver =
64              new LUDecomposition(MatrixUtils.createRealMatrix(testData)).getSolver();
65          Assert.assertTrue(solver.isNonSingular());
66          solver = new LUDecomposition(MatrixUtils.createRealMatrix(singular)).getSolver();
67          Assert.assertFalse(solver.isNonSingular());
68          solver = new LUDecomposition(MatrixUtils.createRealMatrix(bigSingular)).getSolver();
69          Assert.assertFalse(solver.isNonSingular());
70      }
71  
72      /** test solve dimension errors */
73      @Test
74      public void testSolveDimensionErrors() {
75          DecompositionSolver solver =
76              new LUDecomposition(MatrixUtils.createRealMatrix(testData)).getSolver();
77          RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
78          try {
79              solver.solve(b);
80              Assert.fail("an exception should have been thrown");
81          } catch (MathIllegalArgumentException iae) {
82              // expected behavior
83          }
84          try {
85              solver.solve(b.getColumnVector(0));
86              Assert.fail("an exception should have been thrown");
87          } catch (MathIllegalArgumentException iae) {
88              // expected behavior
89          }
90          try {
91              solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0)));
92              Assert.fail("an exception should have been thrown");
93          } catch (MathIllegalArgumentException iae) {
94              // expected behavior
95          }
96      }
97  
98      /** test solve singularity errors */
99      @Test
100     public void testSolveSingularityErrors() {
101         DecompositionSolver solver =
102             new LUDecomposition(MatrixUtils.createRealMatrix(singular)).getSolver();
103         RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
104         try {
105             solver.solve(b);
106             Assert.fail("an exception should have been thrown");
107         } catch (SingularMatrixException ime) {
108             // expected behavior
109         }
110         try {
111             solver.solve(b.getColumnVector(0));
112             Assert.fail("an exception should have been thrown");
113         } catch (SingularMatrixException ime) {
114             // expected behavior
115         }
116         try {
117             solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0)));
118             Assert.fail("an exception should have been thrown");
119         } catch (SingularMatrixException ime) {
120             // expected behavior
121         }
122     }
123 
124     /** test solve */
125     @Test
126     public void testSolve() {
127         DecompositionSolver solver =
128             new LUDecomposition(MatrixUtils.createRealMatrix(testData)).getSolver();
129         RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
130                 { 1, 0 }, { 2, -5 }, { 3, 1 }
131         });
132         RealMatrix xRef = MatrixUtils.createRealMatrix(new double[][] {
133                 { 19, -71 }, { -6, 22 }, { -2, 9 }
134         });
135 
136         // using RealMatrix
137         Assert.assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), 1.0e-13);
138 
139         // using ArrayRealVector
140         for (int i = 0; i < b.getColumnDimension(); ++i) {
141             Assert.assertEquals(0,
142                          solver.solve(b.getColumnVector(i)).subtract(xRef.getColumnVector(i)).getNorm(),
143                          1.0e-13);
144         }
145 
146         // using RealVector with an alternate implementation
147         for (int i = 0; i < b.getColumnDimension(); ++i) {
148             ArrayRealVectorTest.RealVectorTestImpl v =
149                 new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(i));
150             Assert.assertEquals(0,
151                          solver.solve(v).subtract(xRef.getColumnVector(i)).getNorm(),
152                          1.0e-13);
153         }
154     }
155 
156     /** test determinant */
157     @Test
158     public void testDeterminant() {
159         Assert.assertEquals( -1, getDeterminant(MatrixUtils.createRealMatrix(testData)), 1.0e-15);
160         Assert.assertEquals(-10, getDeterminant(MatrixUtils.createRealMatrix(luData)), 1.0e-14);
161         Assert.assertEquals(  0, getDeterminant(MatrixUtils.createRealMatrix(singular)), 1.0e-17);
162         Assert.assertEquals(  0, getDeterminant(MatrixUtils.createRealMatrix(bigSingular)), 1.0e-10);
163     }
164 
165     private double getDeterminant(RealMatrix m) {
166         return new LUDecomposition(m).getDeterminant();
167     }
168 }