/*
* 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.impls.matrix;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.ml.math.ExternalizeTest;
import org.apache.ignite.ml.math.IdentityValueMapper;
import org.apache.ignite.ml.math.Matrix;
import org.apache.ignite.ml.math.MatrixKeyMapper;
import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
import org.apache.ignite.ml.math.impls.MathTestConstants;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.apache.ignite.testframework.junits.common.GridCommonTest;
/**
* Tests for {@link CacheMatrix}.
*/
@GridCommonTest(group = "Distributed Models")
public class CacheMatrixTest extends GridCommonAbstractTest {
/** Number of nodes in grid */
private static final int NODE_COUNT = 3;
/** Cache name. */
private static final String CACHE_NAME = "test-cache";
/** */
private static final String UNEXPECTED_ATTRIBUTE_VALUE = "Unexpected attribute value.";
/** Grid instance. */
private Ignite ignite;
/** Matrix rows */
private final int rows = MathTestConstants.STORAGE_SIZE;
/** Matrix cols */
private final int cols = MathTestConstants.STORAGE_SIZE;
/**
* Default constructor.
*/
public CacheMatrixTest() {
super(false);
}
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
for (int i = 1; i <= NODE_COUNT; i++)
startGrid(i);
}
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
stopAllGrids();
}
/**
* {@inheritDoc}
*/
@Override protected void beforeTest() throws Exception {
ignite = grid(NODE_COUNT);
ignite.configuration().setPeerClassLoadingEnabled(true);
}
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
ignite.destroyCache(CACHE_NAME);
}
/** */
public void testGetSet() throws Exception {
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
double v = Math.random();
cacheMatrix.set(i, j, v);
assert Double.compare(v, cacheMatrix.get(i, j)) == 0;
assert Double.compare(v, cache.get(keyMapper.apply(i, j))) == 0;
}
}
}
/** */
public void testCopy() throws Exception {
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
fillMatrix(cacheMatrix);
try {
cacheMatrix.copy();
fail("UnsupportedOperationException expected");
}
catch (UnsupportedOperationException e) {
// No-op.
}
}
/** */
public void testLike() throws Exception {
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
try {
cacheMatrix.like(rows, cols);
fail("UnsupportedOperationException expected");
}
catch (UnsupportedOperationException e) {
// No-op.
}
}
/** */
public void testLikeVector() throws Exception {
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
try {
cacheMatrix.likeVector(cols);
fail("UnsupportedOperationException expected");
}
catch (UnsupportedOperationException e) {
// No-op.
}
}
/** */
public void testPlus() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
double plusVal = 2;
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
initMatrix(cacheMatrix);
cacheMatrix.plus(plusVal);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
assertEquals(plusVal, cacheMatrix.get(i, j));
}
/** */
public void testDivide() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
double initVal = 1;
double divVal = 2;
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
initMatrix(cacheMatrix);
cacheMatrix.assign(initVal);
cacheMatrix.divide(divVal);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
assertTrue(Double.compare(cacheMatrix.get(i, j), initVal / divVal) == 0);
}
/** */
public void testTimes() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
double initVal = 1;
double timVal = 2;
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
initMatrix(cacheMatrix);
cacheMatrix.assign(initVal);
cacheMatrix.times(timVal);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
assertTrue(Double.compare(cacheMatrix.get(i, j), initVal * timVal) == 0);
}
/** */
public void testSum() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
double sum;
initMatrix(cacheMatrix);
sum = cacheMatrix.sum();
assertTrue(Double.compare(sum, 0d) == 0);
cacheMatrix.assign(1d);
sum = cacheMatrix.sum();
assertTrue(Double.compare(sum, rows * cols) == 0);
}
/** */
public void testAssignSingleValue() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
double initVal = 1;
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
initMatrix(cacheMatrix);
cacheMatrix.assign(initVal);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
assertEquals(initVal, cacheMatrix.get(i, j));
}
/** */
public void testAssignArray() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
double[][] initVal = new double[rows][cols];
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
initVal[i][j] = Math.random();
cacheMatrix.assign(initVal);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
assertEquals(initVal[i][j], cacheMatrix.get(i, j));
}
/** */
public void testAttributes() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
assertFalse(UNEXPECTED_ATTRIBUTE_VALUE, cacheMatrix.isSequentialAccess());
assertFalse(UNEXPECTED_ATTRIBUTE_VALUE, cacheMatrix.isDense());
assertFalse(UNEXPECTED_ATTRIBUTE_VALUE, cacheMatrix.isArrayBased());
assertTrue(UNEXPECTED_ATTRIBUTE_VALUE, cacheMatrix.isRandomAccess());
assertTrue(UNEXPECTED_ATTRIBUTE_VALUE, cacheMatrix.isDistributed());
}
/** */
public void testExternalization() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
final CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
ExternalizeTest<CacheMatrix<Integer, Double>> externalizeTest = new ExternalizeTest<CacheMatrix<Integer, Double>>() {
/** {@inheritDoc} */
@Override public void externalizeTest() {
super.externalizeTest(cacheMatrix);
}
};
externalizeTest.externalizeTest();
}
/** */
public void testMinMax() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
final CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
cacheMatrix.set(i, j, i * rows + j);
assertEquals(0.0, cacheMatrix.minValue(), 0.0);
assertEquals(rows * cols - 1, cacheMatrix.maxValue(), 0.0);
}
/** */
public void testMap() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
MatrixKeyMapper<Integer> keyMapper = getKeyMapper(rows, cols);
IgniteCache<Integer, Double> cache = getCache();
final CacheMatrix<Integer, Double> cacheMatrix = new CacheMatrix<>(rows, cols, cache, keyMapper, new IdentityValueMapper());
initMatrix(cacheMatrix);
cacheMatrix.map(value -> value + 10);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
assertEquals(10.0, cacheMatrix.getX(i, j), 0.0);
}
/** */
private IgniteCache<Integer, Double> getCache() {
assert ignite != null;
CacheConfiguration cfg = new CacheConfiguration();
cfg.setName(CACHE_NAME);
IgniteCache<Integer, Double> cache = ignite.getOrCreateCache(CACHE_NAME);
assert cache != null;
return cache;
}
/** */
private MatrixKeyMapper<Integer> getKeyMapper(final int rows, final int cols) {
return new MatrixKeyMapperForTests(rows, cols);
}
/**
* Init the given matrix by random values.
*/
private void fillMatrix(Matrix m) {
for (int i = 0; i < m.rowSize(); i++)
for (int j = 0; j < m.columnSize(); j++)
m.set(i, j, Math.random());
}
/**
* Init the given matrix by zeros.
*/
private void initMatrix(Matrix m) {
for (int i = 0; i < m.rowSize(); i++)
for (int j = 0; j < m.columnSize(); j++)
m.set(i, j, 0d);
}
}