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 }