/*
* 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.util.Arrays;
import java.util.stream.StreamSupport;
import org.apache.ignite.ml.math.Matrix;
import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.VectorStorage;
import org.apache.ignite.ml.math.exceptions.IndexException;
import org.apache.ignite.ml.math.functions.Functions;
import org.apache.ignite.ml.math.impls.MathTestConstants;
import org.apache.ignite.ml.math.impls.storage.vector.ArrayVectorStorage;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* Unit test for {@link AbstractVector}.
*/
public class AbstractVectorTest {
/** */
private AbstractVector testVector;
/** */
@Before
public void setUp() {
testVector = getAbstractVector();
}
/** */
@Test
public void setStorage() {
testVector.setStorage(createStorage());
assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE);
}
/** */
@Test
public void size() {
testVector.setStorage(createStorage());
assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE);
testVector.setStorage(new ArrayVectorStorage(MathTestConstants.STORAGE_SIZE + MathTestConstants.STORAGE_SIZE));
assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE + MathTestConstants.STORAGE_SIZE);
testVector = getAbstractVector(createStorage());
assertTrue(testVector.size() == MathTestConstants.STORAGE_SIZE);
}
/** */
@Test
public void getPositive() {
testVector = getAbstractVector(createStorage());
for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
assertNotNull(MathTestConstants.NULL_VALUES, testVector.get(i));
}
/** */
@Test(expected = NullPointerException.class)
public void getNegative0() {
testVector.get(0);
}
/** */
@Test(expected = IndexException.class)
public void getNegative1() {
testVector.setStorage(createStorage());
testVector.get(-1);
}
/** */
@Test(expected = IndexException.class)
public void getNegative2() {
testVector.setStorage(createStorage());
testVector.get(testVector.size() + 1);
}
/** */
@Test(expected = NullPointerException.class)
public void getXNegative0() {
testVector.getX(0);
}
/** */
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void getXNegative1() {
testVector.setStorage(createStorage());
testVector.getX(-1);
}
/** */
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void getXNegative2() {
testVector.setStorage(createStorage());
testVector.getX(MathTestConstants.STORAGE_SIZE + 1);
}
/** */
@Test
public void set() {
double[] data = initVector();
for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
testVector.set(i, Math.exp(data[i]));
for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.get(i), Math.exp(data[i]), MathTestConstants.NIL_DELTA);
}
/** */
@Test(expected = IndexException.class)
public void setNegative0() {
testVector.set(-1, -1);
}
/** */
@Test(expected = IndexException.class)
public void setNegative1() {
initVector();
testVector.set(-1, -1);
}
/** */
@Test(expected = IndexException.class)
public void setNegative2() {
initVector();
testVector.set(MathTestConstants.STORAGE_SIZE + 1, -1);
}
/** */
@Test(expected = IndexOutOfBoundsException.class)
public void setXNegative0() {
initVector();
testVector.setX(-1, -1);
}
/** */
@Test(expected = IndexOutOfBoundsException.class)
public void setXNegative1() {
initVector();
testVector.setX(MathTestConstants.STORAGE_SIZE + 1, -1);
}
/** */
@Test(expected = NullPointerException.class)
public void setXNegative2() {
testVector.setX(-1, -1);
}
/** */
@Test
public void isZero() {
assertTrue(MathTestConstants.UNEXPECTED_VAL, testVector.isZero(0d));
assertFalse(MathTestConstants.UNEXPECTED_VAL, testVector.isZero(1d));
}
/** */
@Test
public void guid() {
assertNotNull(MathTestConstants.NULL_GUID, testVector.guid());
assertEquals(MathTestConstants.UNEXPECTED_GUID_VAL, testVector.guid(), testVector.guid());
assertFalse(MathTestConstants.EMPTY_GUID, testVector.guid().toString().isEmpty());
testVector = getAbstractVector(createStorage());
assertNotNull(MathTestConstants.NULL_GUID, testVector.guid());
assertEquals(MathTestConstants.UNEXPECTED_GUID_VAL, testVector.guid(), testVector.guid());
assertFalse(MathTestConstants.EMPTY_GUID, testVector.guid().toString().isEmpty());
}
/** */
@Test
public void equalsTest() {
VectorStorage storage = createStorage();
AbstractVector testVector1 = getAbstractVector();
testVector1.setStorage(storage);
AbstractVector testVector2 = getAbstractVector();
assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector, testVector);
testVector2.setStorage(storage);
assertTrue(MathTestConstants.VAL_NOT_EQUALS, testVector1.equals(testVector2));
assertFalse(MathTestConstants.VALUES_SHOULD_BE_NOT_EQUALS, testVector1.equals(testVector));
}
/** */
@Test(expected = NullPointerException.class)
public void all() {
assertNotNull(MathTestConstants.NULL_VAL, testVector.all());
assertNotNull(MathTestConstants.NULL_VAL, getAbstractVector(createStorage()).all());
getAbstractVector().all().iterator().next();
}
/** */
@Test
public void nonZeroElements() {
VectorStorage storage = createStorage();
double[] data = storage.data();
testVector = getAbstractVector(storage);
assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.nonZeroElements(), Arrays.stream(data).filter(x -> x != 0d).count());
addNilValues(data);
assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.nonZeroElements(), Arrays.stream(data).filter(x -> x != 0d).count());
}
/** */
@Test
public void foldMapWithSecondVector() {
double[] data0 = initVector();
VectorStorage storage1 = createStorage();
double[] data1 = storage1.data().clone();
AbstractVector testVector1 = getAbstractVector(storage1);
StringBuilder testVal = new StringBuilder();
for (int i = 0; i < data0.length; i++)
testVal.append(data0[i] + data1[i]);
assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.foldMap(testVector1, (string, xi) -> string.concat(xi.toString()), Functions.PLUS, ""), testVal.toString());
}
/** */
@Test
public void nonZeroes() {
assertNotNull(MathTestConstants.NULL_VAL, testVector.nonZeroes());
double[] data = initVector();
assertNotNull(MathTestConstants.NULL_VAL, testVector.nonZeroes());
Assert.assertEquals(MathTestConstants.VAL_NOT_EQUALS, StreamSupport.stream(testVector.nonZeroes().spliterator(), false).count(), Arrays.stream(data).filter(x -> x != 0d).count());
addNilValues(data);
Assert.assertEquals(MathTestConstants.VAL_NOT_EQUALS, StreamSupport.stream(testVector.nonZeroes().spliterator(), false).count(), Arrays.stream(data).filter(x -> x != 0d).count());
}
/** */
@Test(expected = NullPointerException.class)
public void nonZeroesEmpty() {
testVector.nonZeroes().iterator().next();
}
/** */
@Test(expected = NullPointerException.class)
public void assign() {
testVector.assign(MathTestConstants.TEST_VAL);
}
/** */
@Test(expected = NullPointerException.class)
public void assignArr() {
testVector.assign(new double[1]);
}
/** */
@Test(expected = NullPointerException.class)
public void assignArrEmpty() {
testVector.assign(new double[0]);
}
/** */
@Test(expected = NullPointerException.class)
public void dotNegative() {
testVector.dot(getAbstractVector(createEmptyStorage()));
}
/** */
@Test
public void dotSelf() {
double[] data = initVector();
assertEquals(MathTestConstants.VAL_NOT_EQUALS, testVector.dotSelf(), Arrays.stream(data).reduce(0, (x, y) -> x + y * y), MathTestConstants.NIL_DELTA);
}
/** */
@Test
public void getStorage() {
assertNotNull(MathTestConstants.NULL_VAL, getAbstractVector(createEmptyStorage()));
assertNotNull(MathTestConstants.NULL_VAL, getAbstractVector(createStorage()));
testVector.setStorage(createStorage());
assertNotNull(MathTestConstants.NULL_VAL, testVector.getStorage());
}
/** */
@Test
public void getElement() {
double[] data = initVector();
for (int i = 0; i < data.length; i++) {
assertNotNull(MathTestConstants.NULL_VAL, testVector.getElement(i));
assertEquals(MathTestConstants.UNEXPECTED_VAL, testVector.getElement(i).get(), data[i], MathTestConstants.NIL_DELTA);
testVector.getElement(i).set(++data[i]);
assertEquals(MathTestConstants.UNEXPECTED_VAL, testVector.getElement(i).get(), data[i], MathTestConstants.NIL_DELTA);
}
}
/**
* Create {@link AbstractVector} with storage for tests.
*
* @param storage {@link VectorStorage}
* @return AbstractVector.
*/
@SuppressWarnings("ClassWithoutNoArgConstructor")
private AbstractVector getAbstractVector(VectorStorage storage) {
return new AbstractVector(storage) { // TODO: find out how to fix warning about missing constructor
/** {@inheritDoc} */
@Override public boolean isDense() {
return false;
}
/** {@inheritDoc} */
@Override public boolean isSequentialAccess() {
return false;
}
/** {@inheritDoc} */
@Override public Matrix likeMatrix(int rows, int cols) {
return null;
}
/** {@inheritDoc} */
@Override public Vector copy() {
return getAbstractVector(this.getStorage());
}
/** {@inheritDoc} */
@Override public Vector like(int crd) {
return null;
}
/** {@inheritDoc} */
@Override public Vector normalize() {
return null;
}
/** {@inheritDoc} */
@Override public Vector normalize(double power) {
return null;
}
/** {@inheritDoc} */
@Override public Vector logNormalize() {
return null;
}
/** {@inheritDoc} */
@Override public Vector logNormalize(double power) {
return null;
}
/** {@inheritDoc} */
@Override public Vector viewPart(int off, int len) {
return null;
}
/** {@inheritDoc} */
@Override public boolean isRandomAccess() {
return true;
}
/** {@inheritDoc} */
@Override public boolean isDistributed() {
return false;
}
};
}
/**
* Create empty {@link AbstractVector} for tests.
*
* @return AbstractVector.
*/
private AbstractVector getAbstractVector() {
return new AbstractVector() { // TODO: find out how to fix warning about missing constructor
/** {@inheritDoc} */
@Override public boolean isDense() {
return false;
}
/** {@inheritDoc} */
@Override public Matrix likeMatrix(int rows, int cols) {
return null;
}
/** {@inheritDoc} */
@Override public boolean isSequentialAccess() {
return false;
}
/** {@inheritDoc} */
@Override public Vector copy() {
return getAbstractVector(this.getStorage());
}
/** {@inheritDoc} */
@Override public Vector like(int crd) {
return null;
}
/** {@inheritDoc} */
@Override public Vector normalize() {
return null;
}
/** {@inheritDoc} */
@Override public Vector normalize(double power) {
return null;
}
/** {@inheritDoc} */
@Override public Vector logNormalize() {
return null;
}
/** {@inheritDoc} */
@Override public Vector logNormalize(double power) {
return null;
}
/** {@inheritDoc} */
@Override public Vector viewPart(int off, int len) {
return null;
}
/** {@inheritDoc} */
@Override public boolean isRandomAccess() {
return true;
}
/** {@inheritDoc} */
@Override public boolean isDistributed() {
return false;
}
};
}
/**
* Create {@link VectorStorage} for tests.
*
* @return VectorStorage
*/
private VectorStorage createEmptyStorage() {
return new ArrayVectorStorage(MathTestConstants.STORAGE_SIZE);
}
/**
* Create filled {@link VectorStorage} for tests.
*
* @return VectorStorage.
*/
private VectorStorage createStorage() {
ArrayVectorStorage storage = new ArrayVectorStorage(MathTestConstants.STORAGE_SIZE);
for (int i = 0; i < MathTestConstants.STORAGE_SIZE; i++)
storage.set(i, Math.random());
return storage;
}
/**
* Init vector and return initialized values.
*
* @return Initial values.
*/
private double[] initVector() {
VectorStorage storage = createStorage();
double[] data = storage.data().clone();
testVector = getAbstractVector(storage);
return data;
}
/**
* Add some zeroes to vector elements.
*/
private void addNilValues() {
testVector.set(10, 0);
testVector.set(50, 0);
}
/**
* Add some zeroes to vector elements. Also set zeroes to the same elements in reference array data
*/
private void addNilValues(double[] testRef) {
addNilValues();
testRef[10] = 0;
testRef[50] = 0;
}
}