/*
* 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 hivemall.utils.math;
import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.RealMatrix;
import org.apache.commons.math3.linear.SingularValueDecomposition;
import org.junit.Assert;
import org.junit.Test;
public class MatrixUtilsTest {
@Test
public void testAryule1k2() {
int k = 2;
double[] R = new double[] {1, 2, 3};
double[] A = new double[k + 1];
MatrixUtils.aryule(R, A, k);
Assert.assertEquals(1.3333333333333335d, A[1], 0.001d);
Assert.assertEquals(0.3333333333333333d, A[2], 0.001d);
}
@Test
public void testAryule1k9() {
final int k = 9;
double[] R = new double[] {143.85, 141.95, 141.45, 142.30, 140.60, 140.00, 138.40, 137.10,
138.90, 139.85};
double[] A = new double[k + 1];
MatrixUtils.aryule(R, A, k);
double[] expected = new double[] {-1.0, 2.90380682, 0.31235631, 1.26463104, -3.30187384,
-1.61653593, -2.10367317, 1.37563117, 2.18139823, 0.02314717};
Assert.assertArrayEquals(expected, A, 0.01d);
}
@Test
public void testArburgk2() {
// Expected outputs are obtained from Octave's arburg() function
// k must be less than (X.length - 2) on Octave, but A can be computed w/o the assumption
int k = 2;
double[] X = new double[] {1, 2, 3, 4, 5};
double[] A = new double[k + 1];
MatrixUtils.arburg(X, A, k);
Assert.assertEquals(-1.86391d, A[1], 0.00001d);
Assert.assertEquals(0.95710d, A[2], 0.00001d);
}
@Test
public void testArburgk5() {
final int k = 5;
double[] X = new double[] {143.85, 141.95, 141.45, 142.30, 140.60, 140.00, 138.40, 137.10,
138.90, 139.85};
double[] A = new double[k + 1];
MatrixUtils.arburg(X, A, k);
double[] expected = new double[] {-1.0, -1.31033, 0.58569, -0.56058, 0.63859, -0.35334};
Assert.assertArrayEquals(expected, A, 0.00001d);
}
@Test
public void testToeplitz() {
RealMatrix[] c = new RealMatrix[] {new Array2DRowRealMatrix(new double[] {1}),
new Array2DRowRealMatrix(new double[] {2}),
new Array2DRowRealMatrix(new double[] {3})};
RealMatrix[][] A = MatrixUtils.toeplitz(c, 3);
// 1 2 3
// 2 1 2
// 3 2 1
Assert.assertArrayEquals(new RealMatrix[] {new Array2DRowRealMatrix(new double[] {1}),
new Array2DRowRealMatrix(new double[] {2}),
new Array2DRowRealMatrix(new double[] {3})}, A[0]);
Assert.assertArrayEquals(new RealMatrix[] {new Array2DRowRealMatrix(new double[] {2}),
new Array2DRowRealMatrix(new double[] {1}),
new Array2DRowRealMatrix(new double[] {2})}, A[1]);
Assert.assertArrayEquals(new RealMatrix[] {new Array2DRowRealMatrix(new double[] {3}),
new Array2DRowRealMatrix(new double[] {2}),
new Array2DRowRealMatrix(new double[] {1})}, A[2]);
}
@Test
public void testCombineMatrices1D() {
RealMatrix[] m1 = new RealMatrix[] {new Array2DRowRealMatrix(new double[] {0, 1}),
new Array2DRowRealMatrix(new double[] {2, 3}),
new Array2DRowRealMatrix(new double[] {4, 5})};
RealMatrix flatten1 = MatrixUtils.combinedMatrices(m1);
double[][] data = flatten1.getData();
Assert.assertEquals(6, data.length);
Assert.assertArrayEquals(new double[] {0}, data[0], 0.d);
Assert.assertArrayEquals(new double[] {1}, data[1], 0.d);
Assert.assertArrayEquals(new double[] {2}, data[2], 0.d);
Assert.assertArrayEquals(new double[] {3}, data[3], 0.d);
Assert.assertArrayEquals(new double[] {4}, data[4], 0.d);
Assert.assertArrayEquals(new double[] {5}, data[5], 0.d);
}
@Test
public void testCombinedMatrices2D() {
RealMatrix[] m1 = new RealMatrix[] {
new Array2DRowRealMatrix(new double[][] {new double[] {1, 2, 3},
new double[] {4, 5, 6}}),
new Array2DRowRealMatrix(new double[][] {new double[] {7, 8, 9},
new double[] {10, 11, 12}}),
new Array2DRowRealMatrix(new double[][] {new double[] {13, 14, 15},
new double[] {16, 17, 18}})};
RealMatrix flatten1 = MatrixUtils.combinedMatrices(m1);
Assert.assertEquals(3, flatten1.getColumnDimension());
Assert.assertEquals(6, flatten1.getRowDimension());
}
@Test
public void testCombinedMatrices2D_Toeplitz() {
RealMatrix e1 = new Array2DRowRealMatrix(new double[] {1, 1.1});
RealMatrix e2 = new Array2DRowRealMatrix(new double[] {2, 2.2});
RealMatrix e2T = e2.transpose();
RealMatrix e3 = new Array2DRowRealMatrix(new double[] {3, 3.3});
RealMatrix e3T = e3.transpose();
RealMatrix[] m1 = new RealMatrix[] {e1, e2, e3};
// {1.0,1.1}
// {2.0,2.2}
// {3.0,3.3}
RealMatrix[][] toeplitz1 = MatrixUtils.toeplitz(m1, 3);
Assert.assertEquals(3, toeplitz1.length);
Assert.assertEquals(3, toeplitz1[0].length);
Assert.assertEquals(3, toeplitz1[1].length);
Assert.assertEquals(3, toeplitz1[2].length);
Assert.assertEquals(e1, toeplitz1[0][0]);
Assert.assertEquals(e1, toeplitz1[1][1]);
Assert.assertEquals(e1, toeplitz1[2][2]);
Assert.assertEquals(e2, toeplitz1[1][0]);
Assert.assertEquals(e2, toeplitz1[2][1]);
Assert.assertEquals(e3, toeplitz1[2][0]);
Assert.assertEquals(e2T, toeplitz1[0][1]);
Assert.assertEquals(e2T, toeplitz1[1][2]);
Assert.assertEquals(e3T, toeplitz1[0][2]);
// {1.0,1.1} {2.0,2.2}' {3.0,3.3}'
// {2.0,2.2} {1.0,1.1} {2.0,2.2}'
// {3.0,3.3} {2.0,2.2} {1.0,1.1}
RealMatrix flatten1 = MatrixUtils.combinedMatrices(toeplitz1, 2);
// 1.0 0.0 2.0 2.2 3.0 3.3
// 1.1 0.0 0.0 0.0 0.0 0.0
// 2.0 0.0 1.0 0.0 2.0 2.2
// 2.2 0.0 1.1 0.0 0.0 0.0
// 3.0 0.0 2.0 0.0 1.0 0.0
// 3.3 0.0 2.2 0.0 1.1 0.0
Assert.assertEquals(6, flatten1.getRowDimension());
Assert.assertEquals(6, flatten1.getColumnDimension());
}
@Test
public void testFlatten1D() {
RealMatrix[] m1 = new RealMatrix[] {new Array2DRowRealMatrix(new double[] {0, 1}),
new Array2DRowRealMatrix(new double[] {2, 3}),
new Array2DRowRealMatrix(new double[] {4, 5})};
double[] actual = MatrixUtils.flatten(m1);
Assert.assertArrayEquals(actual, new double[] {0, 1, 2, 3, 4, 5}, 0.d);
}
@Test
public void testFlatten2D() {
RealMatrix[] m1 = new RealMatrix[] {
new Array2DRowRealMatrix(new double[][] {new double[] {1, 2, 3},
new double[] {4, 5, 6}}),
new Array2DRowRealMatrix(new double[][] {new double[] {7, 8, 9},
new double[] {10, 11, 12}}),
new Array2DRowRealMatrix(new double[][] {new double[] {13, 14, 15},
new double[] {16, 17, 18}})};
double[] actual = MatrixUtils.flatten(m1);
double[] expected = new double[18];
for (int i = 0; i < expected.length; i++) {
expected[i] = i + 1;
}
Assert.assertArrayEquals(expected, actual, 0.d);
}
@Test
public void testUnflatten2D() {
double[] data = new double[24];
for (int i = 0; i < data.length; i++) {
data[i] = i + 1;
}
RealMatrix[] actual = MatrixUtils.unflatten(data, 2, 3, 4);
RealMatrix[] expected = new RealMatrix[] {
new Array2DRowRealMatrix(new double[][] {new double[] {1, 2, 3},
new double[] {4, 5, 6}}),
new Array2DRowRealMatrix(new double[][] {new double[] {7, 8, 9},
new double[] {10, 11, 12}}),
new Array2DRowRealMatrix(new double[][] {new double[] {13, 14, 15},
new double[] {16, 17, 18}}),
new Array2DRowRealMatrix(new double[][] {new double[] {19, 20, 21},
new double[] {22, 23, 24}})};
Assert.assertArrayEquals(expected, actual);
}
@Test
public void testPower1() {
RealMatrix A = new Array2DRowRealMatrix(new double[][] {new double[] {1, 2, 3},
new double[] {4, 5, 6}});
double[] x = new double[3];
x[0] = Math.random();
x[1] = Math.random();
x[2] = Math.random();
double[] u = new double[2];
double[] v = new double[3];
double s = MatrixUtils.power1(A, x, 2, u, v);
SingularValueDecomposition svdA = new SingularValueDecomposition(A);
Assert.assertArrayEquals(svdA.getU().getColumn(0), u, 0.001d);
Assert.assertArrayEquals(svdA.getV().getColumn(0), v, 0.001d);
Assert.assertEquals(svdA.getSingularValues()[0], s, 0.001d);
}
@Test
public void testLanczosTridiagonalization() {
// Symmetric matrix
RealMatrix C = new Array2DRowRealMatrix(new double[][] {new double[] {1, 2, 3, 4},
new double[] {2, 1, 4, 3}, new double[] {3, 4, 1, 2}, new double[] {4, 3, 2, 1}});
// naive initial vector
double[] a = new double[] {1, 1, 1, 1};
RealMatrix actual = new Array2DRowRealMatrix(new double[4][4]);
MatrixUtils.lanczosTridiagonalization(C, a, actual);
RealMatrix expected = new Array2DRowRealMatrix(new double[][] {new double[] {40, 60, 0, 0},
new double[] {60, 10, 120, 0}, new double[] {0, 120, 10, 120},
new double[] {0, 0, 120, 10}});
Assert.assertEquals(expected, actual);
}
@Test
public void testTridiagonalEigen() {
// Tridiagonal Matrix
RealMatrix T = new Array2DRowRealMatrix(new double[][] {new double[] {40, 60, 0, 0},
new double[] {60, 10, 120, 0}, new double[] {0, 120, 10, 120},
new double[] {0, 0, 120, 10}});
double[] eigvals = new double[4];
RealMatrix eigvecs = new Array2DRowRealMatrix(new double[4][4]);
MatrixUtils.tridiagonalEigen(T, 2, eigvals, eigvecs);
RealMatrix actual = eigvecs.multiply(eigvecs.transpose());
RealMatrix expected = new Array2DRowRealMatrix(new double[4][4]);
for (int i = 0; i < 4; i++) {
expected.setEntry(i, i, 1);
}
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
Assert.assertEquals(expected.getEntry(i, j), actual.getEntry(i, j), 0.001d);
}
}
}
}