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.math.linear;
19  
20  import java.util.Random;
21  
22  import junit.framework.Test;
23  import junit.framework.TestCase;
24  import junit.framework.TestSuite;
25  
26  import org.apache.commons.math.linear.DecompositionSolver;
27  import org.apache.commons.math.linear.EigenDecompositionImpl;
28  import org.apache.commons.math.linear.InvalidMatrixException;
29  import org.apache.commons.math.linear.MatrixUtils;
30  import org.apache.commons.math.linear.RealMatrix;
31  import org.apache.commons.math.linear.ArrayRealVector;
32  import org.apache.commons.math.util.MathUtils;
33  
34  public class EigenSolverTest extends TestCase {
35  
36      private double[] refValues;
37      private RealMatrix matrix;
38  
39      public EigenSolverTest(String name) {
40          super(name);
41      }
42  
43      public static Test suite() {
44          TestSuite suite = new TestSuite(EigenSolverTest.class);
45          suite.setName("EigenSolver Tests");
46          return suite;
47      }
48  
49      /** test non invertible matrix */
50      public void testNonInvertible() {
51          Random r = new Random(9994100315209l);
52          RealMatrix m =
53              EigenDecompositionImplTest.createTestMatrix(r, new double[] { 1.0, 0.0, -1.0, -2.0, -3.0 });
54          DecompositionSolver es = new EigenDecompositionImpl(m, MathUtils.SAFE_MIN).getSolver();
55          assertFalse(es.isNonSingular());
56          try {
57              es.getInverse();
58              fail("an exception should have been thrown");
59          } catch (InvalidMatrixException ime) {
60              // expected behavior
61          } catch (Exception e) {
62              fail("wrong exception caught");
63          }
64      }
65  
66      /** test invertible matrix */
67      public void testInvertible() {
68          Random r = new Random(9994100315209l);
69          RealMatrix m =
70              EigenDecompositionImplTest.createTestMatrix(r, new double[] { 1.0, 0.5, -1.0, -2.0, -3.0 });
71          DecompositionSolver es = new EigenDecompositionImpl(m, MathUtils.SAFE_MIN).getSolver();
72          assertTrue(es.isNonSingular());
73          RealMatrix inverse = es.getInverse();
74          RealMatrix error =
75              m.multiply(inverse).subtract(MatrixUtils.createRealIdentityMatrix(m.getRowDimension()));
76          assertEquals(0, error.getNorm(), 4.0e-15);
77      }
78  
79      /** test solve dimension errors */
80      public void testSolveDimensionErrors() {
81          DecompositionSolver es = new EigenDecompositionImpl(matrix, MathUtils.SAFE_MIN).getSolver();
82          RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
83          try {
84              es.solve(b);
85              fail("an exception should have been thrown");
86          } catch (IllegalArgumentException iae) {
87              // expected behavior
88          } catch (Exception e) {
89              fail("wrong exception caught");
90          }
91          try {
92              es.solve(b.getColumn(0));
93              fail("an exception should have been thrown");
94          } catch (IllegalArgumentException iae) {
95              // expected behavior
96          } catch (Exception e) {
97              fail("wrong exception caught");
98          }
99          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 }