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 java.util.Random; 021 022 import junit.framework.Test; 023 import junit.framework.TestCase; 024 import junit.framework.TestSuite; 025 026 import org.apache.commons.math.linear.DecompositionSolver; 027 import org.apache.commons.math.linear.EigenDecompositionImpl; 028 import org.apache.commons.math.linear.InvalidMatrixException; 029 import org.apache.commons.math.linear.MatrixUtils; 030 import org.apache.commons.math.linear.RealMatrix; 031 import org.apache.commons.math.linear.ArrayRealVector; 032 import org.apache.commons.math.util.MathUtils; 033 034 public class EigenSolverTest extends TestCase { 035 036 private double[] refValues; 037 private RealMatrix matrix; 038 039 public EigenSolverTest(String name) { 040 super(name); 041 } 042 043 public static Test suite() { 044 TestSuite suite = new TestSuite(EigenSolverTest.class); 045 suite.setName("EigenSolver Tests"); 046 return suite; 047 } 048 049 /** test non invertible matrix */ 050 public void testNonInvertible() { 051 Random r = new Random(9994100315209l); 052 RealMatrix m = 053 EigenDecompositionImplTest.createTestMatrix(r, new double[] { 1.0, 0.0, -1.0, -2.0, -3.0 }); 054 DecompositionSolver es = new EigenDecompositionImpl(m, MathUtils.SAFE_MIN).getSolver(); 055 assertFalse(es.isNonSingular()); 056 try { 057 es.getInverse(); 058 fail("an exception should have been thrown"); 059 } catch (InvalidMatrixException ime) { 060 // expected behavior 061 } catch (Exception e) { 062 fail("wrong exception caught"); 063 } 064 } 065 066 /** test invertible matrix */ 067 public void testInvertible() { 068 Random r = new Random(9994100315209l); 069 RealMatrix m = 070 EigenDecompositionImplTest.createTestMatrix(r, new double[] { 1.0, 0.5, -1.0, -2.0, -3.0 }); 071 DecompositionSolver es = new EigenDecompositionImpl(m, MathUtils.SAFE_MIN).getSolver(); 072 assertTrue(es.isNonSingular()); 073 RealMatrix inverse = es.getInverse(); 074 RealMatrix error = 075 m.multiply(inverse).subtract(MatrixUtils.createRealIdentityMatrix(m.getRowDimension())); 076 assertEquals(0, error.getNorm(), 4.0e-15); 077 } 078 079 /** test solve dimension errors */ 080 public void testSolveDimensionErrors() { 081 DecompositionSolver es = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN).getSolver(); 082 RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]); 083 try { 084 es.solve(b); 085 fail("an exception should have been thrown"); 086 } catch (IllegalArgumentException iae) { 087 // expected behavior 088 } catch (Exception e) { 089 fail("wrong exception caught"); 090 } 091 try { 092 es.solve(b.getColumn(0)); 093 fail("an exception should have been thrown"); 094 } catch (IllegalArgumentException iae) { 095 // expected behavior 096 } catch (Exception e) { 097 fail("wrong exception caught"); 098 } 099 try { 100 es.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0))); 101 fail("an exception should have been thrown"); 102 } catch (IllegalArgumentException iae) { 103 // expected behavior 104 } catch (Exception e) { 105 fail("wrong exception caught"); 106 } 107 } 108 109 /** test solve */ 110 public void testSolve() { 111 RealMatrix m = MatrixUtils.createRealMatrix(new double[][] { 112 { 91, 5, 29, 32, 40, 14 }, 113 { 5, 34, -1, 0, 2, -1 }, 114 { 29, -1, 12, 9, 21, 8 }, 115 { 32, 0, 9, 14, 9, 0 }, 116 { 40, 2, 21, 9, 51, 19 }, 117 { 14, -1, 8, 0, 19, 14 } 118 }); 119 DecompositionSolver es = new EigenDecompositionImpl(m, MathUtils.SAFE_MIN).getSolver(); 120 RealMatrix b = MatrixUtils.createRealMatrix(new double[][] { 121 { 1561, 269, 188 }, 122 { 69, -21, 70 }, 123 { 739, 108, 63 }, 124 { 324, 86, 59 }, 125 { 1624, 194, 107 }, 126 { 796, 69, 36 } 127 }); 128 RealMatrix xRef = MatrixUtils.createRealMatrix(new double[][] { 129 { 1, 2, 1 }, 130 { 2, -1, 2 }, 131 { 4, 2, 3 }, 132 { 8, -1, 0 }, 133 { 16, 2, 0 }, 134 { 32, -1, 0 } 135 }); 136 137 // using RealMatrix 138 assertEquals(0, es.solve(b).subtract(xRef).getNorm(), 2.0e-12); 139 140 // using double[] 141 for (int i = 0; i < b.getColumnDimension(); ++i) { 142 assertEquals(0, 143 new ArrayRealVector(es.solve(b.getColumn(i))).subtract(xRef.getColumnVector(i)).getNorm(), 144 2.0e-11); 145 } 146 147 // using Array2DRowRealMatrix 148 for (int i = 0; i < b.getColumnDimension(); ++i) { 149 assertEquals(0, 150 es.solve(b.getColumnVector(i)).subtract(xRef.getColumnVector(i)).getNorm(), 151 2.0e-11); 152 } 153 154 // using RealMatrix with an alternate implementation 155 for (int i = 0; i < b.getColumnDimension(); ++i) { 156 ArrayRealVectorTest.RealVectorTestImpl v = 157 new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(i)); 158 assertEquals(0, 159 es.solve(v).subtract(xRef.getColumnVector(i)).getNorm(), 160 2.0e-11); 161 } 162 163 } 164 165 @Override 166 public void setUp() { 167 refValues = new double[] { 168 2.003, 2.002, 2.001, 1.001, 1.000, 0.001 169 }; 170 matrix = EigenDecompositionImplTest.createTestMatrix(new Random(35992629946426l), refValues); 171 } 172 173 @Override 174 public void tearDown() { 175 refValues = null; 176 matrix = null; 177 } 178 179 }