/**
* 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.mahout.math;
import org.apache.mahout.common.RandomUtils;
import org.apache.mahout.math.function.Functions;
import org.apache.mahout.math.jet.random.Gamma;
import org.junit.Assert;
import org.junit.Test;
import java.util.Random;
public final class TestSparseRowMatrix extends MatrixTest {
@Override
public Matrix matrixFactory(double[][] values) {
Matrix matrix = new SparseRowMatrix(values.length, values[0].length);
for (int row = 0; row < matrix.rowSize(); row++) {
for (int col = 0; col < matrix.columnSize(); col++) {
matrix.setQuick(row, col, values[row][col]);
}
}
return matrix;
}
@Test(timeout=50000)
public void testTimesSparseEfficiency() {
Random raw = RandomUtils.getRandom();
Gamma gen = new Gamma(0.1, 0.1, raw);
// build two large sequential sparse matrices and multiply them
Matrix x = new SparseRowMatrix(1000, 2000, false);
for (int i = 0; i < 1000; i++) {
int[] values = new int[1000];
for (int k = 0; k < 1000; k++) {
int j = (int) Math.min(1000, gen.nextDouble());
values[j]++;
}
for (int j = 0; j < 1000; j++) {
if (values[j] > 0) {
x.set(i, j, values[j]);
}
}
}
Matrix y = new SparseRowMatrix(2000, 1000, false);
for (int i = 0; i < 2000; i++) {
int[] values = new int[1000];
for (int k = 0; k < 1000; k++) {
int j = (int) Math.min(1000, gen.nextDouble());
values[j]++;
}
for (int j = 0; j < 1000; j++) {
if (values[j] > 0) {
y.set(i, j, values[j]);
}
}
}
long t0 = System.nanoTime();
Matrix z = x.times(y);
double elapsedTime = (System.nanoTime() - t0) * 1e-6;
System.out.printf("done in %.1f ms\n", elapsedTime);
for (int k = 0; k < 1000; k++) {
int i = (int) (-10 * Math.log(raw.nextDouble()));
int j = (int) (-10 * Math.log(raw.nextDouble()));
Assert.assertEquals(x.viewRow(i).dot(y.viewColumn(j)), z.get(i, j), 1e-12);
}
}
@Test(timeout=50000)
public void testTimesDenseEfficiency() {
Random raw = RandomUtils.getRandom();
Gamma gen = new Gamma(0.1, 0.1, raw);
// build a sequential sparse matrix and a dense matrix and multiply them
Matrix x = new SparseRowMatrix(1000, 2000, false);
for (int i = 0; i < 1000; i++) {
int[] values = new int[1000];
for (int k = 0; k < 1000; k++) {
int j = (int) Math.min(1000, gen.nextDouble());
values[j]++;
}
for (int j = 0; j < 1000; j++) {
if (values[j] > 0) {
x.set(i, j, values[j]);
}
}
}
Matrix y = new DenseMatrix(2000, 20);
for (int i = 0; i < 2000; i++) {
for (int j = 0; j < 20; j++) {
y.set(i, j, raw.nextDouble());
}
}
long t0 = System.nanoTime();
Matrix z = x.times(y);
double elapsedTime = (System.nanoTime() - t0) * 1e-6;
System.out.printf("done in %.1f ms\n", elapsedTime);
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 20; j++) {
Assert.assertEquals(x.viewRow(i).dot(y.viewColumn(j)), z.get(i, j), 1e-12);
}
}
}
@Test(timeout=50000)
public void testTimesOtherSparseEfficiency() {
Random raw = RandomUtils.getRandom();
Gamma gen = new Gamma(0.1, 0.1, raw);
// build a sequential sparse matrix and a diagonal matrix and multiply them
Matrix x = new SparseRowMatrix(1000, 2000, false);
for (int i = 0; i < 1000; i++) {
int[] values = new int[1000];
for (int k = 0; k < 1000; k++) {
int j = (int) Math.min(1000, gen.nextDouble());
values[j]++;
}
for (int j = 0; j < 1000; j++) {
if (values[j] > 0) {
x.set(i, j, values[j]);
}
}
}
Vector d = new DenseVector(2000).assign(Functions.random());
Matrix y = new DiagonalMatrix(d);
long t0 = System.nanoTime();
Matrix z = x.times(y);
double elapsedTime = (System.nanoTime() - t0) * 1e-6;
System.out.printf("done in %.1f ms\n", elapsedTime);
for (MatrixSlice row : z) {
for (Vector.Element element : row.nonZeroes()) {
assertEquals(x.get(row.index(), element.index()) * d.get(element.index()), element.get(), 1e-12);
}
}
}
@Test(timeout=50000)
public void testTimesCorrect() {
Random raw = RandomUtils.getRandom();
// build two large sequential sparse matrices and multiply them
Matrix x = new SparseRowMatrix(100, 2000, false)
.assign(Functions.random());
Matrix y = new SparseRowMatrix(2000, 100, false)
.assign(Functions.random());
Matrix xd = new DenseMatrix(100, 2000).assign(x);
Matrix yd = new DenseMatrix(2000, 100).assign(y);
assertEquals(0, xd.times(yd).minus(x.times(y)).aggregate(Functions.PLUS, Functions.ABS), 1e-15);
assertEquals(0, x.times(yd).minus(x.times(y)).aggregate(Functions.PLUS, Functions.ABS), 1e-15);
assertEquals(0, xd.times(y).minus(x.times(y)).aggregate(Functions.PLUS, Functions.ABS), 1e-15);
}
}