/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.ignite.ml.math.decompositions; import org.apache.ignite.ml.math.Matrix; import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix; import org.apache.ignite.ml.math.impls.matrix.PivotedMatrixView; import org.apache.ignite.ml.math.util.MatrixUtil; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; /** */ public class SingularValueDecompositionTest { /** */ @Test public void basicTest() { basicTest(new DenseLocalOnHeapMatrix(new double[][] { {2.0d, -1.0d, 0.0d}, {-1.0d, 2.0d, -1.0d}, {0.0d, -1.0d, 2.0d} })); } /** * Test for {@link MatrixUtil} features (more specifically, we test matrix which does not have * a native like/copy methods support). */ @Test public void matrixUtilTest() { basicTest(new PivotedMatrixView(new DenseLocalOnHeapMatrix(new double[][] { {2.0d, -1.0d, 0.0d}, {-1.0d, 2.0d, -1.0d}, {0.0d, -1.0d, 2.0d} }))); } /** */ @Test public void rowsLessThanColumnsTest() { DenseLocalOnHeapMatrix m = new DenseLocalOnHeapMatrix(new double[][] { {2.0d, -1.0d, 0.0d}, {-1.0d, 2.0d, -1.0d} }); SingularValueDecomposition dec = new SingularValueDecomposition(m); assertEquals("Unexpected value for singular values size.", 2, dec.getSingularValues().length); Matrix s = dec.getS(); Matrix u = dec.getU(); Matrix v = dec.getV(); Matrix covariance = dec.getCovariance(0.5); assertNotNull("Matrix s is expected to be not null.", s); assertNotNull("Matrix u is expected to be not null.", u); assertNotNull("Matrix v is expected to be not null.", v); assertNotNull("Covariance matrix is expected to be not null.", covariance); dec.destroy(); } /** */ @Test(expected = AssertionError.class) public void nullMatrixTest() { new SingularValueDecomposition(null); } /** */ private void basicTest(Matrix m) { SingularValueDecomposition dec = new SingularValueDecomposition(m); assertEquals("Unexpected value for singular values size.", 3, dec.getSingularValues().length); Matrix s = dec.getS(); Matrix u = dec.getU(); Matrix v = dec.getV(); Matrix covariance = dec.getCovariance(0.5); assertNotNull("Matrix s is expected to be not null.", s); assertNotNull("Matrix u is expected to be not null.", u); assertNotNull("Matrix v is expected to be not null.", v); assertNotNull("Covariance matrix is expected to be not null.", covariance); assertTrue("Decomposition cond is expected to be positive.", dec.cond() > 0); assertTrue("Decomposition norm2 is expected to be positive.", dec.norm2() > 0); assertEquals("Decomposition rank differs from expected.", 3, dec.rank()); assertEquals("Decomposition singular values size differs from expected.", 3, dec.getSingularValues().length); Matrix recomposed = (u.times(s).times(v.transpose())); for (int row = 0; row < m.rowSize(); row++) for (int col = 0; col < m.columnSize(); col++) assertEquals("Unexpected recomposed matrix value at (" + row + "," + col + ").", m.get(row, col), recomposed.get(row, col), 0.001); for (int row = 0; row < covariance.rowSize(); row++) for (int col = row + 1; col < covariance.columnSize(); col++) assertEquals("Unexpected covariance matrix value at (" + row + "," + col + ").", covariance.get(row, col), covariance.get(col, row), 0.001); dec.destroy(); } }