001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.math.linear; 019 020 import junit.framework.Test; 021 import junit.framework.TestCase; 022 import junit.framework.TestSuite; 023 024 import org.apache.commons.math.linear.DecompositionSolver; 025 import org.apache.commons.math.linear.InvalidMatrixException; 026 import org.apache.commons.math.linear.LUDecompositionImpl; 027 import org.apache.commons.math.linear.MatrixUtils; 028 import org.apache.commons.math.linear.RealMatrix; 029 import org.apache.commons.math.linear.ArrayRealVector; 030 031 public class LUSolverTest extends TestCase { 032 private double[][] testData = { 033 { 1.0, 2.0, 3.0}, 034 { 2.0, 5.0, 3.0}, 035 { 1.0, 0.0, 8.0} 036 }; 037 private double[][] luData = { 038 { 2.0, 3.0, 3.0 }, 039 { 0.0, 5.0, 7.0 }, 040 { 6.0, 9.0, 8.0 } 041 }; 042 043 // singular matrices 044 private double[][] singular = { 045 { 2.0, 3.0 }, 046 { 2.0, 3.0 } 047 }; 048 private double[][] bigSingular = { 049 { 1.0, 2.0, 3.0, 4.0 }, 050 { 2.0, 5.0, 3.0, 4.0 }, 051 { 7.0, 3.0, 256.0, 1930.0 }, 052 { 3.0, 7.0, 6.0, 8.0 } 053 }; // 4th row = 1st + 2nd 054 055 public LUSolverTest(String name) { 056 super(name); 057 } 058 059 public static Test suite() { 060 TestSuite suite = new TestSuite(LUSolverTest.class); 061 suite.setName("LUSolver Tests"); 062 return suite; 063 } 064 065 /** test threshold impact */ 066 public void testThreshold() { 067 final RealMatrix matrix = MatrixUtils.createRealMatrix(new double[][] { 068 { 1.0, 2.0, 3.0}, 069 { 2.0, 5.0, 3.0}, 070 { 4.000001, 9.0, 9.0} 071 }); 072 assertFalse(new LUDecompositionImpl(matrix, 1.0e-5).getSolver().isNonSingular()); 073 assertTrue(new LUDecompositionImpl(matrix, 1.0e-10).getSolver().isNonSingular()); 074 } 075 076 /** test singular */ 077 public void testSingular() { 078 DecompositionSolver solver = 079 new LUDecompositionImpl(MatrixUtils.createRealMatrix(testData)).getSolver(); 080 assertTrue(solver.isNonSingular()); 081 solver = new LUDecompositionImpl(MatrixUtils.createRealMatrix(singular)).getSolver(); 082 assertFalse(solver.isNonSingular()); 083 solver = new LUDecompositionImpl(MatrixUtils.createRealMatrix(bigSingular)).getSolver(); 084 assertFalse(solver.isNonSingular()); 085 } 086 087 /** test solve dimension errors */ 088 public void testSolveDimensionErrors() { 089 DecompositionSolver solver = 090 new LUDecompositionImpl(MatrixUtils.createRealMatrix(testData)).getSolver(); 091 RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]); 092 try { 093 solver.solve(b); 094 fail("an exception should have been thrown"); 095 } catch (IllegalArgumentException iae) { 096 // expected behavior 097 } catch (Exception e) { 098 fail("wrong exception caught"); 099 } 100 try { 101 solver.solve(b.getColumn(0)); 102 fail("an exception should have been thrown"); 103 } catch (IllegalArgumentException iae) { 104 // expected behavior 105 } catch (Exception e) { 106 fail("wrong exception caught"); 107 } 108 try { 109 solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0))); 110 fail("an exception should have been thrown"); 111 } catch (IllegalArgumentException iae) { 112 // expected behavior 113 } catch (Exception e) { 114 fail("wrong exception caught"); 115 } 116 } 117 118 /** test solve singularity errors */ 119 public void testSolveSingularityErrors() { 120 DecompositionSolver solver = 121 new LUDecompositionImpl(MatrixUtils.createRealMatrix(singular)).getSolver(); 122 RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]); 123 try { 124 solver.solve(b); 125 fail("an exception should have been thrown"); 126 } catch (InvalidMatrixException ime) { 127 // expected behavior 128 } catch (Exception e) { 129 fail("wrong exception caught"); 130 } 131 try { 132 solver.solve(b.getColumn(0)); 133 fail("an exception should have been thrown"); 134 } catch (InvalidMatrixException ime) { 135 // expected behavior 136 } catch (Exception e) { 137 fail("wrong exception caught"); 138 } 139 try { 140 solver.solve(b.getColumnVector(0)); 141 fail("an exception should have been thrown"); 142 } catch (InvalidMatrixException ime) { 143 // expected behavior 144 } catch (Exception e) { 145 fail("wrong exception caught"); 146 } 147 try { 148 solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0))); 149 fail("an exception should have been thrown"); 150 } catch (InvalidMatrixException ime) { 151 // expected behavior 152 } catch (Exception e) { 153 fail("wrong exception caught"); 154 } 155 } 156 157 /** test solve */ 158 public void testSolve() { 159 DecompositionSolver solver = 160 new LUDecompositionImpl(MatrixUtils.createRealMatrix(testData)).getSolver(); 161 RealMatrix b = MatrixUtils.createRealMatrix(new double[][] { 162 { 1, 0 }, { 2, -5 }, { 3, 1 } 163 }); 164 RealMatrix xRef = MatrixUtils.createRealMatrix(new double[][] { 165 { 19, -71 }, { -6, 22 }, { -2, 9 } 166 }); 167 168 // using RealMatrix 169 assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), 1.0e-13); 170 171 // using double[] 172 for (int i = 0; i < b.getColumnDimension(); ++i) { 173 assertEquals(0, 174 new ArrayRealVector(solver.solve(b.getColumn(i))).subtract(xRef.getColumnVector(i)).getNorm(), 175 1.0e-13); 176 } 177 178 // using ArrayRealVector 179 for (int i = 0; i < b.getColumnDimension(); ++i) { 180 assertEquals(0, 181 solver.solve(b.getColumnVector(i)).subtract(xRef.getColumnVector(i)).getNorm(), 182 1.0e-13); 183 } 184 185 // using RealVector with an alternate implementation 186 for (int i = 0; i < b.getColumnDimension(); ++i) { 187 ArrayRealVectorTest.RealVectorTestImpl v = 188 new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(i)); 189 assertEquals(0, 190 solver.solve(v).subtract(xRef.getColumnVector(i)).getNorm(), 191 1.0e-13); 192 } 193 194 } 195 196 /** test determinant */ 197 public void testDeterminant() { 198 assertEquals( -1, getDeterminant(MatrixUtils.createRealMatrix(testData)), 1.0e-15); 199 assertEquals(-10, getDeterminant(MatrixUtils.createRealMatrix(luData)), 1.0e-14); 200 assertEquals( 0, getDeterminant(MatrixUtils.createRealMatrix(singular)), 1.0e-17); 201 assertEquals( 0, getDeterminant(MatrixUtils.createRealMatrix(bigSingular)), 1.0e-10); 202 } 203 204 private double getDeterminant(RealMatrix m) { 205 return new LUDecompositionImpl(m).getDeterminant(); 206 } 207 208 }