You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/04/19 08:15:46 UTC
[03/43] ignite git commit: IGNITE-5000 Rename Ignite Math module to
Ignite ML module added missed licenses renamed packages fixed wrong ml
profile activation
http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorIterableTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorIterableTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorIterableTest.java
new file mode 100644
index 0000000..16c2571
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorIterableTest.java
@@ -0,0 +1,376 @@
+/*
+ * 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.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.function.BiConsumer;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.impls.MathTestConstants;
+import org.junit.Test;
+
+import static java.util.Spliterator.ORDERED;
+import static java.util.Spliterator.SIZED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/** */
+public class VectorIterableTest {
+ /** */
+ @Test
+ public void allTest() {
+ consumeSampleVectors(
+ (v, desc) -> {
+ int expIdx = 0;
+
+ for (Vector.Element e : v.all()) {
+ int actualIdx = e.index();
+
+ assertEquals("Unexpected index for " + desc,
+ expIdx, actualIdx);
+
+ expIdx++;
+ }
+
+ assertEquals("Unexpected amount of elements for " + desc,
+ expIdx, v.size());
+ }
+ );
+ }
+
+ /** */
+ @Test
+ public void allTestBound() {
+ consumeSampleVectors(
+ (v, desc) -> iteratorTestBound(v.all().iterator(), desc)
+ );
+ }
+
+ /** */
+ @Test
+ public void nonZeroesTestBasic() {
+ final int size = 5;
+
+ final double[] nonZeroesOddData = new double[size], nonZeroesEvenData = new double[size];
+
+ for (int idx = 0; idx < size; idx++) {
+ final boolean odd = (idx & 1) == 1;
+
+ nonZeroesOddData[idx] = odd ? 1 : 0;
+
+ nonZeroesEvenData[idx] = odd ? 0 : 1;
+ }
+
+ assertTrue("Arrays failed to initialize.",
+ !isZero(nonZeroesEvenData[0])
+ && isZero(nonZeroesEvenData[1])
+ && isZero(nonZeroesOddData[0])
+ && !isZero(nonZeroesOddData[1]));
+
+ final Vector nonZeroesEvenVec = new DenseLocalOnHeapVector(nonZeroesEvenData),
+ nonZeroesOddVec = new DenseLocalOnHeapVector(nonZeroesOddData);
+
+ assertTrue("Vectors failed to initialize.",
+ !isZero(nonZeroesEvenVec.getElement(0).get())
+ && isZero(nonZeroesEvenVec.getElement(1).get())
+ && isZero(nonZeroesOddVec.getElement(0).get())
+ && !isZero(nonZeroesOddVec.getElement(1).get()));
+
+ assertTrue("Iterator(s) failed to start.",
+ nonZeroesEvenVec.nonZeroes().iterator().next() != null
+ && nonZeroesOddVec.nonZeroes().iterator().next() != null);
+
+ int nonZeroesActual = 0;
+
+ for (Vector.Element e : nonZeroesEvenVec.nonZeroes()) {
+ final int idx = e.index();
+
+ final boolean odd = (idx & 1) == 1;
+
+ final double val = e.get();
+
+ assertTrue("Not an even index " + idx + ", for value " + val, !odd);
+
+ assertTrue("Zero value " + val + " at even index " + idx, !isZero(val));
+
+ nonZeroesActual++;
+ }
+
+ final int nonZeroesOddExp = (size + 1) / 2;
+
+ assertEquals("Unexpected num of iterated odd non-zeroes.", nonZeroesOddExp, nonZeroesActual);
+
+ assertEquals("Unexpected nonZeroElements of odd.", nonZeroesOddExp, nonZeroesEvenVec.nonZeroElements());
+
+ nonZeroesActual = 0;
+
+ for (Vector.Element e : nonZeroesOddVec.nonZeroes()) {
+ final int idx = e.index();
+
+ final boolean odd = (idx & 1) == 1;
+
+ final double val = e.get();
+
+ assertTrue("Not an odd index " + idx + ", for value " + val, odd);
+
+ assertTrue("Zero value " + val + " at even index " + idx, !isZero(val));
+
+ nonZeroesActual++;
+ }
+
+ final int nonZeroesEvenExp = size / 2;
+
+ assertEquals("Unexpected num of iterated even non-zeroes", nonZeroesEvenExp, nonZeroesActual);
+
+ assertEquals("Unexpected nonZeroElements of even", nonZeroesEvenExp, nonZeroesOddVec.nonZeroElements());
+ }
+
+ /** */
+ @Test
+ public void nonZeroesTest() {
+ // todo make RandomVector constructor that accepts a function and use it here
+ // in order to *reliably* test non-zeroes in there
+ consumeSampleVectors(
+ (v, desc) -> consumeSampleVectorsWithZeroes(v, (vec, numZeroes)
+ -> {
+ int numZeroesActual = vec.size();
+
+ for (Vector.Element e : vec.nonZeroes()) {
+ numZeroesActual--;
+
+ assertTrue("Unexpected zero at " + desc + ", index " + e.index(), !isZero(e.get()));
+ }
+
+ assertEquals("Unexpected num zeroes at " + desc, (int)numZeroes, numZeroesActual);
+ }));
+ }
+
+ /** */
+ @Test
+ public void nonZeroesTestBound() {
+ consumeSampleVectors(
+ (v, desc) -> consumeSampleVectorsWithZeroes(v, (vec, numZeroes)
+ -> iteratorTestBound(vec.nonZeroes().iterator(), desc)));
+ }
+
+ /** */
+ @Test
+ public void nonZeroElementsTest() {
+ consumeSampleVectors(
+ (v, desc) -> consumeSampleVectorsWithZeroes(v, (vec, numZeroes)
+ -> assertEquals("Unexpected num zeroes at " + desc,
+ (int)numZeroes, vec.size() - vec.nonZeroElements())));
+ }
+
+ /** */
+ @Test
+ public void allSpliteratorTest() {
+ consumeSampleVectors(
+ (v, desc) -> {
+ final String desc1 = " " + desc;
+
+ Spliterator<Double> spliterator = v.allSpliterator();
+
+ assertNotNull(MathTestConstants.NULL_VAL + desc1, spliterator);
+
+ assertNull(MathTestConstants.NOT_NULL_VAL + desc1, spliterator.trySplit());
+
+ assertTrue(MathTestConstants.UNEXPECTED_VAL + desc1, spliterator.hasCharacteristics(ORDERED | SIZED));
+
+ if (!readOnly(v))
+ fillWithNonZeroes(v);
+
+ spliterator = v.allSpliterator();
+
+ assertNotNull(MathTestConstants.NULL_VAL + desc1, spliterator);
+
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS + desc1, spliterator.estimateSize(), v.size());
+
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS + desc1, spliterator.getExactSizeIfKnown(), v.size());
+
+ assertTrue(MathTestConstants.UNEXPECTED_VAL + desc1, spliterator.hasCharacteristics(ORDERED | SIZED));
+
+ Spliterator<Double> secondHalf = spliterator.trySplit();
+
+ assertNull(MathTestConstants.NOT_NULL_VAL + desc1, secondHalf);
+
+ spliterator.tryAdvance(x -> {
+ });
+ }
+ );
+ }
+
+ /** */
+ @Test
+ public void nonZeroSpliteratorTest() {
+ consumeSampleVectors(
+ (v, desc) -> consumeSampleVectorsWithZeroes(v, (vec, numZeroes)
+ -> {
+ final String desc1 = " Num zeroes " + numZeroes + " " + desc;
+
+ Spliterator<Double> spliterator = vec.nonZeroSpliterator();
+
+ assertNotNull(MathTestConstants.NULL_VAL + desc1, spliterator);
+
+ assertNull(MathTestConstants.NOT_NULL_VAL + desc1, spliterator.trySplit());
+
+ assertTrue(MathTestConstants.UNEXPECTED_VAL + desc1, spliterator.hasCharacteristics(ORDERED | SIZED));
+
+ spliterator = vec.nonZeroSpliterator();
+
+ assertNotNull(MathTestConstants.NULL_VAL + desc1, spliterator);
+
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS + desc1, spliterator.estimateSize(), vec.size() - numZeroes);
+
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS + desc1, spliterator.getExactSizeIfKnown(), vec.size() - numZeroes);
+
+ assertTrue(MathTestConstants.UNEXPECTED_VAL + desc1, spliterator.hasCharacteristics(ORDERED | SIZED));
+
+ Spliterator<Double> secondHalf = spliterator.trySplit();
+
+ assertNull(MathTestConstants.NOT_NULL_VAL + desc1, secondHalf);
+
+ double[] data = new double[vec.size()];
+
+ for (Vector.Element e : vec.all())
+ data[e.index()] = e.get();
+
+ spliterator = vec.nonZeroSpliterator();
+
+ assertNotNull(MathTestConstants.NULL_VAL + desc1, spliterator);
+
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS + desc1, spliterator.estimateSize(),
+ Arrays.stream(data).filter(x -> x != 0d).count());
+
+ assertEquals(MathTestConstants.VAL_NOT_EQUALS + desc1, spliterator.getExactSizeIfKnown(),
+ Arrays.stream(data).filter(x -> x != 0d).count());
+
+ assertTrue(MathTestConstants.UNEXPECTED_VAL + desc1, spliterator.hasCharacteristics(ORDERED | SIZED));
+
+ secondHalf = spliterator.trySplit();
+
+ assertNull(MathTestConstants.NOT_NULL_VAL + desc1, secondHalf);
+
+ if (!spliterator.tryAdvance(x -> {
+ }))
+ fail(MathTestConstants.NO_NEXT_ELEMENT + desc1);
+ }));
+ }
+
+ /** */
+ private void iteratorTestBound(Iterator<Vector.Element> it, String desc) {
+ while (it.hasNext())
+ assertNotNull(it.next());
+
+ boolean expECaught = false;
+
+ try {
+ it.next();
+ }
+ catch (NoSuchElementException e) {
+ expECaught = true;
+ }
+
+ assertTrue("Expected exception missed for " + desc,
+ expECaught);
+ }
+
+ /** */
+ private void consumeSampleVectorsWithZeroes(Vector sample,
+ BiConsumer<Vector, Integer> consumer) {
+ if (readOnly(sample)) {
+ int numZeroes = 0;
+
+ for (Vector.Element e : sample.all())
+ if (isZero(e.get()))
+ numZeroes++;
+
+ consumer.accept(sample, numZeroes);
+
+ return;
+ }
+
+ fillWithNonZeroes(sample);
+
+ consumer.accept(sample, 0);
+
+ final int sampleSize = sample.size();
+
+ if (sampleSize == 0)
+ return;
+
+ for (Vector.Element e : sample.all())
+ e.set(0);
+
+ consumer.accept(sample, sampleSize);
+
+ fillWithNonZeroes(sample);
+
+ for (int testIdx : new int[] {0, sampleSize / 2, sampleSize - 1}) {
+ final Vector.Element e = sample.getElement(testIdx);
+
+ final double backup = e.get();
+
+ e.set(0);
+
+ consumer.accept(sample, 1);
+
+ e.set(backup);
+ }
+
+ if (sampleSize < 3)
+ return;
+
+ sample.getElement(sampleSize / 3).set(0);
+
+ sample.getElement((2 * sampleSize) / 3).set(0);
+
+ consumer.accept(sample, 2);
+ }
+
+ /** */
+ private void fillWithNonZeroes(Vector sample) {
+ int idx = 0;
+
+ for (Vector.Element e : sample.all())
+ e.set(1 + idx++);
+
+ assertEquals("Not all filled with non-zeroes", idx, sample.size());
+ }
+
+ /** */
+ private void consumeSampleVectors(BiConsumer<Vector, String> consumer) {
+ new VectorImplementationsFixtures().consumeSampleVectors(null, consumer);
+ }
+
+ /** */
+ private boolean isZero(double val) {
+ return val == 0.0;
+ }
+
+ /** */
+ private boolean readOnly(Vector v) {
+ return v instanceof RandomVector || v instanceof ConstantVector;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorNormTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorNormTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorNormTest.java
new file mode 100644
index 0000000..4e4f212
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorNormTest.java
@@ -0,0 +1,247 @@
+/*
+ * 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.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import org.apache.ignite.ml.math.Vector;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/** */
+public class VectorNormTest {
+ /** */
+ @Test
+ public void normalizeTest() {
+ normalizeTest(2, (val, len) -> val / len, Vector::normalize);
+ }
+
+ /** */
+ @Test
+ public void normalizePowerTest() {
+ for (double pow : new double[] {0, 0.5, 1, 2, 2.5, Double.POSITIVE_INFINITY})
+ normalizeTest(pow, (val, norm) -> val / norm, (v) -> v.normalize(pow));
+ }
+
+ /** */
+ @Test
+ public void logNormalizeTest() {
+ normalizeTest(2, (val, len) -> Math.log1p(val) / (len * Math.log(2)), Vector::logNormalize);
+ }
+
+ /** */
+ @Test
+ public void logNormalizePowerTest() {
+ for (double pow : new double[] {1.1, 2, 2.5})
+ normalizeTest(pow, (val, norm) -> Math.log1p(val) / (norm * Math.log(pow)), (v) -> v.logNormalize(pow));
+ }
+
+ /** */
+ @Test
+ public void kNormTest() {
+ for (double pow : new double[] {0, 0.5, 1, 2, 2.5, Double.POSITIVE_INFINITY})
+ toDoubleTest(pow, ref -> new Norm(ref, pow).calculate(), v -> v.kNorm(pow));
+ }
+
+ /** */
+ @Test
+ public void getLengthSquaredTest() {
+ toDoubleTest(2.0, ref -> new Norm(ref, 2).sumPowers(), Vector::getLengthSquared);
+ }
+
+ /** */
+ @Test
+ public void getDistanceSquaredTest() {
+ consumeSampleVectors((v, desc) -> {
+ new VectorImplementationsTest.ElementsChecker(v, desc); // IMPL NOTE this initialises vector
+
+ final int size = v.size();
+ final Vector vOnHeap = new DenseLocalOnHeapVector(size);
+ final Vector vOffHeap = new DenseLocalOffHeapVector(size);
+
+ invertValues(v, vOnHeap);
+ invertValues(v, vOffHeap);
+
+ for (int idx = 0; idx < size; idx++) {
+ final double exp = v.get(idx);
+ final int idxMirror = size - 1 - idx;
+
+ assertTrue("On heap vector difference at " + desc + ", idx " + idx,
+ exp - vOnHeap.get(idxMirror) == 0);
+ assertTrue("Off heap vector difference at " + desc + ", idx " + idx,
+ exp - vOffHeap.get(idxMirror) == 0);
+ }
+
+ final double exp = vOnHeap.minus(v).getLengthSquared(); // IMPL NOTE this won't mutate vOnHeap
+ final VectorImplementationsTest.Metric metric = new VectorImplementationsTest.Metric(exp, v.getDistanceSquared(vOnHeap));
+
+ assertTrue("On heap vector not close enough at " + desc + ", " + metric,
+ metric.closeEnough());
+
+ final VectorImplementationsTest.Metric metric1 = new VectorImplementationsTest.Metric(exp, v.getDistanceSquared(vOffHeap));
+
+ assertTrue("Off heap vector not close enough at " + desc + ", " + metric1,
+ metric1.closeEnough());
+ });
+ }
+
+ /** */
+ @Test
+ public void dotTest() {
+ consumeSampleVectors((v, desc) -> {
+ new VectorImplementationsTest.ElementsChecker(v, desc); // IMPL NOTE this initialises vector
+
+ final int size = v.size();
+ final Vector v1 = new DenseLocalOnHeapVector(size);
+
+ invertValues(v, v1);
+
+ final double actual = v.dot(v1);
+
+ double exp = 0;
+
+ for (Vector.Element e : v.all())
+ exp += e.get() * v1.get(e.index());
+
+ final VectorImplementationsTest.Metric metric = new VectorImplementationsTest.Metric(exp, actual);
+
+ assertTrue("Dot product not close enough at " + desc + ", " + metric,
+ metric.closeEnough());
+ });
+ }
+
+ /** */
+ private void invertValues(Vector src, Vector dst) {
+ final int size = src.size();
+
+ for (Vector.Element e : src.all()) {
+ final int idx = size - 1 - e.index();
+ final double val = e.get();
+
+ dst.set(idx, val);
+ }
+ }
+
+ /** */
+ private void toDoubleTest(Double val, Function<double[], Double> calcRef, Function<Vector, Double> calcVec) {
+ consumeSampleVectors((v, desc) -> {
+ final int size = v.size();
+ final double[] ref = new double[size];
+
+ new VectorImplementationsTest.ElementsChecker(v, ref, desc); // IMPL NOTE this initialises vector and reference array
+
+ final double exp = calcRef.apply(ref);
+ final double obtained = calcVec.apply(v);
+ final VectorImplementationsTest.Metric metric = new VectorImplementationsTest.Metric(exp, obtained);
+
+ assertTrue("Not close enough at " + desc
+ + (val == null ? "" : ", value " + val) + ", " + metric, metric.closeEnough());
+ });
+ }
+
+ /** */
+ private void normalizeTest(double pow, BiFunction<Double, Double, Double> operation,
+ Function<Vector, Vector> vecOperation) {
+ consumeSampleVectors((v, desc) -> {
+ final int size = v.size();
+ final double[] ref = new double[size];
+ final boolean nonNegative = pow != (int)pow;
+
+ final VectorImplementationsTest.ElementsChecker checker = new VectorImplementationsTest.ElementsChecker(v, ref, desc + ", pow = " + pow, nonNegative);
+ final double norm = new Norm(ref, pow).calculate();
+
+ for (int idx = 0; idx < size; idx++)
+ ref[idx] = operation.apply(ref[idx], norm);
+
+ checker.assertCloseEnough(vecOperation.apply(v), ref);
+ });
+ }
+
+ /** */
+ private void consumeSampleVectors(BiConsumer<Vector, String> consumer) {
+ new VectorImplementationsFixtures().consumeSampleVectors(null, consumer);
+ }
+
+ /** */
+ private static class Norm {
+ /** */
+ private final double[] arr;
+
+ /** */
+ private final Double pow;
+
+ /** */
+ Norm(double[] arr, double pow) {
+ this.arr = arr;
+ this.pow = pow;
+ }
+
+ /** */
+ double calculate() {
+ if (pow.equals(0.0))
+ return countNonZeroes(); // IMPL NOTE this is beautiful if you think of it
+
+ if (pow.equals(Double.POSITIVE_INFINITY))
+ return maxAbs();
+
+ return Math.pow(sumPowers(), 1 / pow);
+ }
+
+ /** */
+ double sumPowers() {
+ if (pow.equals(0.0))
+ return countNonZeroes();
+
+ double norm = 0;
+
+ for (double val : arr)
+ norm += pow == 1 ? Math.abs(val) : Math.pow(val, pow);
+
+ return norm;
+ }
+
+ /** */
+ private int countNonZeroes() {
+ int cnt = 0;
+
+ final Double zero = 0.0;
+
+ for (double val : arr)
+ if (!zero.equals(val))
+ cnt++;
+
+ return cnt;
+ }
+
+ /** */
+ private double maxAbs() {
+ double res = 0;
+
+ for (double val : arr) {
+ final double abs = Math.abs(val);
+
+ if (abs > res)
+ res = abs;
+ }
+
+ return res;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorToMatrixTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorToMatrixTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorToMatrixTest.java
new file mode 100644
index 0000000..4d5bc56
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorToMatrixTest.java
@@ -0,0 +1,308 @@
+/*
+ * 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.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOffHeapMatrix;
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.matrix.RandomMatrix;
+import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrix;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/** Tests for methods of Vector that involve Matrix. */
+public class VectorToMatrixTest {
+ /** */
+ private static final Map<Class<? extends Vector>, Class<? extends Matrix>> typesMap = typesMap();
+
+ /** */
+ private static final List<Class<? extends Vector>> likeMatrixUnsupported = Arrays.asList(FunctionVector.class,
+ SingleElementVector.class, SingleElementVectorView.class, ConstantVector.class);
+
+ /** */
+ @Test
+ public void testHaveLikeMatrix() throws InstantiationException, IllegalAccessException {
+ for (Class<? extends Vector> key : typesMap.keySet()) {
+ Class<? extends Matrix> val = typesMap.get(key);
+
+ if (val == null && likeMatrixSupported(key))
+ System.out.println("Missing test for implementation of likeMatrix for " + key.getSimpleName());
+ }
+ }
+
+ /** */
+ @Test
+ public void testLikeMatrixUnsupported() throws Exception {
+ consumeSampleVectors((v, desc) -> {
+ if (likeMatrixSupported(v.getClass()))
+ return;
+
+ boolean expECaught = false;
+
+ try {
+ assertNull("Null view instead of exception in " + desc, v.likeMatrix(1, 1));
+ }
+ catch (UnsupportedOperationException uoe) {
+ expECaught = true;
+ }
+
+ assertTrue("Expected exception was not caught in " + desc, expECaught);
+ });
+ }
+
+ /** */
+ @Test
+ public void testLikeMatrix() {
+ consumeSampleVectors((v, desc) -> {
+ if (!availableForTesting(v))
+ return;
+
+ final Matrix matrix = v.likeMatrix(1, 1);
+
+ Class<? extends Vector> key = v.getClass();
+
+ Class<? extends Matrix> expMatrixType = typesMap.get(key);
+
+ assertNotNull("Expect non-null matrix for " + key.getSimpleName() + " in " + desc, matrix);
+
+ Class<? extends Matrix> actualMatrixType = matrix.getClass();
+
+ assertTrue("Expected matrix type " + expMatrixType.getSimpleName()
+ + " should be assignable from actual type " + actualMatrixType.getSimpleName() + " in " + desc,
+ expMatrixType.isAssignableFrom(actualMatrixType));
+
+ for (int rows : new int[] {1, 2})
+ for (int cols : new int[] {1, 2}) {
+ final Matrix actualMatrix = v.likeMatrix(rows, cols);
+
+ String details = "rows " + rows + " cols " + cols;
+
+ assertNotNull("Expect non-null matrix for " + details + " in " + desc,
+ actualMatrix);
+
+ assertEquals("Unexpected number of rows in " + desc, rows, actualMatrix.rowSize());
+
+ assertEquals("Unexpected number of cols in " + desc, cols, actualMatrix.columnSize());
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testToMatrix() {
+ consumeSampleVectors((v, desc) -> {
+ if (!availableForTesting(v))
+ return;
+
+ fillWithNonZeroes(v);
+
+ final Matrix matrixRow = v.toMatrix(true);
+
+ final Matrix matrixCol = v.toMatrix(false);
+
+ for (Vector.Element e : v.all())
+ assertToMatrixValue(desc, matrixRow, matrixCol, e.get(), e.index());
+ });
+ }
+
+ /** */
+ @Test
+ public void testToMatrixPlusOne() {
+ consumeSampleVectors((v, desc) -> {
+ if (!availableForTesting(v))
+ return;
+
+ fillWithNonZeroes(v);
+
+ for (double zeroVal : new double[] {-1, 0, 1, 2}) {
+ final Matrix matrixRow = v.toMatrixPlusOne(true, zeroVal);
+
+ final Matrix matrixCol = v.toMatrixPlusOne(false, zeroVal);
+
+ final Metric metricRow0 = new Metric(zeroVal, matrixRow.get(0, 0));
+
+ assertTrue("Not close enough row like " + metricRow0 + " at index 0 in " + desc,
+ metricRow0.closeEnough());
+
+ final Metric metricCol0 = new Metric(zeroVal, matrixCol.get(0, 0));
+
+ assertTrue("Not close enough cols like " + metricCol0 + " at index 0 in " + desc,
+ metricCol0.closeEnough());
+
+ for (Vector.Element e : v.all())
+ assertToMatrixValue(desc, matrixRow, matrixCol, e.get(), e.index() + 1);
+ }
+ });
+ }
+
+ /** */
+ @Test
+ public void testCross() {
+ consumeSampleVectors((v, desc) -> {
+ if (!availableForTesting(v))
+ return;
+
+ fillWithNonZeroes(v);
+
+ for (int delta : new int[] {-1, 0, 1}) {
+ final int size2 = v.size() + delta;
+
+ if (size2 < 1)
+ return;
+
+ final Vector v2 = new DenseLocalOnHeapVector(size2);
+
+ for (Vector.Element e : v2.all())
+ e.set(size2 - e.index());
+
+ assertCross(v, v2, desc);
+ }
+ });
+ }
+
+ /** */
+ private void assertCross(Vector v1, Vector v2, String desc) {
+ assertNotNull(v1);
+ assertNotNull(v2);
+
+ final Matrix res = v1.cross(v2);
+
+ assertNotNull("Cross matrix is expected to be not null in " + desc, res);
+
+ assertEquals("Unexpected number of rows in cross Matrix in " + desc, v1.size(), res.rowSize());
+
+ assertEquals("Unexpected number of cols in cross Matrix in " + desc, v2.size(), res.columnSize());
+
+ for (int row = 0; row < v1.size(); row++)
+ for (int col = 0; col < v2.size(); col++) {
+ final Metric metric = new Metric(v1.get(row) * v2.get(col), res.get(row, col));
+
+ assertTrue("Not close enough cross " + metric + " at row " + row + " at col " + col
+ + " in " + desc, metric.closeEnough());
+ }
+ }
+
+ /** */
+ private void assertToMatrixValue(String desc, Matrix matrixRow, Matrix matrixCol, double exp, int idx) {
+ final Metric metricRow = new Metric(exp, matrixRow.get(0, idx));
+
+ assertTrue("Not close enough row like " + metricRow + " at index " + idx + " in " + desc,
+ metricRow.closeEnough());
+
+ final Metric metricCol = new Metric(exp, matrixCol.get(idx, 0));
+
+ assertTrue("Not close enough cols like " + matrixCol + " at index " + idx + " in " + desc,
+ metricCol.closeEnough());
+ }
+
+ /** */
+ private void fillWithNonZeroes(Vector sample) {
+ if (sample instanceof RandomVector)
+ return;
+
+ for (Vector.Element e : sample.all())
+ e.set(1 + e.index());
+ }
+
+ /** */
+ private boolean availableForTesting(Vector v) {
+ assertNotNull("Error in test: vector is null", v);
+
+ if (!likeMatrixSupported(v.getClass()))
+ return false;
+
+ final boolean availableForTesting = typesMap.get(v.getClass()) != null;
+
+ final Matrix actualLikeMatrix = v.likeMatrix(1, 1);
+
+ assertTrue("Need to enable matrix testing for vector type " + v.getClass().getSimpleName(),
+ availableForTesting || actualLikeMatrix == null);
+
+ return availableForTesting;
+ }
+
+ /** Ignore test for given vector type. */
+ private boolean likeMatrixSupported(Class<? extends Vector> clazz) {
+ for (Class<? extends Vector> ignoredClass : likeMatrixUnsupported)
+ if (ignoredClass.isAssignableFrom(clazz))
+ return false;
+
+ return true;
+ }
+
+ /** */
+ private void consumeSampleVectors(BiConsumer<Vector, String> consumer) {
+ new VectorImplementationsFixtures().consumeSampleVectors(null, consumer);
+ }
+
+ /** */
+ private static Map<Class<? extends Vector>, Class<? extends Matrix>> typesMap() {
+ return new LinkedHashMap<Class<? extends Vector>, Class<? extends Matrix>>() {{
+ put(DenseLocalOnHeapVector.class, DenseLocalOnHeapMatrix.class);
+ put(DenseLocalOffHeapVector.class, DenseLocalOffHeapMatrix.class);
+ put(RandomVector.class, RandomMatrix.class);
+ put(SparseLocalVector.class, SparseLocalOnHeapMatrix.class);
+ put(SingleElementVector.class, null); // todo find out if we need SingleElementMatrix to match, or skip it
+ put(ConstantVector.class, null);
+ put(FunctionVector.class, null);
+ put(PivotedVectorView.class, DenseLocalOnHeapMatrix.class); // IMPL NOTE per fixture
+ put(SingleElementVectorView.class, null);
+ put(MatrixVectorView.class, DenseLocalOnHeapMatrix.class); // IMPL NOTE per fixture
+ put(DelegatingVector.class, DenseLocalOnHeapMatrix.class); // IMPL NOTE per fixture
+ // IMPL NOTE check for presence of all implementations here will be done in testHaveLikeMatrix via Fixture
+ }};
+ }
+
+ /** */
+ private static class Metric { // todo consider if softer tolerance (like say 0.1 or 0.01) would make sense here
+ /** */
+ private final double exp;
+
+ /** */
+ private final double obtained;
+
+ /** **/
+ Metric(double exp, double obtained) {
+ this.exp = exp;
+ this.obtained = obtained;
+ }
+
+ /** */
+ boolean closeEnough() {
+ return new Double(exp).equals(obtained);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "Metric{" + "expected=" + exp +
+ ", obtained=" + obtained +
+ '}';
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorViewTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorViewTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorViewTest.java
new file mode 100644
index 0000000..ad2bc3f
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/VectorViewTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.function.BiConsumer;
+import java.util.stream.IntStream;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.impls.MathTestConstants;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Unit tests for {@link VectorView}.
+ */
+public class VectorViewTest {
+ /** */
+ private static final int OFFSET = 10;
+
+ /** */
+ private static final int VIEW_LENGTH = 80;
+
+ /** */
+ private static final String EXTERNALIZE_TEST_FILE_NAME = "externalizeTest";
+
+ /** */
+ private VectorView testVector;
+
+ /** */
+ private DenseLocalOnHeapVector parentVector;
+
+ /** */
+ private double[] parentData;
+
+ /** */
+ @Before
+ public void setup() {
+ parentVector = new DenseLocalOnHeapVector(MathTestConstants.STORAGE_SIZE);
+
+ IntStream.range(0, MathTestConstants.STORAGE_SIZE).forEach(idx -> parentVector.set(idx, Math.random()));
+
+ parentData = parentVector.getStorage().data().clone();
+
+ testVector = new VectorView(parentVector, OFFSET, VIEW_LENGTH);
+ }
+
+ /** */
+ @AfterClass
+ public static void cleanup() throws IOException {
+ Files.deleteIfExists(Paths.get(EXTERNALIZE_TEST_FILE_NAME));
+ }
+
+ /** */
+ @Test
+ public void testCopy() throws Exception {
+ Vector cp = testVector.copy();
+
+ assertTrue(MathTestConstants.VAL_NOT_EQUALS, cp.equals(testVector));
+ }
+
+ /** */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLike() throws Exception {
+ for (int card : new int[] {1, 2, 4, 8, 16, 32, 64, 128})
+ consumeSampleVectors((v, desc) -> {
+ Vector vLike = new VectorView(v, 0, 1).like(card);
+
+ Class<? extends Vector> expType = v.getClass();
+
+ assertNotNull("Expect non-null like vector for " + expType.getSimpleName() + " in " + desc, vLike);
+
+ assertEquals("Expect size equal to cardinality at " + desc, card, vLike.size());
+
+ Class<? extends Vector> actualType = vLike.getClass();
+
+ assertTrue("Expected matrix type " + expType.getSimpleName()
+ + " should be assignable from actual type " + actualType.getSimpleName() + " in " + desc,
+ expType.isAssignableFrom(actualType));
+
+ });
+ }
+
+ /** See also {@link VectorToMatrixTest#testLikeMatrix()}. */
+ @Test
+ public void testLikeMatrix() {
+ consumeSampleVectors((v, desc) -> {
+ boolean expECaught = false;
+
+ try {
+ assertNull("Null view instead of exception in " + desc, new VectorView(v, 0, 1).likeMatrix(1, 1));
+ }
+ catch (UnsupportedOperationException uoe) {
+ expECaught = true;
+ }
+
+ assertTrue("Expected exception was not caught in " + desc, expECaught);
+ });
+ }
+
+ /** */
+ @Test
+ public void testWriteReadExternal() throws Exception {
+ assertNotNull("Unexpected null parent data", parentData);
+
+ File f = new File(EXTERNALIZE_TEST_FILE_NAME);
+
+ try {
+ ObjectOutputStream objOutputStream = new ObjectOutputStream(new FileOutputStream(f));
+
+ objOutputStream.writeObject(testVector);
+
+ objOutputStream.close();
+
+ ObjectInputStream objInputStream = new ObjectInputStream(new FileInputStream(f));
+
+ VectorView readVector = (VectorView)objInputStream.readObject();
+
+ objInputStream.close();
+
+ assertTrue(MathTestConstants.VAL_NOT_EQUALS, testVector.equals(readVector));
+ }
+ catch (ClassNotFoundException | IOException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ /** */
+ private void consumeSampleVectors(BiConsumer<Vector, String> consumer) {
+ new VectorImplementationsFixtures().consumeSampleVectors(null, consumer);
+ }
+
+}