/*******************************************************************************
* Copyright (c) 2010 Haifeng Li
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package smile.math.matrix;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import smile.math.Math;
/**
*
* @author Haifeng Li
*/
public class SingularValueDecompositionTest {
public SingularValueDecompositionTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose1() {
System.out.println("decompose symm");
double[][] A = {
{0.9000, 0.4000, 0.7000},
{0.4000, 0.5000, 0.3000},
{0.7000, 0.3000, 0.8000}
};
double[] s = {1.7498382, 0.3165784, 0.1335834};
double[][] U = {
{0.6881997, -0.07121225, 0.7220180},
{0.3700456, 0.89044952, -0.2648886},
{0.6240573, -0.44947578, -0.6391588}
};
double[][] V = {
{0.6881997, -0.07121225, 0.7220180},
{0.3700456, 0.89044952, -0.2648886},
{0.6240573, -0.44947578, -0.6391588}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose2() {
System.out.println("decompose asymm");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336, -0.1392502, -1.88207227},
{0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873, -0.5553013, 1.63805985},
{0.12641406, -0.8710055, -0.2712301, 0.2296515, 1.1781535, -0.2158704, -0.27529472}
};
double[] s = {3.8589375, 3.4396766, 2.6487176, 2.2317399, 1.5165054, 0.8109055, 0.2706515};
double[][] U = {
{-0.3082776, 0.77676231, 0.01330514, 0.23231424, -0.47682758, 0.13927109, 0.02640713},
{-0.4013477, -0.09112050, 0.48754440, 0.47371793, 0.40636608, 0.24600706, -0.37796295},
{0.0599719, -0.31406586, 0.45428229, -0.08071283, -0.38432597, 0.57320261, 0.45673993},
{-0.7694214, -0.12681435, -0.05536793, -0.62189972, -0.02075522, -0.01724911, -0.03681864},
{-0.3319069, -0.17984404, -0.54466777, 0.45335157, 0.19377726, 0.12333423, 0.55003852},
{0.1259351, 0.49087824, 0.16349687, -0.32080176, 0.64828744, 0.20643772, 0.38812467},
{0.1491884, 0.01768604, -0.47884363, -0.14108924, 0.03922507, 0.73034065, -0.43965505}
};
double[][] V = {
{-0.2122609, -0.54650056, 0.08071332, -0.43239135, -0.2925067, 0.1414550, 0.59769207},
{-0.1943605, 0.63132116, -0.54059857, -0.37089970, -0.1363031, 0.2892641, 0.17774114},
{0.3031265, -0.06182488, 0.18579097, -0.38606409, -0.5364911, 0.2983466, -0.58642548},
{0.1844063, 0.24425278, 0.25923756, 0.59043765, -0.4435443, 0.3959057, 0.37019098},
{-0.7164205, 0.30694911, 0.58264743, -0.07458095, -0.1142140, -0.1311972, -0.13124764},
{-0.1103067, -0.10633600, 0.18257905, -0.03638501, 0.5722925, 0.7784398, -0.09153611},
{-0.5156083, -0.36573746, -0.47613340, 0.41342817, -0.2659765, 0.1654796, -0.32346758}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose3() {
System.out.println("decompose m = n+1");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336, -0.1392502},
{0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873, -0.5553013},
{0.12641406, -0.8710055, -0.2712301, 0.2296515, 1.1781535, -0.2158704}
};
double[] s = {3.6447007, 3.1719019, 2.4155022, 1.6952749, 1.0349052, 0.6735233};
double[][] U = {
{-0.66231606, 0.51980064, -0.26908096, -0.33255132, 0.1998343961, 0.25344461},
{-0.30950323, -0.38356363, -0.57342388, 0.43584295, -0.2842953084, 0.06773874},
{0.17209598, -0.40152786, -0.25549740, -0.47194228, -0.1795895194, 0.60960160},
{-0.58855512, -0.52801793, 0.59486615, -0.13721651, -0.0004042427, -0.01414006},
{-0.06838272, 0.03221968, 0.14785619, 0.64819245, 0.3955572924, 0.53374206},
{-0.23683786, 0.25613876, 0.07459517, 0.19208798, -0.7235935956, -0.10586201},
{0.16959559, 0.27570548, 0.39014092, 0.02900709, -0.4085787191, 0.51310416}
};
double[][] V = {
{-0.08624942, 0.642381656, -0.35639657, 0.2600624, -0.303192728, -0.5415995},
{0.46728106, -0.567452824, -0.56054543, 0.1717478, 0.067268188, -0.3337846},
{-0.26399674, -0.005897261, -0.02438536, 0.8302504, 0.448103782, 0.1989057},
{-0.03389306, -0.296652409, 0.68563317, 0.2309273, -0.145824242, -0.6051146},
{0.83642784, 0.352498963, 0.29305340, 0.2264531, 0.006202435, 0.1973149},
{0.06127719, 0.230326187, 0.04693098, -0.3300697, 0.825499232, -0.3880689}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose4() {
System.out.println("decompose m = n+2");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336},
{0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873},
{0.12641406, -0.8710055, -0.2712301, 0.2296515, 1.1781535}
};
double[] s = {3.6392869, 3.0965326, 2.4131673, 1.6285557, 0.7495616};
double[][] U = {
{-0.68672751, -0.47077690, -0.27062524, 0.30518577, 0.35585700},
{-0.28422169, 0.33969351, -0.56700359, -0.38788214, -0.15789372},
{0.18880503, 0.39049353, -0.26448028, 0.50872376, 0.42411327},
{-0.56957699, 0.56761727, 0.58111879, 0.11662686, -0.01347444},
{-0.06682433, -0.04559753, 0.15586923, -0.68802278, 0.60990585},
{-0.23677832, -0.29935481, 0.09428368, -0.03224480, -0.50781217},
{0.16440378, -0.31082218, 0.40550635, 0.09794049, 0.19627380}
};
double[][] V = {
{-0.10646320, -0.668422750, -0.33744231, -0.1953744, -0.6243702},
{0.48885825, 0.546411345, -0.57018018, -0.2348795, -0.2866678},
{-0.26164973, 0.002221196, -0.01788181, -0.9049532, 0.3350739},
{-0.02353895, 0.306904408, 0.68247803, -0.2353931, -0.6197333},
{0.82502638, -0.400562630, 0.30810911, -0.1797507, 0.1778750}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose5() {
System.out.println("decompose m = n+3");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701},
{0.06605075, 1.0315583, 0.8294362, -0.3646043},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332},
{0.88248425, -0.9360321, 0.1393172, 0.1393281},
{0.12641406, -0.8710055, -0.2712301, 0.2296515}
};
double[] s = {3.2188437, 2.5504483, 1.7163918, 0.9212875};
double[][] U = {
{-0.7390710, 0.15540183, 0.093738524, -0.60555964},
{0.1716777, 0.26405327, -0.616548935, -0.11171885},
{0.4583068, 0.19615535, 0.365025826, -0.56118537},
{0.1185448, -0.88710768, -0.004538332, -0.24629659},
{-0.1055393, -0.19831478, -0.634814754, -0.26986239},
{-0.3836089, -0.06331799, 0.006896881, 0.41026537},
{-0.2047156, -0.19326474, 0.273456965, 0.06389058}
};
double[][] V = {
{-0.5820171, 0.4822386, -0.12201399, 0.6432842},
{0.7734720, 0.4993237, -0.27962029, 0.2724507},
{-0.1670058, -0.1563235, -0.94966302, -0.2140379},
{0.1873664, -0.7026270, -0.07117046, 0.6827473}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose6() {
System.out.println("decompose m = n-1");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336, -0.1392502, -1.88207227},
{0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873, -0.5553013, 1.63805985},};
double[] s = {3.8244094, 3.4392541, 2.3784254, 2.1694244, 1.5150752, 0.4743856, 0.0};
double[][] U = {
{0.31443091, 0.77409564, -0.06404561, 0.2362505, 0.48411517, 0.08732402},
{0.37429954, -0.08997642, 0.33948894, 0.7403030, -0.37663472, -0.21598420},
{-0.08460683, -0.30944648, 0.49768196, 0.1798789, 0.40657776, 0.67211259},
{0.78096534, -0.13597601, 0.27845058, -0.5407806, 0.01748391, -0.03632677},
{0.35762337, -0.18789909, -0.68652942, 0.1670810, -0.20242003, 0.54459792},
{-0.12678093, 0.49307962, 0.29000123, -0.2083774, -0.64590538, 0.44281315}
};
double[][] V = {
{-0.2062642, 0.54825338, -0.27956720, 0.3408979, -0.2925761, -0.412469519},
{-0.2516350, -0.62127194, 0.28319612, 0.5322251, -0.1297528, -0.410270389},
{0.3043552, 0.05848409, -0.35475338, 0.2434904, -0.5456797, 0.040325347},
{0.2047160, -0.24974630, 0.01491918, -0.6588368, -0.4616580, -0.465507184},
{-0.6713331, -0.30795185, -0.57548345, -0.1976943, -0.1242132, 0.261610893},
{-0.1122210, 0.10728081, -0.28476779, -0.1527923, 0.5474147, -0.612188492},
{-0.5443460, 0.37590198, 0.55072289, -0.2115256, -0.2675392, -0.003003781}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose7() {
System.out.println("decompose m = n-2");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336, -0.1392502, -1.88207227},};
double[] s = {3.8105658, 3.0883849, 2.2956507, 2.0984771, 0.9019027, 0.0, 0.0};
double[][] U = {
{0.4022505, -0.8371341, 0.218900330, -0.01150020, 0.29891712},
{0.3628648, 0.1788073, 0.520476180, 0.66921454, -0.34294833},
{-0.1204081, 0.3526074, 0.512685919, -0.03159520, 0.77286790},
{0.7654028, 0.3523577, -0.005786511, -0.53518467, -0.05955197},
{0.3258590, 0.1369180, -0.646766462, 0.51439164, 0.43836489}
};
double[][] V = {
{-0.1340510, -0.6074832, -0.07579249, 0.38390363, -0.4471462},
{-0.3332981, 0.5665840, 0.37922383, 0.48268873, -0.1570301},
{0.3105522, -0.0324612, -0.30945577, 0.48678825, -0.3365301},
{0.1820803, 0.4083420, -0.35471238, -0.43842294, -0.6389961},
{-0.7114696, 0.1311251, -0.64046888, 0.07815179, 0.1194533},
{-0.1112159, -0.2728406, -0.19551704, -0.23056606, 0.1841538},
{-0.4720051, -0.2247534, 0.42477493, -0.36219292, -0.4534882}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose8() {
System.out.println("decompose m = n-3");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563},};
double[] s = {3.668957, 3.068763, 2.179053, 1.293110, 0.0, 0.0, 0.0};
double[][] U = {
{-0.4918880, 0.7841689, -0.1533124, 0.34586230},
{-0.3688033, -0.2221466, -0.8172311, -0.38310353},
{0.1037476, -0.3784190, -0.3438745, 0.85310363},
{-0.7818356, -0.4387814, 0.4363243, 0.07632262}
};
double[][] V = {
{0.11456074, 0.63620515, -0.23901163, -0.4625536},
{0.36382542, -0.54930940, -0.60614838, -0.1412273},
{-0.22044591, 0.06740501, -0.13539726, -0.6782114},
{-0.14811938, -0.41609019, 0.59161667, -0.4135324},
{0.81615679, -0.00968160, 0.35107473, -0.2405136},
{0.09577622, 0.28606564, 0.28844835, 0.1625626},
{0.32967585, 0.18412070, -0.02567023, 0.2254902}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-6));
assertEquals(U.length, result.getU().nrows());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecompose9() {
System.out.println("decompose sparse matrix");
double[][] A = {
{1, 0, 0, 1, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 1, 0, 0, 0, 0},
{0, 1, 1, 2, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1, 1}
};
double[] s = {3.34088, 2.5417, 2.35394, 1.64453, 1.50483, 1.30638, 0.845903, 0.560134, 0.363677};
double[][] Vt = {
{0.197393, 0.60599, 0.462918, 0.542114, 0.279469, 0.00381521, 0.0146315, 0.0241368, 0.0819574},
{0.0559135, -0.165593, 0.127312, 0.231755, -0.106775, -0.192848, -0.437875, -0.615122, -0.529937},
{-0.11027, 0.497326, -0.207606, -0.569921, 0.50545, -0.0981842, -0.192956, -0.252904, -0.0792731},
{-0.949785, -0.0286489, 0.0416092, 0.267714, 0.150035, 0.0150815, 0.0155072, 0.010199, -0.0245549},
{-0.0456786, 0.206327, -0.378336, 0.205605, -0.327194, -0.394841, -0.349485, -0.149798, 0.601993},
{-0.0765936, -0.256475, 0.7244, -0.368861, 0.034813, -0.300161, -0.212201, 9.74342e-05, 0.362219},
{-0.177318, 0.432984, 0.23689, -0.2648, -0.672304, 0.34084, 0.152195, -0.249146, -0.0380342},
{-0.0143933, 0.0493053, 0.0088255, -0.0194669, -0.0583496, 0.454477, -0.761527, 0.449643, -0.0696375},
{-0.0636923, 0.242783, 0.0240769, -0.0842069, -0.262376, -0.619847, 0.0179752, 0.51989, -0.453507}
};
double[][] Ut = {
{0.221351, 0.197645, 0.24047, 0.403599, 0.644481, 0.265037, 0.265037, 0.300828, 0.205918, 0.0127462, 0.0361358, 0.0317563},
{0.11318, 0.0720878, -0.043152, -0.0570703, 0.167301, -0.10716, -0.10716, 0.14127, -0.273647, -0.490162, -0.622785, -0.450509},
{-0.288958, -0.13504, 0.164429, 0.337804, -0.361148, 0.425998, 0.425998, -0.330308, 0.177597, -0.23112, -0.223086, -0.141115},
{-0.414751, -0.55224, -0.594962, 0.0991137, 0.333462, 0.0738122, 0.0738122, 0.188092, -0.0323519, 0.024802, 0.000700072, -0.00872947},
{0.106275, -0.281769, 0.106755, -0.331734, 0.158955, -0.0803194, -0.0803194, -0.114785, 0.53715, -0.59417, 0.0682529, 0.300495},
{-0.340983, 0.495878, -0.254955, 0.384832, -0.206523, -0.169676, -0.169676, 0.272155, 0.080944, -0.392125, 0.114909, 0.277343},
{-0.522658, 0.0704234, 0.30224, -0.00287218, 0.165829, -0.282916, -0.282916, -0.0329941, 0.466898, 0.288317, -0.159575, -0.339495},
{-0.0604501, -0.00994004, 0.062328, -0.000390504, 0.034272, -0.0161465, -0.0161465, -0.018998, -0.0362988, 0.254568, -0.681125, 0.6784180},
{-0.406678, -0.10893, 0.492444, 0.0123293, 0.270696, -0.0538747, -0.0538747, -0.165339, -0.579426, -0.225424, 0.231961, 0.182535}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-5));
assertEquals(Ut[0].length, result.getU().nrows());
assertEquals(Ut.length, result.getU().ncols());
for (int i = 0; i < Ut.length; i++) {
for (int j = 0; j < Ut[i].length; j++) {
assertEquals(Math.abs(Ut[i][j]), Math.abs(result.getU().get(j, i)), 1E-5);
}
}
assertEquals(Vt[0].length, result.getV().nrows());
assertEquals(Vt.length, result.getV().ncols());
for (int i = 0; i < Vt.length; i++) {
for (int j = 0; j < Vt[i].length; j++) {
assertEquals(Math.abs(Vt[i][j]), Math.abs(result.getV().get(j, i)), 1E-5);
}
}
}
/**
* Test of solve method, of class SingularValueDecomposition.
*/
@Test
public void testSolve_doubleArr_doubleArr() {
System.out.println("solve");
double[][] A = {
{0.9000, 0.4000, 0.7000},
{0.4000, 0.5000, 0.3000},
{0.7000, 0.3000, 0.8000}
};
double[] B = {0.5, 0.5, 0.5};
double[] X = {-0.2027027, 0.8783784, 0.4729730};
SingularValueDecomposition result = new SingularValueDecomposition(A);
double[] x = new double[B.length];
result.solve(B, x);
assertEquals(X.length, x.length);
for (int i = 0; i < X.length; i++) {
assertEquals(X[i], x[i], 1E-7);
}
}
/**
* Test of solve method, of class SingularValueDecomposition.
*/
@Test
public void testSolve_doubleArrArr_doubleArrArr() {
System.out.println("solve");
double[][] A = {
{0.9000, 0.4000, 0.7000},
{0.4000, 0.5000, 0.3000},
{0.7000, 0.3000, 0.8000}
};
double[][] B2 = {
{0.5, 0.2},
{0.5, 0.8},
{0.5, 0.3}
};
double[][] X2 = {
{-0.2027027, -1.2837838},
{0.8783784, 2.2297297},
{0.4729730, 0.6621622}
};
SingularValueDecomposition result = new SingularValueDecomposition(A);
double[][] x = new double[B2.length][B2[0].length];
result.solve(B2, x);
assertEquals(X2.length, x.length);
assertEquals(X2[0].length, x[0].length);
for (int i = 0; i < X2.length; i++) {
for (int j = 0; j < X2[i].length; j++) {
assertEquals(X2[i][j], x[i][j], 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecomposeLanczos() {
System.out.println("decompose Lanczos");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563},
{-0.07318103, -0.2783787, 1.2237598, 0.1995332, 0.2545336, -0.1392502, -1.88207227},
{0.88248425, -0.9360321, 0.1393172, 0.1393281, -0.3277873, -0.5553013, 1.63805985},
{0.12641406, -0.8710055, -0.2712301, 0.2296515, 1.1781535, -0.2158704, -0.27529472}
};
double[] s = {3.8589375, 3.4396766, 2.6487176, 2.2317399, 1.5165054, 0.8109055, 0.2706515};
double[][] U = {
{-0.3082776, 0.77676231, 0.01330514, 0.23231424, -0.47682758, 0.13927109, 0.02640713},
{-0.4013477, -0.09112050, 0.48754440, 0.47371793, 0.40636608, 0.24600706, -0.37796295},
{0.0599719, -0.31406586, 0.45428229, -0.08071283, -0.38432597, 0.57320261, 0.45673993},
{-0.7694214, -0.12681435, -0.05536793, -0.62189972, -0.02075522, -0.01724911, -0.03681864},
{-0.3319069, -0.17984404, -0.54466777, 0.45335157, 0.19377726, 0.12333423, 0.55003852},
{0.1259351, 0.49087824, 0.16349687, -0.32080176, 0.64828744, 0.20643772, 0.38812467},
{0.1491884, 0.01768604, -0.47884363, -0.14108924, 0.03922507, 0.73034065, -0.43965505}
};
double[][] V = {
{-0.2122609, -0.54650056, 0.08071332, -0.43239135, -0.2925067, 0.1414550, 0.59769207},
{-0.1943605, 0.63132116, -0.54059857, -0.37089970, -0.1363031, 0.2892641, 0.17774114},
{0.3031265, -0.06182488, 0.18579097, -0.38606409, -0.5364911, 0.2983466, -0.58642548},
{0.1844063, 0.24425278, 0.25923756, 0.59043765, -0.4435443, 0.3959057, 0.37019098},
{-0.7164205, 0.30694911, 0.58264743, -0.07458095, -0.1142140, -0.1311972, -0.13124764},
{-0.1103067, -0.10633600, 0.18257905, -0.03638501, 0.5722925, 0.7784398, -0.09153611},
{-0.5156083, -0.36573746, -0.47613340, 0.41342817, -0.2659765, 0.1654796, -0.32346758}
};
SingularValueDecomposition result = Lanczos.svd(new RowMajorMatrix(A), 7);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-7));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecomposeLanczos2() {
System.out.println("decompose Lanczos m = n-3");
double[][] A = {
{1.19720880, -1.8391378, 0.3019585, -1.1165701, -1.7210814, 0.4918882, -0.04247433},
{0.06605075, 1.0315583, 0.8294362, -0.3646043, -1.6038017, -0.9188110, -0.63760340},
{-1.02637715, 1.0747931, -0.8089055, -0.4726863, -0.2064826, -0.3325532, 0.17966051},
{-1.45817729, -0.8942353, 0.3459245, 1.5068363, -2.0180708, -0.3696350, -1.19575563},};
double[] s = {3.668957, 3.068763, 2.179053, 1.293110};
double[][] U = {
{-0.4918880, 0.7841689, -0.1533124, 0.34586230},
{-0.3688033, -0.2221466, -0.8172311, -0.38310353},
{0.1037476, -0.3784190, -0.3438745, 0.85310363},
{-0.7818356, -0.4387814, 0.4363243, 0.07632262}
};
double[][] V = {
{0.11456074, 0.63620515, -0.23901163, -0.4625536},
{0.36382542, -0.54930940, -0.60614838, -0.1412273},
{-0.22044591, 0.06740501, -0.13539726, -0.6782114},
{-0.14811938, -0.41609019, 0.59161667, -0.4135324},
{0.81615679, -0.00968160, 0.35107473, -0.2405136},
{0.09577622, 0.28606564, 0.28844835, 0.1625626},
{0.32967585, 0.18412070, -0.02567023, 0.2254902}
};
SingularValueDecomposition result = Lanczos.svd(new RowMajorMatrix(A), 4);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-6));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-7);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-7);
}
}
}
/**
* Test of decompose method, of class SingularValueDecomposition.
*/
@Test
public void testDecomposeLanczosSparse() {
System.out.println("decompose Lanczos sparse matrix");
double[][] A = new double[][]{
{1, 0, 0, 1, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0, 0, 0},
{1, 1, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 1, 0, 0, 0, 0},
{0, 1, 1, 2, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 0, 0, 0, 0},
{0, 1, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 0, 0, 0, 1, 1},};
double[][] Vt = new double[][]{
{0.197393, 0.60599, 0.462918, 0.542114, 0.279469, 0.00381521, 0.0146315, 0.0241368, 0.0819574},
{0.0559135, -0.165593, 0.127312, 0.231755, -0.106775, -0.192848, -0.437875, -0.615122, -0.529937},
{-0.11027, 0.497326, -0.207606, -0.569921, 0.50545, -0.0981842, -0.192956, -0.252904, -0.0792731},
{-0.949785, -0.0286489, 0.0416092, 0.267714, 0.150035, 0.0150815, 0.0155072, 0.010199, -0.0245549},
{-0.0456786, 0.206327, -0.378336, 0.205605, -0.327194, -0.394841, -0.349485, -0.149798, 0.601993},
{-0.0765936, -0.256475, 0.7244, -0.368861, 0.034813, -0.300161, -0.212201, 9.74342e-05, 0.362219},
{-0.177318, 0.432984, 0.23689, -0.2648, -0.672304, 0.34084, 0.152195, -0.249146, -0.0380342},
{-0.0143933, 0.0493053, 0.0088255, -0.0194669, -0.0583496, 0.454477, -0.761527, 0.449643, -0.0696375},
{-0.0636923, 0.242783, 0.0240769, -0.0842069, -0.262376, -0.619847, 0.0179752, 0.51989, -0.453507},};
double[][] Ut = new double[][]{
{0.221351, 0.197645, 0.24047, 0.403599, 0.644481, 0.265037, 0.265037, 0.300828, 0.205918, 0.0127462, 0.0361358, 0.0317563},
{0.11318, 0.0720878, -0.043152, -0.0570703, 0.167301, -0.10716, -0.10716, 0.14127, -0.273647, -0.490162, -0.622785, -0.450509},
{-0.288958, -0.13504, 0.164429, 0.337804, -0.361148, 0.425998, 0.425998, -0.330308, 0.177597, -0.23112, -0.223086, -0.141115},
{-0.414751, -0.55224, -0.594962, 0.0991137, 0.333462, 0.0738122, 0.0738122, 0.188092, -0.0323519, 0.024802, 0.000700072, -0.00872947},
{0.106275, -0.281769, 0.106755, -0.331734, 0.158955, -0.0803194, -0.0803194, -0.114785, 0.53715, -0.59417, 0.0682529, 0.300495},
{-0.340983, 0.495878, -0.254955, 0.384832, -0.206523, -0.169676, -0.169676, 0.272155, 0.080944, -0.392125, 0.114909, 0.277343},
{-0.522658, 0.0704234, 0.30224, -0.00287218, 0.165829, -0.282916, -0.282916, -0.0329941, 0.466898, 0.288317, -0.159575, -0.339495},
{-0.0604501, -0.00994004, 0.062328, -0.000390504, 0.034272, -0.0161465, -0.0161465, -0.018998, -0.0362988, 0.254568, -0.681125, 0.6784180},
{-0.406678, -0.10893, 0.492444, 0.0123293, 0.270696, -0.0538747, -0.0538747, -0.165339, -0.579426, -0.225424, 0.231961, 0.182535},};
double[] s = {3.34088, 2.5417, 2.35394, 1.64453, 1.50483, 1.30638, 0.845903, 0.560134, 0.363677};
double[][] U = Math.transpose(Ut);
double[][] V = Math.transpose(Vt);
SingularValueDecomposition result = Lanczos.svd(new SparseMatrix(A), 9);
assertTrue(Math.equals(s, result.getSingularValues(), 1E-5));
assertEquals(U.length, result.getU().nrows());
assertEquals(U[0].length, result.getU().ncols());
for (int i = 0; i < U.length; i++) {
for (int j = 0; j < U[i].length; j++) {
assertEquals(Math.abs(U[i][j]), Math.abs(result.getU().get(i, j)), 1E-5);
}
}
assertEquals(V.length, result.getV().nrows());
assertEquals(V[0].length, result.getV().ncols());
for (int i = 0; i < V.length; i++) {
for (int j = 0; j < V[i].length; j++) {
assertEquals(Math.abs(V[i][j]), Math.abs(result.getV().get(i, j)), 1E-5);
}
}
}
}