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.MatrixUtils;
027 import org.apache.commons.math.linear.RealMatrix;
028 import org.apache.commons.math.linear.ArrayRealVector;
029 import org.apache.commons.math.linear.SingularValueDecompositionImpl;
030
031 public class SingularValueSolverTest extends TestCase {
032
033 private double[][] testSquare = {
034 { 24.0 / 25.0, 43.0 / 25.0 },
035 { 57.0 / 25.0, 24.0 / 25.0 }
036 };
037
038 private static final double normTolerance = 10e-14;
039
040 public SingularValueSolverTest(String name) {
041 super(name);
042 }
043
044 public static Test suite() {
045 TestSuite suite = new TestSuite(SingularValueSolverTest.class);
046 suite.setName("SingularValueSolver Tests");
047 return suite;
048 }
049
050 /** test solve dimension errors */
051 public void testSolveDimensionErrors() {
052 DecompositionSolver solver =
053 new SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare)).getSolver();
054 RealMatrix b = MatrixUtils.createRealMatrix(new double[3][2]);
055 try {
056 solver.solve(b);
057 fail("an exception should have been thrown");
058 } catch (IllegalArgumentException iae) {
059 // expected behavior
060 } catch (Exception e) {
061 fail("wrong exception caught");
062 }
063 try {
064 solver.solve(b.getColumn(0));
065 fail("an exception should have been thrown");
066 } catch (IllegalArgumentException iae) {
067 // expected behavior
068 } catch (Exception e) {
069 fail("wrong exception caught");
070 }
071 try {
072 solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0)));
073 fail("an exception should have been thrown");
074 } catch (IllegalArgumentException iae) {
075 // expected behavior
076 } catch (Exception e) {
077 fail("wrong exception caught");
078 }
079 }
080
081 /** test solve singularity errors */
082 public void testSolveSingularityErrors() {
083 RealMatrix m =
084 MatrixUtils.createRealMatrix(new double[][] {
085 { 1.0, 0.0 },
086 { 0.0, 0.0 }
087 });
088 DecompositionSolver solver = new SingularValueDecompositionImpl(m).getSolver();
089 RealMatrix b = MatrixUtils.createRealMatrix(new double[2][2]);
090 try {
091 solver.solve(b);
092 fail("an exception should have been thrown");
093 } catch (InvalidMatrixException ime) {
094 // expected behavior
095 } catch (Exception e) {
096 fail("wrong exception caught");
097 }
098 try {
099 solver.solve(b.getColumn(0));
100 fail("an exception should have been thrown");
101 } catch (InvalidMatrixException ime) {
102 // expected behavior
103 } catch (Exception e) {
104 fail("wrong exception caught");
105 }
106 try {
107 solver.solve(b.getColumnVector(0));
108 fail("an exception should have been thrown");
109 } catch (InvalidMatrixException ime) {
110 // expected behavior
111 } catch (Exception e) {
112 fail("wrong exception caught");
113 }
114 try {
115 solver.solve(new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(0)));
116 fail("an exception should have been thrown");
117 } catch (InvalidMatrixException ime) {
118 // expected behavior
119 } catch (Exception e) {
120 fail("wrong exception caught");
121 }
122 }
123
124 /** test solve */
125 public void testSolve() {
126 DecompositionSolver solver =
127 new SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare)).getSolver();
128 RealMatrix b = MatrixUtils.createRealMatrix(new double[][] {
129 { 1, 2, 3 }, { 0, -5, 1 }
130 });
131 RealMatrix xRef = MatrixUtils.createRealMatrix(new double[][] {
132 { -8.0 / 25.0, -263.0 / 75.0, -29.0 / 75.0 },
133 { 19.0 / 25.0, 78.0 / 25.0, 49.0 / 25.0 }
134 });
135
136 // using RealMatrix
137 assertEquals(0, solver.solve(b).subtract(xRef).getNorm(), normTolerance);
138
139 // using double[]
140 for (int i = 0; i < b.getColumnDimension(); ++i) {
141 assertEquals(0,
142 new ArrayRealVector(solver.solve(b.getColumn(i))).subtract(xRef.getColumnVector(i)).getNorm(),
143 1.0e-13);
144 }
145
146 // using Array2DRowRealMatrix
147 for (int i = 0; i < b.getColumnDimension(); ++i) {
148 assertEquals(0,
149 solver.solve(b.getColumnVector(i)).subtract(xRef.getColumnVector(i)).getNorm(),
150 1.0e-13);
151 }
152
153 // using RealMatrix with an alternate implementation
154 for (int i = 0; i < b.getColumnDimension(); ++i) {
155 ArrayRealVectorTest.RealVectorTestImpl v =
156 new ArrayRealVectorTest.RealVectorTestImpl(b.getColumn(i));
157 assertEquals(0,
158 solver.solve(v).subtract(xRef.getColumnVector(i)).getNorm(),
159 1.0e-13);
160 }
161
162 }
163
164 /** test condition number */
165 public void testConditionNumber() {
166 SingularValueDecompositionImpl svd =
167 new SingularValueDecompositionImpl(MatrixUtils.createRealMatrix(testSquare));
168 assertEquals(3.0, svd.getConditionNumber(), 1.0e-15);
169 }
170
171 }