http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorIterableTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorIterableTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorIterableTest.java deleted file mode 100644 index 7a64c85..0000000 --- a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorIterableTest.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * 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.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.math.Vector; -import org.apache.ignite.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/math/impls/vector/VectorNormTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorNormTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorNormTest.java deleted file mode 100644 index f1c2928..0000000 --- a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorNormTest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 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.math.impls.vector; - -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Function; -import org.apache.ignite.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/math/impls/vector/VectorToMatrixTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorToMatrixTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorToMatrixTest.java deleted file mode 100644 index adcb2cc..0000000 --- a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorToMatrixTest.java +++ /dev/null @@ -1,291 +0,0 @@ -package org.apache.ignite.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.math.Matrix; -import org.apache.ignite.math.Vector; -import org.apache.ignite.math.exceptions.UnsupportedOperationException; -import org.apache.ignite.math.impls.matrix.DenseLocalOffHeapMatrix; -import org.apache.ignite.math.impls.matrix.DenseLocalOnHeapMatrix; -import org.apache.ignite.math.impls.matrix.RandomMatrix; -import org.apache.ignite.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/math/impls/vector/VectorViewTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorViewTest.java b/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorViewTest.java deleted file mode 100644 index 55893d0..0000000 --- a/modules/ml/src/test/java/org/apache/ignite/math/impls/vector/VectorViewTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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.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.math.Vector; -import org.apache.ignite.math.exceptions.UnsupportedOperationException; -import org.apache.ignite.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 = org.apache.ignite.math.exceptions.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); - } - -} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/ExternalizeTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/ExternalizeTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/ExternalizeTest.java new file mode 100644 index 0000000..32a8ec1 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/ExternalizeTest.java @@ -0,0 +1,66 @@ +/* + * 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; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import org.apache.ignite.ml.math.impls.MathTestConstants; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Common test for externalization. + */ +public abstract class ExternalizeTest<T extends Externalizable & Destroyable> { + /** */ + protected void externalizeTest(T initObj) { + T objRestored = null; + + try { + ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream); + + objOutputStream.writeObject(initObj); + + ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray()); + ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream); + + objRestored = (T)objInputStream.readObject(); + + assertTrue(MathTestConstants.VAL_NOT_EQUALS, initObj.equals(objRestored)); + assertTrue(MathTestConstants.VAL_NOT_EQUALS, Integer.compare(initObj.hashCode(), objRestored.hashCode()) == 0); + } + catch (ClassNotFoundException | IOException e) { + fail(e + " [" + e.getMessage() + "]"); + } + finally { + if (objRestored != null) + objRestored.destroy(); + } + } + + /** */ + @Test + public abstract void externalizeTest(); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java new file mode 100644 index 0000000..720a090 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java @@ -0,0 +1,39 @@ +/* + * 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; + +import org.apache.ignite.ml.math.impls.matrix.CacheMatrixTest; +import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrixTest; +import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorageTest; +import org.apache.ignite.ml.math.impls.vector.CacheVectorTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Test suite for all distributed tests located in org.apache.ignite.math.impls.* package. + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + CacheVectorTest.class, + CacheMatrixTest.class, + SparseDistributedMatrixStorageTest.class, + SparseDistributedMatrixTest.class, +}) +public class MathImplDistributedTestSuite { + // No-op. +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java new file mode 100644 index 0000000..be9c33a --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplLocalTestSuite.java @@ -0,0 +1,123 @@ +/* + * 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; + +import org.apache.ignite.ml.math.decompositions.CholeskyDecompositionTest; +import org.apache.ignite.ml.math.decompositions.EigenDecompositionTest; +import org.apache.ignite.ml.math.decompositions.LUDecompositionTest; +import org.apache.ignite.ml.math.decompositions.QRDecompositionTest; +import org.apache.ignite.ml.math.decompositions.SingularValueDecompositionTest; +import org.apache.ignite.ml.math.impls.matrix.DenseLocalOffHeapMatrixConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrixConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.DiagonalMatrixTest; +import org.apache.ignite.ml.math.impls.matrix.FunctionMatrixConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.MatrixAttributeTest; +import org.apache.ignite.ml.math.impls.matrix.MatrixImplementationsTest; +import org.apache.ignite.ml.math.impls.matrix.MatrixViewConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.PivotedMatrixViewConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.RandomMatrixConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrixConstructorTest; +import org.apache.ignite.ml.math.impls.matrix.TransposedMatrixViewTest; +import org.apache.ignite.ml.math.impls.storage.matrix.MatrixArrayStorageTest; +import org.apache.ignite.ml.math.impls.storage.matrix.MatrixOffHeapStorageTest; +import org.apache.ignite.ml.math.impls.storage.matrix.MatrixStorageImplementationTest; +import org.apache.ignite.ml.math.impls.storage.vector.RandomAccessSparseVectorStorageTest; +import org.apache.ignite.ml.math.impls.storage.vector.SparseLocalOffHeapVectorStorageTest; +import org.apache.ignite.ml.math.impls.storage.vector.VectorArrayStorageTest; +import org.apache.ignite.ml.math.impls.storage.vector.VectorOffheapStorageTest; +import org.apache.ignite.ml.math.impls.vector.AbstractVectorTest; +import org.apache.ignite.ml.math.impls.vector.ConstantVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.DelegatingVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOffHeapVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.FunctionVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.MatrixVectorViewTest; +import org.apache.ignite.ml.math.impls.vector.PivotedVectorViewConstructorTest; +import org.apache.ignite.ml.math.impls.vector.RandomVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.SingleElementVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.SingleElementVectorViewConstructorTest; +import org.apache.ignite.ml.math.impls.vector.SparseLocalVectorConstructorTest; +import org.apache.ignite.ml.math.impls.vector.VectorAttributesTest; +import org.apache.ignite.ml.math.impls.vector.VectorFoldMapTest; +import org.apache.ignite.ml.math.impls.vector.VectorImplementationsTest; +import org.apache.ignite.ml.math.impls.vector.VectorIterableTest; +import org.apache.ignite.ml.math.impls.vector.VectorNormTest; +import org.apache.ignite.ml.math.impls.vector.VectorToMatrixTest; +import org.apache.ignite.ml.math.impls.vector.VectorViewTest; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Test suite for all local tests located in org.apache.ignite.math.impls.* package. + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + // Vector constructors tests. + DenseLocalOnHeapVectorConstructorTest.class, + DenseLocalOffHeapVectorConstructorTest.class, + SparseLocalVectorConstructorTest.class, + RandomVectorConstructorTest.class, + ConstantVectorConstructorTest.class, + FunctionVectorConstructorTest.class, + SingleElementVectorConstructorTest.class, + PivotedVectorViewConstructorTest.class, + SingleElementVectorViewConstructorTest.class, + DelegatingVectorConstructorTest.class, + // Various vectors tests. + AbstractVectorTest.class, + VectorImplementationsTest.class, + VectorViewTest.class, + MatrixVectorViewTest.class, + // Vector particular features tests. + VectorIterableTest.class, + VectorAttributesTest.class, + VectorToMatrixTest.class, + VectorNormTest.class, + VectorFoldMapTest.class, + // Vector storage tests + VectorArrayStorageTest.class, + VectorOffheapStorageTest.class, + RandomAccessSparseVectorStorageTest.class, + SparseLocalOffHeapVectorStorageTest.class, + // Matrix storage tests. + MatrixStorageImplementationTest.class, + MatrixOffHeapStorageTest.class, + MatrixArrayStorageTest.class, + // Matrix constructors tests. + DenseLocalOnHeapMatrixConstructorTest.class, + DenseLocalOffHeapMatrixConstructorTest.class, + RandomMatrixConstructorTest.class, + FunctionMatrixConstructorTest.class, + MatrixViewConstructorTest.class, + PivotedMatrixViewConstructorTest.class, + SparseLocalOnHeapMatrixConstructorTest.class, + // Matrix tests. + MatrixImplementationsTest.class, + DiagonalMatrixTest.class, + MatrixAttributeTest.class, + TransposedMatrixViewTest.class, + // Decomposes + LUDecompositionTest.class, + EigenDecompositionTest.class, + CholeskyDecompositionTest.class, + QRDecompositionTest.class, + SingularValueDecompositionTest.class +}) +public class MathImplLocalTestSuite { + // No-op. +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java new file mode 100644 index 0000000..5f41583 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplMainTestSuite.java @@ -0,0 +1,33 @@ +/* + * 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; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Test suite for local and distributed tests + */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + MathImplLocalTestSuite.class, + MathImplDistributedTestSuite.class +}) +public class MathImplMainTestSuite { + // No-op. +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/TracerTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/TracerTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/TracerTest.java new file mode 100644 index 0000000..d7c746d --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/TracerTest.java @@ -0,0 +1,195 @@ +/* + * 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; + +import java.awt.Color; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import org.apache.ignite.ml.math.impls.MathTestConstants; +import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector; +import org.junit.Test; + +import static java.nio.file.Files.createTempFile; +import static org.junit.Assert.assertEquals; + +/** + * Tests for {@link Tracer}. + */ +public class TracerTest { + /** */ private static final String DEFAULT_FORMAT = "%.10f"; + /** */ private static final double DEFAULT_DELTA = 0.000000001d; + + /** + * Color mapper that maps [0, 1] range into three distinct RGB segments. + */ + private static final Tracer.ColorMapper COLOR_MAPPER = new Tracer.ColorMapper() { + /** {@inheritDoc} */ + @Override public Color apply(Double d) { + if (d <= 0.33) + return Color.RED; + else if (d <= 0.66) + return Color.GREEN; + else + return Color.BLUE; + } + }; + + /** + * @param size Vector size. + */ + private Vector makeRandomVector(int size) { + DenseLocalOnHeapVector vec = new DenseLocalOnHeapVector(size); + + vec.assign((idx) -> Math.random()); + + return vec; + } + + /** + * @param rows Amount of rows in matrix. + * @param cols Amount of columns in matrix. + */ + private Matrix makeRandomMatrix(int rows, int cols) { + DenseLocalOnHeapMatrix mtx = new DenseLocalOnHeapMatrix(rows, cols); + + // Missing assign(f)? + mtx.map((d) -> Math.random()); + + return mtx; + } + + /** + * + */ + @Test + public void testAsciiVectorTracer() { + Vector vec = makeRandomVector(20); + + Tracer.showAscii(vec); + Tracer.showAscii(vec, "%2f"); + Tracer.showAscii(vec, "%.3g"); + } + + /** + * + */ + @Test + public void testAsciiMatrixTracer() { + Matrix mtx = makeRandomMatrix(10, 10); + + Tracer.showAscii(mtx); + Tracer.showAscii(mtx, "%2f"); + Tracer.showAscii(mtx, "%.3g"); + } + + /** + * + */ + @Test + public void testHtmlVectorTracer() throws IOException { + Vector vec1 = makeRandomVector(1000); + + // Default color mapping. + Tracer.showHtml(vec1); + + // Custom color mapping. + Tracer.showHtml(vec1, COLOR_MAPPER); + + // Default color mapping with sorted vector. + Tracer.showHtml(vec1.sort()); + } + + /** + * + */ + @Test + public void testHtmlMatrixTracer() throws IOException { + Matrix mtx1 = makeRandomMatrix(100, 100); + + // Custom color mapping. + Tracer.showHtml(mtx1, COLOR_MAPPER); + + Matrix mtx2 = new DenseLocalOnHeapMatrix(100, 100); + + double MAX = (double)(mtx2.rowSize() * mtx2.columnSize()); + + mtx2.assign((x, y) -> (double)(x * y) / MAX); + + Tracer.showHtml(mtx2); + } + + /** */ + @Test + public void testWriteVectorToCSVFile() throws IOException { + DenseLocalOnHeapVector vector = new DenseLocalOnHeapVector(MathTestConstants.STORAGE_SIZE); + + for (int i = 0; i < vector.size(); i++) + vector.set(i, Math.random()); + + Path file = createTempFile("vector", ".csv"); + + Tracer.saveAsCsv(vector, DEFAULT_FORMAT, file.toString()); + + System.out.println("Vector exported: " + file.getFileName()); + + List<String> strings = Files.readAllLines(file); + Optional<String> reduce = strings.stream().reduce((s1, s2) -> s1 + s2); + String[] csvVals = reduce.get().split(","); + + for (int i = 0; i < vector.size(); i++) { + Double csvVal = Double.valueOf(csvVals[i]); + + assertEquals("Unexpected value.", csvVal, vector.get(i), DEFAULT_DELTA); + } + + Files.deleteIfExists(file); + } + + /** */ + @Test + public void testWriteMatrixToCSVFile() throws IOException { + DenseLocalOnHeapMatrix matrix = new DenseLocalOnHeapMatrix(MathTestConstants.STORAGE_SIZE, MathTestConstants.STORAGE_SIZE); + + for (int i = 0; i < matrix.rowSize(); i++) + for (int j = 0; j < matrix.columnSize(); j++) + matrix.set(i, j, Math.random()); + + Path file = createTempFile("matrix", ".csv"); + + Tracer.saveAsCsv(matrix, DEFAULT_FORMAT, file.toString()); + + System.out.println("Matrix exported: " + file.getFileName()); + + List<String> strings = Files.readAllLines(file); + Optional<String> reduce = strings.stream().reduce((s1, s2) -> s1 + s2); + String[] csvVals = reduce.get().split(","); + + for (int i = 0; i < matrix.rowSize(); i++) + for (int j = 0; j < matrix.columnSize(); j++) { + Double csvVal = Double.valueOf(csvVals[i * matrix.rowSize() + j]); + + assertEquals("Unexpected value.", csvVal, matrix.get(i, j), DEFAULT_DELTA); + } + + Files.deleteIfExists(file); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmark.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmark.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmark.java new file mode 100644 index 0000000..33ccfc9 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmark.java @@ -0,0 +1,205 @@ +/* + * 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.benchmark; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +/** Refer {@link MathBenchmarkSelfTest} for usage examples. */ +class MathBenchmark { + /** */ + private final boolean outputToConsole; + + /** */ + private final String benchmarkName; + + /** */ + private final int measurementTimes; + + /** */ + private final int warmUpTimes; + + /** */ + private final String tag; + + /** */ + private final String comments; + + /** Constructor strictly for use within this class. */ + private MathBenchmark(String benchmarkName, boolean outputToConsole, int measurementTimes, int warmUpTimes, + String tag, String comments) { + this.benchmarkName = benchmarkName; + this.outputToConsole = outputToConsole; + this.measurementTimes = measurementTimes; + this.warmUpTimes = warmUpTimes; + this.tag = tag; + this.comments = comments; + validate(); + } + + /** + * Benchmark with specified name and default parameters, in particular, default output file. + * + * @param benchmarkName name + */ + MathBenchmark(String benchmarkName) { + this(benchmarkName, false, 100, 1, "", ""); + } + + /** + * Executes the code using config of this benchmark. + * + * @param code code to execute + * @throws Exception if something goes wrong + */ + void execute(BenchmarkCode code) throws Exception { + System.out.println("Started benchmark [" + benchmarkName + "]."); + + for (int cnt = 0; cnt < warmUpTimes; cnt++) + code.call(); + + final long start = System.currentTimeMillis(); + + for (int cnt = 0; cnt < measurementTimes; cnt++) + code.call(); + + final long end = System.currentTimeMillis(); + + writeResults(formatResults(start, end)); + + System.out.println("Finished benchmark [" + benchmarkName + "]."); + } + + /** + * Set optional output mode for using stdout. + * + * @return configured benchmark + */ + MathBenchmark outputToConsole() { + return new MathBenchmark(benchmarkName, true, measurementTimes, warmUpTimes, tag, comments); + } + + /** + * Set optional measurement times. + * + * @param param times + * @return configured benchmark + */ + MathBenchmark measurementTimes(int param) { + return new MathBenchmark(benchmarkName, outputToConsole, param, warmUpTimes, tag, comments); + } + + /** + * Set optional warm-up times. + * + * @param param times + * @return configured benchmark + */ + MathBenchmark warmUpTimes(int param) { + return new MathBenchmark(benchmarkName, outputToConsole, measurementTimes, param, tag, comments); + } + + /** + * Set optional tag to help filtering specific kind of benchmark results. + * + * @param param name + * @return configured benchmark + */ + MathBenchmark tag(String param) { + return new MathBenchmark(benchmarkName, outputToConsole, measurementTimes, warmUpTimes, param, comments); + } + + /** + * Set optional comments. + * + * @param param name + * @return configured benchmark + */ + MathBenchmark comments(String param) { + return new MathBenchmark(benchmarkName, outputToConsole, measurementTimes, warmUpTimes, tag, param); + } + + /** */ + private void writeResults(String results) throws Exception { + if (outputToConsole) { + System.out.println(results); + + return; + } + + new ResultsWriter().append(results); + } + + /** */ + private String formatResults(long start, long end) { + final String delim = ","; + + assert !formatDouble(1000_000_001.1).contains(delim) : "Formatted results contain [" + delim + "]."; + + final String ts = formatTs(start); + + assert !ts.contains(delim) : "Formatted timestamp contains [" + delim + "]."; + + return benchmarkName + + delim + + ts + // IMPL NOTE timestamp + delim + + formatDouble((double)(end - start) / measurementTimes) + + delim + + measurementTimes + + delim + + warmUpTimes + + delim + + tag + + delim + + comments; + } + + /** */ + private String formatDouble(double val) { + return String.format(Locale.US, "%f", val); + } + + /** */ + private String formatTs(long ts) { + final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); + + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); + + return sdf.format(new Date(ts)); + } + + /** */ + private void validate() { + if (benchmarkName == null || benchmarkName.isEmpty()) + throw new IllegalArgumentException("Invalid benchmark name: [" + benchmarkName + "]."); + + if (measurementTimes < 1) + throw new IllegalArgumentException("Invalid measurement times: [" + measurementTimes + "]."); + } + + /** */ + interface BenchmarkCode { + // todo find out why Callable<Void> failed to work here + + /** */ + void call() throws Exception; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmarkSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmarkSelfTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmarkSelfTest.java new file mode 100644 index 0000000..86b29db --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/MathBenchmarkSelfTest.java @@ -0,0 +1,100 @@ +/* + * 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.benchmark; + +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +/** */ +public class MathBenchmarkSelfTest { + /** */ + @Test + @Ignore("Benchmark tests are intended only for manual execution") + public void demoTest() throws Exception { + for (int i = 0; i < 2; i++) + new MathBenchmark("demo test") + .outputToConsole() // IMPL NOTE this is to write output into console instead of a file + .tag(null) // IMPL NOTE try null for tag, expect it to be formatted reasonably + .comments(null) // IMPL NOTE try null for comments, expect it to be formatted reasonably + .execute(() -> { + double seed = 1.1; + + for (int cnt = 0; cnt < 1000; cnt++) { + seed = Math.pow(seed, 2); + + assertTrue(seed > 0); + } + }); + } + + /** */ + @Test + @Ignore("Benchmark tests are intended only for manual execution") + public void configTest() throws Exception { + new MathBenchmark("demo config test") + .outputToConsole() + .measurementTimes(2) + .warmUpTimes(0) + .tag("demo tag") + .comments("demo comments") + .execute(() -> System.out.println("config test")); + } + + /** */ + @Test(expected = IllegalArgumentException.class) + @Ignore("Benchmark tests are intended only for manual execution") + public void emptyNameTest() throws Exception { + new MathBenchmark("") + .outputToConsole() + .measurementTimes(1) + .warmUpTimes(1) + .tag("empty name test tag") + .comments("empty name test comments") + .execute(() -> System.out.println("empty name test")); + } + + /** */ + @Test(expected = IllegalArgumentException.class) + @Ignore("Benchmark tests are intended only for manual execution") + public void nullDropboxPathTest() throws Exception { + new ResultsWriter(null, "whatever", "whatever"); + } + + /** */ + @Test(expected = IllegalArgumentException.class) + @Ignore("Benchmark tests are intended only for manual execution") + public void nullDropboxUrlTest() throws Exception { + new ResultsWriter("whatever", null, "whatever"); + } + + /** */ + @Test(expected = IllegalArgumentException.class) + @Ignore("Benchmark tests are intended only for manual execution") + public void nullDropboxTokenTest() throws Exception { + new ResultsWriter("whatever", "whatever", null); + } + + /** */ + @Test(expected = IllegalArgumentException.class) + @Ignore("Benchmark tests are intended only for manual execution") + public void nullResultsTest() throws Exception { + new ResultsWriter("whatever", "whatever", "whatever").append(null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/ResultsWriter.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/ResultsWriter.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/ResultsWriter.java new file mode 100644 index 0000000..2c37bff --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/ResultsWriter.java @@ -0,0 +1,127 @@ +/* + * 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.benchmark; + +import com.dropbox.core.DbxException; +import com.dropbox.core.DbxRequestConfig; +import com.dropbox.core.v2.DbxClientV2; +import com.dropbox.core.v2.files.WriteMode; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.UUID; + +/** */ +class ResultsWriter { + /** */ + private static final String DROPBOX_PATH + = "/benchmarks/math.benchmark.results.csv"; + + /** */ + private static final String DROPBOX_URL + = "https://www.dropbox.com/s/r7tcle31r7gaty8/math.benchmark.results.csv"; + + /** */ + private static final String ACCESS_TOKEN + = "1MMmQjEyzGAAAAAAAAAAfDFrQ6oBPPi4NX-iU_VrgmXB2JDXqRHGa125cTkkEQ0V"; + + /** */ + private final String dropboxPath; + /** */ + private final String dropboxUrl; + /** */ + private final String accessTok; + + /** */ + ResultsWriter(String dropboxPath, String dropboxUrl, String accessTok) { + this.dropboxPath = dropboxPath; + this.dropboxUrl = dropboxUrl; + this.accessTok = accessTok; + + if (dropboxPath == null || dropboxUrl == null || accessTok == null) + throw new IllegalArgumentException("Neither of dropbox path, URL, access token can be null."); + } + + /** **/ + ResultsWriter() { + this(DROPBOX_PATH, DROPBOX_URL, ACCESS_TOKEN); + } + + /** */ + void append(String res) throws DbxException, IOException { + if (res == null) + throw new IllegalArgumentException("benchmark result is null"); + + if (dropboxPath == null) { + System.out.println(res); + + return; + } + + append(res, client()); + } + + /** */ + private void append(String res, DbxClientV2 client) throws DbxException, IOException { + File tmp = createTmpFile(); + + try (FileOutputStream out = new FileOutputStream(tmp)) { + client.files().download(dropboxPath).download(out); + } + + writeResults(res, tmp); + + try (FileInputStream in = new FileInputStream(tmp)) { + client.files().uploadBuilder(dropboxPath).withMode(WriteMode.OVERWRITE).uploadAndFinish(in); + } + + if (!tmp.delete()) + System.out.println("Failed to delete " + tmp.getAbsolutePath()); + + System.out.println("Uploaded benchmark results to: " + dropboxUrl); + } + + /** */ + private void writeResults(String res, File tmp) throws IOException { + final String unixLineSeparator = "\n"; + + try (final PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(tmp.toURI()), + StandardOpenOption.APPEND, StandardOpenOption.CREATE))) { + writer.write(res + unixLineSeparator); + } + } + + /** */ + private File createTmpFile() throws IOException { + File tmp = File.createTempFile(UUID.randomUUID().toString(), ".csv"); + + tmp.deleteOnExit(); + + return tmp; + } + + /** */ + private DbxClientV2 client() { + return new DbxClientV2(DbxRequestConfig.newBuilder("dropbox/MathBenchmark").build(), accessTok); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/VectorBenchmarkTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/VectorBenchmarkTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/VectorBenchmarkTest.java new file mode 100644 index 0000000..fd98382 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/VectorBenchmarkTest.java @@ -0,0 +1,138 @@ +/* + * 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.benchmark; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOffHeapVector; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector; +import org.junit.Ignore; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +/** */ +public class VectorBenchmarkTest { + // todo add benchmarks for other methods in Vector and for other types of Vector and Matrix + + /** */ + @Test + @Ignore("Benchmark tests are intended only for manual execution") + public void testDenseLocalOnHeapVector() throws Exception { + benchmark("DenseLocalOnHeapVector basic mix", DenseLocalOnHeapVector::new, this::basicMix); + + benchmark("DenseLocalOnHeapVector fold map", DenseLocalOnHeapVector::new, this::foldMapMix); + } + + /** */ + @Test + @Ignore("Benchmark tests are intended only for manual execution") + public void testDenseLocalOffHeapVector() throws Exception { + benchmark("DenseLocalOffHeapVector basic mix", DenseLocalOffHeapVector::new, this::basicMix); + + benchmark("DenseLocalOffHeapVector fold map", DenseLocalOffHeapVector::new, this::foldMapMix); + } + + /** */ + private void benchmark(String namePrefix, Function<Integer, Vector> constructor, + BiConsumer<Integer, Function<Integer, Vector>> consumer) throws Exception { + assertNotNull(namePrefix); + + new MathBenchmark(namePrefix + " small sizes").execute(() -> { + for (int size : new int[] {2, 3, 4, 5, 6, 7}) + consumer.accept(size, constructor); + }); + + new MathBenchmark(namePrefix + " sizes powers of 2").execute(() -> { + for (int power : new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}) + consumer.accept(1 << power, constructor); + }); + + new MathBenchmark(namePrefix + " large sizes").execute(() -> { + for (int power : new int[] {10, 12, 14, 16}) + for (int delta : new int[] {-1, 0, 1}) + consumer.accept((1 << power) + delta, constructor); + }); + + new MathBenchmark(namePrefix + " extra large sizes") + .measurementTimes(10) + .execute(() -> { // IMPL NOTE trying below with power 22 almost killed my IDEA and laptop + for (int power : new int[] {17, 18, 19, 20, 21}) + for (int delta : new int[] {-1, 0}) // IMPL NOTE delta +1 is not intended for use here + consumer.accept((1 << power) + delta, constructor); + }); + } + + /** */ + private void basicMix(int size, Function<Integer, Vector> constructor) { + final Vector v1 = constructor.apply(size), v2 = constructor.apply(size); + + for (int idx = 0; idx < size; idx++) { + v1.set(idx, idx); + + v2.set(idx, size - idx); + } + + assertNotNull(v1.sum()); + + assertNotNull(v1.copy()); + + assertFalse(v1.getLengthSquared() < 0); + + assertNotNull(v1.normalize()); + + assertNotNull(v1.logNormalize()); + + assertFalse(v1.getDistanceSquared(v2) < 0); + + assertNotNull(v1.divide(2)); + + assertNotNull(v1.minus(v2)); + + assertNotNull(v1.plus(v2)); + + assertNotNull(v1.dot(v2)); + + assertNotNull(v1.assign(v2)); + + assertNotNull(v1.assign(1)); // IMPL NOTE this would better be last test for it sets all values the same + } + + /** */ + private void foldMapMix(int size, Function<Integer, Vector> constructor) { + final Vector v1 = constructor.apply(size), v2 = constructor.apply(size); + + for (int idx = 0; idx < size; idx++) { + v1.set(idx, idx); + + v2.set(idx, size - idx); + } + + assertNotNull(v1.map((val) -> (val + 1))); + + assertNotNull(v1.map(v2, (one, other) -> one + other / 2.0)); + + assertNotNull(v1.map((val, val1) -> (val + val1), 2.0)); + + assertNotNull(v1.foldMap((sum, val) -> (val + sum), (val) -> val, 0.0)); + + assertNotNull(v1.foldMap(v2, (sum, val) -> (val + sum), (val1, val2) -> val1 + val2, 0.0)); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/package-info.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/package-info.java new file mode 100644 index 0000000..f77e6e32 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/benchmark/package-info.java @@ -0,0 +1,18 @@ +/* + * 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.benchmark; http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/test/java/org/apache/ignite/ml/math/decompositions/CholeskyDecompositionTest.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/decompositions/CholeskyDecompositionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/decompositions/CholeskyDecompositionTest.java new file mode 100644 index 0000000..be03cb1 --- /dev/null +++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/decompositions/CholeskyDecompositionTest.java @@ -0,0 +1,158 @@ +/* + * 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.decompositions; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.exceptions.CardinalityException; +import org.apache.ignite.ml.math.exceptions.NonPositiveDefiniteMatrixException; +import org.apache.ignite.ml.math.exceptions.NonSymmetricMatrixException; +import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix; +import org.apache.ignite.ml.math.impls.matrix.PivotedMatrixView; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** */ +public class CholeskyDecompositionTest { + /** */ + @Test + public void basicTest() { + basicTest(new DenseLocalOnHeapMatrix(new double[][] { + {2.0d, -1.0d, 0.0d}, + {-1.0d, 2.0d, -1.0d}, + {0.0d, -1.0d, 2.0d} + })); + } + + /** + * Test for {@link DecompositionSupport} features. + */ + @Test + public void decompositionSupportTest() { + basicTest(new PivotedMatrixView(new DenseLocalOnHeapMatrix(new double[][] { + {2.0d, -1.0d, 0.0d}, + {-1.0d, 2.0d, -1.0d}, + {0.0d, -1.0d, 2.0d} + }))); + } + + /** */ + @Test(expected = AssertionError.class) + public void nullMatrixTest() { + new CholeskyDecomposition(null); + } + + /** */ + @Test(expected = CardinalityException.class) + public void wrongMatrixSizeTest() { + new CholeskyDecomposition(new DenseLocalOnHeapMatrix(2, 3)); + } + + /** */ + @Test(expected = NonSymmetricMatrixException.class) + public void nonSymmetricMatrixTest() { + new CholeskyDecomposition(new DenseLocalOnHeapMatrix(new double[][] { + {2.0d, -1.0d, 10.0d}, + {-1.0d, 2.0d, -1.0d}, + {-10.0d, -1.0d, 2.0d} + })); + } + + /** */ + @Test(expected = NonPositiveDefiniteMatrixException.class) + public void nonAbsPositiveMatrixTest() { + new CholeskyDecomposition(new DenseLocalOnHeapMatrix(new double[][] { + {2.0d, -1.0d, 0.0d}, + {-1.0d, 0.0d, -1.0d}, + {0.0d, -1.0d, 2.0d} + })); + } + + /** */ + @Test(expected = CardinalityException.class) + public void solveWrongVectorSizeTest() { + new CholeskyDecomposition(new DenseLocalOnHeapMatrix(new double[][] { + {2.0d, -1.0d, 0.0d}, + {-1.0d, 2.0d, -1.0d}, + {0.0d, -1.0d, 2.0d} + })).solve(new DenseLocalOnHeapVector(2)); + } + + /** */ + @Test(expected = CardinalityException.class) + public void solveWrongMatrixSizeTest() { + new CholeskyDecomposition(new DenseLocalOnHeapMatrix(new double[][] { + {2.0d, -1.0d, 0.0d}, + {-1.0d, 2.0d, -1.0d}, + {0.0d, -1.0d, 2.0d} + })).solve(new DenseLocalOnHeapMatrix(2, 3)); + } + + /** */ + private void basicTest(Matrix m) { + // This decomposition is useful when dealing with systems of linear equations of the form + // m x = b where m is a Hermitian matrix. + // For such systems Cholesky decomposition provides + // more effective method of solving compared to LU decomposition. + // Suppose we want to solve system + // m x = b for various bs. Then after we computed Cholesky decomposition, we can feed various bs + // as a matrix of the form + // (b1, b2, ..., bm) + // to the method Cholesky::solve which returns solutions in the form + // (sol1, sol2, ..., solm) + CholeskyDecomposition dec = new CholeskyDecomposition(m); + assertEquals("Unexpected value for decomposition determinant.", + 4d, dec.getDeterminant(), 0d); + + Matrix l = dec.getL(); + Matrix lt = dec.getLT(); + + assertNotNull("Matrix l is expected to be not null.", l); + assertNotNull("Matrix lt is expected to be not null.", lt); + + for (int row = 0; row < l.rowSize(); row++) + for (int col = 0; col < l.columnSize(); col++) + assertEquals("Unexpected value transposed matrix at (" + row + "," + col + ").", + l.get(row, col), lt.get(col, row), 0d); + + Matrix bs = new DenseLocalOnHeapMatrix(new double[][] { + {4.0, -6.0, 7.0}, + {1.0, 1.0, 1.0} + }).transpose(); + Matrix sol = dec.solve(bs); + + assertNotNull("Solution matrix is expected to be not null.", sol); + assertEquals("Solution rows are not as expected.", bs.rowSize(), sol.rowSize()); + assertEquals("Solution columns are not as expected.", bs.columnSize(), sol.columnSize()); + + for (int i = 0; i < sol.columnSize(); i++) + assertNotNull("Solution matrix column is expected to be not null at index " + i, sol.viewColumn(i)); + + Vector b = new DenseLocalOnHeapVector(new double[] {4.0, -6.0, 7.0}); + Vector solVec = dec.solve(b); + + for (int idx = 0; idx < b.size(); idx++) + assertEquals("Unexpected value solution vector at " + idx, + b.get(idx), solVec.get(idx), 0d); + + dec.destroy(); + } +}