/*
* 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.vector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.stream.IntStream;
import junit.framework.TestCase;
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.IdentityValueMapper;
import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.VectorKeyMapper;
import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
import org.apache.ignite.ml.math.functions.Functions;
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 CacheVector}.
*/
@GridCommonTest(group = "Distributed Models")
public class CacheVectorTest extends GridCommonAbstractTest {
/** Number of nodes in grid */
private static final int NODE_COUNT = 3;
/** Cache name. */
private static final String CACHE_NAME = "test-cache";
/** Cache size. */
private static final int size = MathTestConstants.STORAGE_SIZE;
/** Grid instance. */
private Ignite ignite;
/** Default key mapper. */
private VectorKeyMapper<Integer> keyMapper = new TestKeyMapper();
/**
* Default constructor.
*/
public CacheVectorTest() {
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 {
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
for (int i = 0; i < size; i++) {
double random = Math.random();
cacheVector.set(i, random);
assertEquals("Unexpected value.", random, cacheVector.get(i), 0d);
}
}
/** */
public void testMap() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
cacheVector.map(value -> 110d);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), 110d, 0d);
}
/** */
public void testMapBiFunc() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
cacheVector.map(Functions.PLUS, 1d);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), 1d, 0d);
}
/** */
public void testSum() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
assertEquals("Unexpected value.", cacheVector.sum(), 0d, 0d);
cacheVector.assign(1d);
assertEquals("Unexpected value.", cacheVector.sum(), size, 0d);
}
/** */
public void testSumNegative() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
try {
double d = cacheVector.sum();
fail();
}
catch (NullPointerException e) {
// No-op.
}
}
/** */
public void testAssign() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
cacheVector.assign(1d);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), 1d, 0d);
}
/** */
public void testAssignRange() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
cacheVector.assign(IntStream.range(0, size).asDoubleStream().toArray());
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), i, 0d);
}
/** */
public void testAssignVector() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
Vector testVec = new DenseLocalOnHeapVector(IntStream.range(0, size).asDoubleStream().toArray());
cacheVector.assign(testVec);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), testVec.get(i), 0d);
}
/** */
public void testAssignFunc() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
cacheVector.assign(idx -> idx);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), i, 0d);
}
/** */
public void testPlus() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
cacheVector.plus(1d);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), 1d, 0d);
}
/** */
public void testPlusVec() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
Vector testVec = new DenseLocalOnHeapVector(IntStream.range(0, size).asDoubleStream().toArray());
try {
cacheVector.plus(testVec);
TestCase.fail();
}
catch (UnsupportedOperationException ignored) {
}
}
/** */
public void testDivide() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
final int size = MathTestConstants.STORAGE_SIZE;
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
cacheVector.assign(1d);
cacheVector.divide(2d);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), 1d / 2d, 0d);
}
/** */
public void testTimes() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
final int size = MathTestConstants.STORAGE_SIZE;
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
initVector(cacheVector);
cacheVector.assign(1d);
cacheVector.times(2d);
for (int i = 0; i < size; i++)
assertEquals("Unexpected value.", cacheVector.get(i), 2d, 0d);
}
/** */
public void testTimesVector() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
cacheVector.assign(1d);
Vector testVec = new DenseLocalOnHeapVector(IntStream.range(0, size).asDoubleStream().toArray());
try {
cacheVector.times(testVec);
TestCase.fail();
}
catch (UnsupportedOperationException ignored) {
}
}
/** */
public void testMin() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
Vector testVec = new DenseLocalOnHeapVector(IntStream.range(0, size).asDoubleStream().toArray());
cacheVector.assign(testVec);
assertEquals("Unexpected value.", cacheVector.minValue(), 0d, 0d);
}
/** */
public void testMax() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
Vector testVec = new DenseLocalOnHeapVector(IntStream.range(0, size).asDoubleStream().toArray());
cacheVector.assign(testVec);
assertEquals("Unexpected value.", cacheVector.maxValue(), testVec.get(size - 1), 0d);
}
/** */
public void testLike() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
try {
cacheVector.like(size);
TestCase.fail("Unsupported case");
}
catch (UnsupportedOperationException ignored) {
}
}
/** */
public void testLikeMatrix() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
try {
cacheVector.likeMatrix(size, size);
TestCase.fail("Unsupported case");
}
catch (UnsupportedOperationException ignored) {
}
}
/** */
public void testCopy() {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
try {
cacheVector.copy();
TestCase.fail("Unsupported case");
}
catch (UnsupportedOperationException ignored) {
}
}
/** */
public void testExternalize() throws IOException, ClassNotFoundException {
IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
IdentityValueMapper valMapper = new IdentityValueMapper();
CacheVector<Integer, Double> cacheVector = new CacheVector<>(size, getCache(), keyMapper, valMapper);
cacheVector.set(1, 1.0);
ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream);
objOutputStream.writeObject(cacheVector);
ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray());
ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream);
CacheVector objRestored = (CacheVector)objInputStream.readObject();
assertTrue(MathTestConstants.VAL_NOT_EQUALS, cacheVector.equals(objRestored));
assertEquals(MathTestConstants.VAL_NOT_EQUALS, objRestored.get(1), 1.0, 0.0);
}
/** */
private void initVector(CacheVector cacheVector) {
for (int i = 0; i < cacheVector.size(); i++)
cacheVector.set(i, 0d);
}
/** */
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 static class TestKeyMapper implements VectorKeyMapper<Integer> {
/** {@inheritDoc} */
@Override public Integer apply(int i) {
return i;
}
/** {@inheritDoc} */
@Override public boolean isValid(Integer i) {
return i < size;
}
}
}