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 }