You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2017/07/25 17:20:58 UTC
[2/2] ignite git commit: IGNITE-5278: BLAS implemented.
IGNITE-5278: BLAS implemented.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/de259fff
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/de259fff
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/de259fff
Branch: refs/heads/master
Commit: de259fffb7fa5c0f8f6f7eeb84b86f296fe3bde9
Parents: 1318472
Author: Yury Babak <yb...@gridgain.com>
Authored: Tue Jul 25 20:19:27 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Tue Jul 25 20:19:27 2017 +0300
----------------------------------------------------------------------
LICENSE | 7 +
.../ml/math/matrix/ExampleMatrixStorage.java | 6 +-
modules/ml/README.txt | 6 +
modules/ml/licenses/bsd3.txt | 51 ++
modules/ml/pom.xml | 22 +
.../java/org/apache/ignite/ml/math/Blas.java | 484 +++++++++++++++++++
.../java/org/apache/ignite/ml/math/Matrix.java | 31 ++
.../apache/ignite/ml/math/MatrixStorage.java | 2 +-
.../apache/ignite/ml/math/OrderedMatrix.java | 24 +
.../java/org/apache/ignite/ml/math/Vector.java | 8 +
.../decompositions/CholeskyDecomposition.java | 11 +-
.../IgniteIntDoubleToDoubleBiFunction.java | 27 ++
.../functions/IgniteIntIntToIntBiFunction.java | 27 ++
.../ml/math/functions/IgniteTriFunction.java | 35 ++
.../ml/math/impls/matrix/AbstractMatrix.java | 94 +++-
.../impls/matrix/DenseLocalOnHeapMatrix.java | 61 ++-
.../impls/matrix/SparseLocalOnHeapMatrix.java | 27 ++
.../storage/matrix/ArrayMatrixStorage.java | 78 ++-
.../matrix/DenseOffHeapMatrixStorage.java | 2 +-
.../storage/matrix/MatrixDelegateStorage.java | 2 +-
.../matrix/SparseDistributedMatrixStorage.java | 4 +-
.../matrix/SparseLocalOnHeapMatrixStorage.java | 18 +
.../vector/SparseLocalOnHeapVectorStorage.java | 6 +
.../impls/vector/AbstractReadOnlyVector.java | 6 +
.../ml/math/impls/vector/AbstractVector.java | 8 +
.../ml/math/impls/vector/DelegatingVector.java | 6 +
.../ml/math/impls/vector/SparseLocalVector.java | 39 ++
.../apache/ignite/ml/math/util/MatrixUtil.java | 48 ++
.../KMeansDistributedClustererTest.java | 15 +-
.../org/apache/ignite/ml/math/BlasTest.java | 357 ++++++++++++++
.../ignite/ml/math/MathImplMainTestSuite.java | 3 +-
.../impls/matrix/MatrixViewConstructorTest.java | 2 +-
.../storage/matrix/MatrixArrayStorageTest.java | 6 +-
33 files changed, 1475 insertions(+), 48 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index c971434..6e77825 100644
--- a/LICENSE
+++ b/LICENSE
@@ -220,6 +220,13 @@ This product bundles SnapTree, which is available under a
https://github.com/nbronson/snaptree/blob/master/LICENSE.
==============================================================================
+For netlib-java:
+==============================================================================
+This product bundles netlib-java, which is available under a
+"3-clause BSD" license. For details, see
+https://github.com/fommil/netlib-java/blob/master/LICENSE.txt.
+
+==============================================================================
For JSR 166 classes in "org.jsr166" package
==============================================================================
This product bundles JSR-166 classes which are donated to public domain.
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
----------------------------------------------------------------------
diff --git a/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java b/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
index 5dedfbf..1ccb2e2 100644
--- a/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
+++ b/examples/src/main/ml/org/apache/ignite/examples/ml/math/matrix/ExampleMatrixStorage.java
@@ -23,7 +23,9 @@ import java.io.ObjectOutput;
import java.util.Arrays;
import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
import org.apache.ignite.ml.math.impls.storage.matrix.ArrayMatrixStorage;
+import org.apache.ignite.ml.math.util.MatrixUtil;
/**
* Example matrix storage implementation, modeled after {@link ArrayMatrixStorage}.
@@ -117,8 +119,8 @@ class ExampleMatrixStorage implements MatrixStorage {
}
/** {@inheritDoc} */
- @Override public double[][] data() {
- return data;
+ @Override public double[] data() {
+ return MatrixUtil.flatten(data, StorageConstants.ROW_STORAGE_MODE);
}
/** {@inheritDoc */
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/README.txt
----------------------------------------------------------------------
diff --git a/modules/ml/README.txt b/modules/ml/README.txt
index e0cc093..e85b7a0 100644
--- a/modules/ml/README.txt
+++ b/modules/ml/README.txt
@@ -12,4 +12,10 @@ Based on ideas from Apache Mahout.
Run from project root:
mvn clean package -Pml -DskipTests -pl modules/ml -am
+Apache binary releases cannot include LGPL dependencies. If you would like to activate native BLAS optimizations
+into your build, you should download the source release
+from Ignite website and do the build with the following maven command:
+
+mvn clean package -Pml,lgpl -DskipTests -pl modules/ml -am
+
Find generated jars in target folder.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/licenses/bsd3.txt
----------------------------------------------------------------------
diff --git a/modules/ml/licenses/bsd3.txt b/modules/ml/licenses/bsd3.txt
new file mode 100644
index 0000000..d6b30c1
--- /dev/null
+++ b/modules/ml/licenses/bsd3.txt
@@ -0,0 +1,51 @@
+This product binaries redistribute netlib-java which is available under the following license:
+
+Copyright (c) 2013 Samuel Halliday
+Copyright (c) 1992-2011 The University of Tennessee and The University
+ of Tennessee Research Foundation. All rights
+ reserved.
+Copyright (c) 2000-2011 The University of California Berkeley. All
+ rights reserved.
+Copyright (c) 2006-2011 The University of Colorado Denver. All rights
+ reserved.
+
+$COPYRIGHT$
+
+Additional copyrights may follow
+
+$HEADER$
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer listed
+ in this license in the documentation and/or other materials
+ provided with the distribution.
+
+- Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+The copyright holders provide no reassurances that the source code
+provided does not infringe any patent, copyright, or any other
+intellectual property rights of third parties. The copyright holders
+disclaim any liability to any recipient for claims brought against
+recipient by any third party for infringement of that parties
+intellectual property rights.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/pom.xml
----------------------------------------------------------------------
diff --git a/modules/ml/pom.xml b/modules/ml/pom.xml
index d619719..478d8c4 100644
--- a/modules/ml/pom.xml
+++ b/modules/ml/pom.xml
@@ -36,6 +36,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <netlibjava.version>1.1.2</netlibjava.version>
</properties>
<dependencies>
@@ -88,6 +89,13 @@
</dependency>
<dependency>
+ <groupId>com.github.fommil.netlib</groupId>
+ <artifactId>core</artifactId>
+ <version>${netlibjava.version}</version>
+ <type>pom</type>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-rng-core</artifactId>
<version>1.0</version>
@@ -101,6 +109,20 @@
</dependencies>
+ <profiles>
+ <profile>
+ <id>lgpl</id>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.github.fommil.netlib</groupId>
+ <artifactId>all</artifactId>
+ <version>${netlibjava.version}</version>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
<build>
<plugins>
<plugin>
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java
new file mode 100644
index 0000000..57f994e
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/Blas.java
@@ -0,0 +1,484 @@
+/*
+ * 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 com.github.fommil.netlib.BLAS;
+import com.github.fommil.netlib.F2jBLAS;
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.ints.IntIterator;
+import it.unimi.dsi.fastutil.ints.IntSet;
+import java.util.Set;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
+import org.apache.ignite.ml.math.exceptions.NonSquareMatrixException;
+import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrix;
+import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
+import org.apache.ignite.ml.math.impls.vector.SparseLocalVector;
+
+/**
+ * Useful subset of BLAS operations.
+ * This class is based on 'BLAS' class from Apache Spark MLlib.
+ */
+public class Blas {
+ /** F2J implementation of BLAS. */
+ transient static private BLAS f2jBlas = new F2jBLAS();
+
+ /** Native implementation of BLAS. F2J implementation will be used as fallback if no native implementation is found
+ */
+ transient static private BLAS nativeBlas = BLAS.getInstance();
+
+ /**
+ * Performs y += a * x
+ *
+ * @param a Scalar a.
+ * @param x Vector x.
+ * @param y Vector y.
+ */
+ public static void axpy(Double a, Vector x, Vector y) {
+ if (x.size() != y.size())
+ throw new CardinalityException(x.size(), y.size());
+
+ if (x.isArrayBased() && y.isArrayBased())
+ axpy(a, x.getStorage().data(), y.getStorage().data());
+ else if (x instanceof SparseLocalVector && y.isArrayBased())
+ axpy(a, (SparseLocalVector)x, y.getStorage().data());
+ else
+ throw new MathIllegalArgumentException("Operation 'axpy' doesn't support this combination of parameters [x="
+ + x.getClass().getName() + ", y="+y.getClass().getName()+"].");
+ }
+
+ /** */
+ private static void axpy(Double a, double[] x, double[] y) {
+ f2jBlas.daxpy(x.length, a, x, 1, y, 1);
+ }
+
+ /** */
+ private static void axpy(Double a, SparseLocalVector x, double[] y) {
+ int xSize = x.size();
+
+ if (a == 1.0) {
+ int k = 0;
+
+ while (k < xSize) {
+ y[k] += x.getX(k);
+ k++;
+ }
+ } else {
+ int k = 0;
+
+ while (k < xSize) {
+ y[k] += a * x.getX(k);
+ k++;
+ }
+ }
+ }
+
+ /**
+ * Returns dot product of vectors x and y.
+ *
+ * @param x Vector x.
+ * @param y Vector y.
+ * @return Dot product of x and y.
+ **/
+ public static Double dot(Vector x, Vector y) {
+ return x.dot(y);
+ }
+
+ /**
+ * Copies Vector x into Vector y. (y = x)
+ *
+ * @param x Vector x.
+ * @param y Vector y.
+ */
+ public void copy(Vector x, Vector y) {
+ int n = y.size();
+
+ if (x.size() != n)
+ throw new CardinalityException(x.size(), n);
+
+ if (y.isArrayBased()) {
+ double[] yData = y.getStorage().data();
+
+ if (x.isArrayBased())
+ System.arraycopy(x.getStorage().data(), 0, y.getStorage().data(), 0, n);
+ else {
+ if (y instanceof SparseLocalVector) {
+ for (int i = 0; i < n; i++)
+ yData[i] = x.getX(i);
+ }
+ }
+ } else
+ throw new IllegalArgumentException("Vector y must be array based in copy.");
+ }
+
+
+ /**
+ * Performs in-place multiplication of vector x by a real scalar a. (x = a * x)
+ *
+ * @param a Scalar a.
+ * @param x Vector x.
+ **/
+ public static void scal(Double a, Vector x) {
+ if (x.isArrayBased())
+ f2jBlas.dscal(x.size(), a, x.getStorage().data(), 1);
+ else if (x instanceof SparseLocalVector) {
+ Set<Integer> indexes = ((SparseLocalVector)x).indexes();
+
+ for (Integer i : indexes)
+ x.compute(i, (ind, v) -> v * a);
+ } else
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Adds alpha * v * v.t to a matrix in-place. This is the same as BLAS's ?SPR.
+ *
+ * @param u the upper triangular part of the matrix in a [[DenseVector]](column major)
+ */
+ public static void spr(Double alpha, DenseLocalOnHeapVector v, DenseLocalOnHeapVector u) {
+ nativeBlas.dspr("U", v.size(), alpha, v.getStorage().data(), 1, u.getStorage().data());
+ }
+
+ /** */
+ public static void spr(Double alpha, SparseLocalVector v, DenseLocalOnHeapVector u) {
+ int prevNonDfltInd = 0;
+ int startInd = 0;
+ double av;
+ double[] uData = u.getStorage().data();
+
+ for (Integer nonDefaultInd : v.indexes()) {
+ startInd += (nonDefaultInd - prevNonDfltInd) * (nonDefaultInd + prevNonDfltInd + 1) / 2;
+ av = alpha * v.get(nonDefaultInd);
+
+ for (Integer i : v.indexes())
+ if (i <= nonDefaultInd)
+ uData[startInd + i] += av * v.getX(i);
+
+ prevNonDfltInd = nonDefaultInd;
+ }
+ }
+
+ /**
+ * A := alpha * x * x^T + A
+ * @param alpha a real scalar that will be multiplied to x * x^T^.
+ * @param x the vector x that contains the n elements.
+ * @param a the symmetric matrix A. Size of n x n.
+ */
+ void syr(Double alpha, Vector x, DenseLocalOnHeapMatrix a) {
+ int mA = a.rowSize();
+ int nA = a.columnSize();
+
+ if (mA != nA)
+ throw new NonSquareMatrixException(mA, nA);
+
+ if (mA != x.size())
+ throw new CardinalityException(x.size(), mA);
+
+ // TODO: IGNITE-5535, Process DenseLocalOffHeapVector
+ if (x instanceof DenseLocalOnHeapVector)
+ syr(alpha, x, a);
+ else if (x instanceof SparseLocalVector)
+ syr(alpha, x, a);
+ else
+ throw new IllegalArgumentException("Operation 'syr' does not support vector [class="
+ + x.getClass().getName() + "].");
+ }
+
+ /** */
+ static void syr(Double alpha, DenseLocalOnHeapVector x, DenseLocalOnHeapMatrix a) {
+ int nA = a.rowSize();
+ int mA = a.columnSize();
+
+ nativeBlas.dsyr("U", x.size(), alpha, x.getStorage().data(), 1, a.getStorage().data(), nA);
+
+ // Fill lower triangular part of A
+ int i = 0;
+ while (i < mA) {
+ int j = i + 1;
+
+ while (j < nA) {
+ a.setX(i, j, a.getX(j, i));
+ j++;
+ }
+ i++;
+ }
+ }
+
+ /** */
+ public static void syr(Double alpha, SparseLocalVector x, DenseLocalOnHeapMatrix a) {
+ int mA = a.columnSize();
+
+ for (Integer i : x.indexes()) {
+ double mult = alpha * x.getX(i);
+ for (Integer j : x.indexes())
+ a.getStorage().data()[mA * i + j] += mult * x.getX(j);
+ }
+ }
+
+ /**
+ * For the moment we have no flags indicating if matrix is transposed or not. Therefore all dgemm parameters for
+ * transposition are equal to 'N'.
+ */
+ public static void gemm(Double alpha, Matrix a, DenseLocalOnHeapMatrix b, Double beta, DenseLocalOnHeapMatrix c) {
+ if (alpha == 0.0 && beta == 1.0)
+ return;
+ else if (alpha == 0.0)
+ scal(c, beta);
+ else {
+ if (a instanceof SparseLocalOnHeapMatrix)
+ gemm(alpha, (SparseLocalOnHeapMatrix)a, b, beta, c);
+ else if (a instanceof DenseLocalOnHeapMatrix) {
+ double[] fA = a.getStorage().data();
+ double[] fB = b.getStorage().data();
+ double[] fC = c.getStorage().data();
+
+ nativeBlas.dgemm("N", "N", a.rowSize(), b.columnSize(), a.columnSize(), alpha, fA,
+ a.rowSize(), fB, b.rowSize(), beta, fC, c.rowSize());
+ } else
+ throw new IllegalArgumentException("Operation 'gemm' doesn't support for matrix [class="
+ + a.getClass().getName() + "].");
+ }
+ }
+
+ /**
+ * C := alpha * A * B + beta * C
+ * For `SparseMatrix` A.
+ */
+ private static void gemm(Double alpha, SparseLocalOnHeapMatrix a, DenseLocalOnHeapMatrix b, Double beta,
+ DenseLocalOnHeapMatrix c) {
+ int mA = a.rowSize();
+ int nB = b.columnSize();
+ int kA = a.columnSize();
+ int kB = b.rowSize();
+
+ if (kA != kB)
+ throw new CardinalityException(kA, kB);
+
+ if (mA != c.rowSize())
+ throw new CardinalityException(mA, c.rowSize());
+
+ if (nB != c.columnSize())
+ throw new CardinalityException(nB, c.columnSize());
+
+ if (beta != 1.0)
+ scal(c, beta);
+
+ Int2ObjectArrayMap<IntSet> im = a.indexesMap();
+ IntIterator rowsIter = im.keySet().iterator();
+ int row;
+ // We use here this form of iteration instead of 'for' because of nextInt.
+ while (rowsIter.hasNext()) {
+ row = rowsIter.nextInt();
+
+ for (int colInd = 0; colInd < nB; colInd++) {
+ double sum = 0.0;
+
+ IntIterator kIter = im.get(row).iterator();
+ int k;
+
+ while (kIter.hasNext()) {
+ k = kIter.nextInt();
+ sum += a.get(row, k) * b.get(k, colInd) * alpha;
+ }
+
+ c.setX(row, colInd, c.getX(row, colInd) + sum);
+ }
+ }
+ }
+
+ /**
+ * y := alpha * A * x + beta * y.
+ *
+ * @param alpha Alpha.
+ * @param a Matrix a.
+ * @param x Vector x.
+ * @param beta Beta.
+ * @param y Vector y.
+ */
+ public static void gemv(double alpha, Matrix a, Vector x, double beta, DenseLocalOnHeapVector y) {
+ checkCardinality(a, x);
+ checkCardinality(a, y);
+
+ if (alpha == 0.0 && beta == 1.0)
+ return;
+
+ if (alpha == 0.0) {
+ scal(y, beta);
+ return;
+ }
+
+ if (a instanceof SparseLocalOnHeapMatrix && x instanceof DenseLocalOnHeapVector)
+ gemv(alpha, (SparseLocalOnHeapMatrix)a, (DenseLocalOnHeapVector)x, beta, y);
+ else if (a instanceof SparseLocalOnHeapMatrix && x instanceof SparseLocalVector)
+ gemv(alpha, (SparseLocalOnHeapMatrix)a, (SparseLocalVector)x, beta, y);
+ else if (a instanceof DenseLocalOnHeapMatrix && x instanceof DenseLocalOnHeapVector)
+ gemv(alpha, (DenseLocalOnHeapMatrix)a, (DenseLocalOnHeapVector)x, beta, y);
+ else if (a instanceof DenseLocalOnHeapMatrix && x instanceof SparseLocalVector)
+ gemv(alpha, (DenseLocalOnHeapMatrix)a, (SparseLocalVector)x, beta, y);
+ else
+ throw new IllegalArgumentException("Operation gemv doesn't support running thist input [matrix=" +
+ a.getClass().getSimpleName() + ", vector=" + x.getClass().getSimpleName()+"].");
+ }
+
+ /**
+ * y := alpha * A * x + beta * y.
+ *
+ * @param alpha Alpha.
+ * @param a Matrix a.
+ * @param x Vector x.
+ * @param beta Beta.
+ * @param y Vector y.
+ */
+ private static void gemv(double alpha, SparseLocalOnHeapMatrix a, DenseLocalOnHeapVector x, double beta,
+ DenseLocalOnHeapVector y) {
+
+ if (beta != 1.0)
+ scal(y, beta);
+
+ IntIterator rowIter = a.indexesMap().keySet().iterator();
+ while (rowIter.hasNext()) {
+ int row = rowIter.nextInt();
+
+ double sum = 0.0;
+ IntIterator colIter = a.indexesMap().get(row).iterator();
+ while (colIter.hasNext()) {
+ int col = colIter.nextInt();
+ sum += alpha * a.getX(row, col) * x.getX(col);
+ }
+
+ y.setX(row, y.getX(row) + sum);
+ }
+ }
+
+ /**
+ * y := alpha * A * x + beta * y.
+ *
+ * @param alpha Alpha.
+ * @param a Matrix a.
+ * @param x Vector x.
+ * @param beta Beta.
+ * @param y Vector y.
+ */
+ private static void gemv(double alpha, DenseLocalOnHeapMatrix a, DenseLocalOnHeapVector x, double beta,
+ DenseLocalOnHeapVector y) {
+ nativeBlas.dgemv("N", a.rowSize(), a.columnSize(), alpha, a.getStorage().data(), a.rowSize(), x.getStorage().data(), 1, beta,
+ y.getStorage().data(), 1);
+ }
+
+ /**
+ * y := alpha * A * x + beta * y.
+ *
+ * @param alpha Alpha.
+ * @param a Matrix a.
+ * @param x Vector x.
+ * @param beta Beta.
+ * @param y Vector y.
+ */
+ private static void gemv(double alpha, SparseLocalOnHeapMatrix a, SparseLocalVector x, double beta,
+ DenseLocalOnHeapVector y) {
+
+
+ if (beta != 1.0)
+ scal(y, beta);
+
+ IntIterator rowIter = a.indexesMap().keySet().iterator();
+ while (rowIter.hasNext()) {
+ int row = rowIter.nextInt();
+
+ double sum = 0.0;
+ IntIterator colIter = a.indexesMap().get(row).iterator();
+ while (colIter.hasNext()) {
+ int col = colIter.nextInt();
+
+ sum += alpha * a.getX(row, col) * x.getX(col);
+ }
+
+ y.set(row, y.get(row) + sum);
+ }
+ }
+
+ /**
+ * y := alpha * A * x + beta * y.
+ *
+ * @param alpha Alpha.
+ * @param a Matrix a.
+ * @param x Vector x.
+ * @param beta Beta.
+ * @param y Vector y.
+ */
+ private static void gemv(double alpha, DenseLocalOnHeapMatrix a, SparseLocalVector x, double beta,
+ DenseLocalOnHeapVector y) {
+ int rowCntrForA = 0;
+ int mA = a.rowSize();
+
+ double[] aData = a.getStorage().data();
+
+ IntSet indexes = x.indexes();
+
+ double[] yValues = y.getStorage().data();
+
+ while (rowCntrForA < mA) {
+ double sum = 0.0;
+
+ IntIterator iter = indexes.iterator();
+ while (iter.hasNext()) {
+ int xIdx = iter.nextInt();
+ sum += x.getX(xIdx) * aData[xIdx * mA + rowCntrForA];
+ }
+
+ yValues[rowCntrForA] = sum * alpha + beta * yValues[rowCntrForA];
+ rowCntrForA++;
+ }
+ }
+
+ /**
+ * M := alpha * M.
+ * @param m Matrix M.
+ * @param alpha Aplha.
+ */
+ private static void scal(Matrix m, double alpha) {
+ if (alpha != 1.0)
+ for (int i = 0; i < m.rowSize(); i++)
+ for (int j = 0; j < m.columnSize(); j++)
+ m.setX(i, j, m.getX(i, j) * alpha);
+
+ }
+
+ /**
+ * v := alpha * v.
+ * @param v Vector v.
+ * @param alpha Aplha.
+ */
+ private static void scal(Vector v, double alpha) {
+ if (alpha != 1.0)
+ for (int i = 0; i < v.size(); i++)
+ v.compute(i, (ind, val) -> val * alpha);
+ }
+
+ /**
+ * Checks if Matrix A can be multiplied by vector v, if not CardinalityException is thrown.
+ *
+ * @param a Matrix A.
+ * @param v Vector v.
+ */
+ public static void checkCardinality(Matrix a, Vector v) throws CardinalityException {
+ if (a.columnSize() != v.size())
+ throw new CardinalityException(a.columnSize(), v.size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
index 2cf4e63..66de1a1 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/Matrix.java
@@ -18,6 +18,7 @@
package org.apache.ignite.ml.math;
import java.io.Externalizable;
+import java.util.Spliterator;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.ml.math.exceptions.CardinalityException;
import org.apache.ignite.ml.math.exceptions.IndexException;
@@ -25,6 +26,7 @@ import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
import org.apache.ignite.ml.math.functions.IgniteFunction;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction;
/**
@@ -187,6 +189,27 @@ public interface Matrix extends MetaAttributes, Externalizable, StorageOpsMetric
public Matrix map(Matrix mtx, IgniteBiFunction<Double, Double, Double> fun);
/**
+ * Gets number of non-zero elements in this matrix.
+ *
+ * @return Number of non-zero elements in this matrix.
+ */
+ public int nonZeroElements();
+
+ /**
+ * Gets spliterator for all values in this matrix.
+ *
+ * @return Spliterator for all values.
+ */
+ public Spliterator<Double> allSpliterator();
+
+ /**
+ * Gets spliterator for all non-zero values in this matrix.
+ *
+ * @return Spliterator for all non-zero values.
+ */
+ public Spliterator<Double> nonZeroSpliterator();
+
+ /**
* Assigns values from given vector to the specified column in this matrix.
*
* @param col Column index.
@@ -515,4 +538,12 @@ public interface Matrix extends MetaAttributes, Externalizable, StorageOpsMetric
public default void destroy() {
// No-op.
}
+
+ /**
+ * Replace matrix entry with value oldVal at (row, col) with result of computing f(row, col, oldVal).
+ * @param row Row.
+ * @param col Column.
+ * @param f Function used for replacing.
+ */
+ public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
index ccfebe5..3b905bc 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/MatrixStorage.java
@@ -52,7 +52,7 @@ public interface MatrixStorage extends Externalizable, StorageOpsMetrics, Destro
*
* @see StorageOpsMetrics#isArrayBased()
*/
- default public double[][] data() {
+ default public double[] data() {
return null;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java
new file mode 100644
index 0000000..2c3acc8
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/OrderedMatrix.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+/** Interface for matrix with particular order for storing entities. */
+public interface OrderedMatrix {
+ /** Get access mode. */
+ public int accessMode();
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
index e1c5df0..5fd39af 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/Vector.java
@@ -26,6 +26,7 @@ import org.apache.ignite.ml.math.exceptions.IndexException;
import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
/**
* A vector interface.
@@ -496,4 +497,11 @@ public interface Vector extends MetaAttributes, Externalizable, StorageOpsMetric
* @return Vector GUID.
*/
public IgniteUuid guid();
+
+ /**
+ * Replace vector entry with value oldVal at i with result of computing f(i, oldVal).
+ * @param i Position.
+ * @param f Function used for replacing.
+ **/
+ public void compute(int i, IgniteIntDoubleToDoubleBiFunction f);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
index 84028fe..73fbe2c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/decompositions/CholeskyDecomposition.java
@@ -23,6 +23,7 @@ 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.util.MatrixUtil;
import static org.apache.ignite.ml.math.util.MatrixUtil.like;
import static org.apache.ignite.ml.math.util.MatrixUtil.likeVector;
@@ -252,7 +253,7 @@ public class CholeskyDecomposition implements Destroyable {
throw new CardinalityException(b.rowSize(), m);
final int nColB = b.columnSize();
- final double[][] x = b.getStorage().data();
+ final double[][] x = MatrixUtil.unflatten(b.getStorage().data(), b.columnSize());
// Solve LY = b
for (int j = 0; j < m; j++) {
@@ -295,15 +296,13 @@ public class CholeskyDecomposition implements Destroyable {
/** */
private double[][] toDoubleArr(Matrix mtx) {
if (mtx.isArrayBased())
- return mtx.getStorage().data();
+ return MatrixUtil.unflatten(mtx.getStorage().data(), mtx.columnSize());
- double[][] res = new double[mtx.rowSize()][];
+ double[][] res = new double[mtx.rowSize()][mtx.columnSize()];
- for (int row = 0; row < mtx.rowSize(); row++) {
- res[row] = new double[mtx.columnSize()];
+ for (int row = 0; row < mtx.rowSize(); row++)
for (int col = 0; col < mtx.columnSize(); col++)
res[row][col] = mtx.get(row, col);
- }
return res;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java
new file mode 100644
index 0000000..c9a91ae
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntDoubleToDoubleBiFunction.java
@@ -0,0 +1,27 @@
+/*
+ * 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.functions;
+
+import java.io.Serializable;
+
+/** BiFunction (int, double) -> double. */
+@FunctionalInterface
+public interface IgniteIntDoubleToDoubleBiFunction extends Serializable {
+ /** */
+ public double apply(int x, double d);
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java
new file mode 100644
index 0000000..bfd472c
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteIntIntToIntBiFunction.java
@@ -0,0 +1,27 @@
+/*
+ * 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.functions;
+
+import java.io.Serializable;
+
+/** BiFunction (int, int) -> int. */
+@FunctionalInterface
+public interface IgniteIntIntToIntBiFunction extends Serializable {
+ /** */
+ public int apply(int x, int y);
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java
new file mode 100644
index 0000000..3284a00
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteTriFunction.java
@@ -0,0 +1,35 @@
+/*
+ * 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.functions;
+
+import java.io.Serializable;
+import java.util.Objects;
+import java.util.function.Function;
+
+/** Serializable TriFunction (A, B, C) -> R. */
+@FunctionalInterface
+public interface IgniteTriFunction<A,B,C,R> extends Serializable {
+ /** */
+ R apply(A a, B b, C c);
+
+ /** */
+ default <V> IgniteTriFunction<A, B, C, V> andThen(Function<? super R, ? extends V> after) {
+ Objects.requireNonNull(after);
+ return (A a, B b, C c) -> after.apply(apply(a, b, c));
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
index 647ebc6..e1efd0c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
@@ -24,6 +24,8 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
+import java.util.Spliterator;
+import java.util.function.Consumer;
import org.apache.ignite.lang.IgniteUuid;
import org.apache.ignite.ml.math.Matrix;
import org.apache.ignite.ml.math.MatrixStorage;
@@ -36,6 +38,7 @@ import org.apache.ignite.ml.math.functions.Functions;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
import org.apache.ignite.ml.math.functions.IgniteFunction;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction;
import org.apache.ignite.ml.math.impls.vector.MatrixVectorView;
@@ -326,8 +329,7 @@ public abstract class AbstractMatrix implements Matrix {
/** {@inheritDoc} */
@Override public Matrix assign(double val) {
if (sto.isArrayBased())
- for (double[] column : sto.data())
- Arrays.fill(column, val);
+ Arrays.fill(sto.data(), val);
else {
int rows = rowSize();
int cols = columnSize();
@@ -421,6 +423,85 @@ public abstract class AbstractMatrix implements Matrix {
}
/** {@inheritDoc} */
+ @Override public Spliterator<Double> allSpliterator() {
+ return new Spliterator<Double>() {
+ /** {@inheritDoc} */
+ @Override public boolean tryAdvance(Consumer<? super Double> act) {
+ int rLen = rowSize();
+ int cLen = columnSize();
+
+ for (int i = 0; i < rLen; i++)
+ for (int j = 0; j < cLen; j++)
+ act.accept(storageGet(i, j));
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Spliterator<Double> trySplit() {
+ return null; // No Splitting.
+ }
+
+ /** {@inheritDoc} */
+ @Override public long estimateSize() {
+ return rowSize() * columnSize();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int characteristics() {
+ return ORDERED | SIZED;
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
+ @Override public int nonZeroElements() {
+ int cnt = 0;
+
+ for (int i = 0; i < rowSize(); i++)
+ for (int j = 0; j < rowSize(); j++)
+ if (get(i, j) != 0.0)
+ cnt++;
+
+ return cnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Spliterator<Double> nonZeroSpliterator() {
+ return new Spliterator<Double>() {
+ /** {@inheritDoc} */
+ @Override public boolean tryAdvance(Consumer<? super Double> act) {
+ int rLen = rowSize();
+ int cLen = columnSize();
+
+ for (int i = 0; i < rLen; i++)
+ for (int j = 0; j < cLen; j++) {
+ double val = storageGet(i, j);
+
+ if (val != 0.0)
+ act.accept(val);
+ }
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Spliterator<Double> trySplit() {
+ return null; // No Splitting.
+ }
+
+ /** {@inheritDoc} */
+ @Override public long estimateSize() {
+ return nonZeroElements();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int characteristics() {
+ return ORDERED | SIZED;
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
@Override public Matrix assignColumn(int col, Vector vec) {
checkColumnIndex(col);
@@ -442,7 +523,7 @@ public abstract class AbstractMatrix implements Matrix {
throw new CardinalityException(cols, vec.size());
if (sto.isArrayBased() && vec.getStorage().isArrayBased())
- System.arraycopy(vec.getStorage().data(), 0, sto.data()[row], 0, cols);
+ System.arraycopy(vec.getStorage().data(), 0, sto.data(), cols * row, cols);
else
for (int y = 0; y < cols; y++)
storageSet(row, y, vec.getX(y));
@@ -623,7 +704,7 @@ public abstract class AbstractMatrix implements Matrix {
throw new CardinalityException(cols, data.length);
if (sto.isArrayBased())
- System.arraycopy(data, 0, sto.data()[row], 0, cols);
+ System.arraycopy(data, 0, sto.data(), row * cols, cols);
else
for (int y = 0; y < cols; y++)
setX(row, y, data[y]);
@@ -880,4 +961,9 @@ public abstract class AbstractMatrix implements Matrix {
return (sto != null ? sto.equals(that.getStorage()) : that.getStorage() == null);
}
+
+ /** {@inheritDoc} */
+ @Override public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
+ setX(row, col, f.apply(row, col, getX(row, col)));
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
index f95e0cc..393fff6 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java
@@ -18,6 +18,8 @@
package org.apache.ignite.ml.math.impls.matrix;
import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.OrderedMatrix;
+import org.apache.ignite.ml.math.StorageConstants;
import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.impls.storage.matrix.ArrayMatrixStorage;
import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
@@ -30,7 +32,7 @@ import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
* local, non-distributed execution is satisfactory and on-heap JVM storage is enough
* to keep the entire data set.
*/
-public class DenseLocalOnHeapMatrix extends AbstractMatrix {
+public class DenseLocalOnHeapMatrix extends AbstractMatrix implements OrderedMatrix {
/**
*
*/
@@ -43,44 +45,89 @@ public class DenseLocalOnHeapMatrix extends AbstractMatrix {
* @param cols Amount of columns in matrix.
*/
public DenseLocalOnHeapMatrix(int rows, int cols) {
+ this(rows, cols, StorageConstants.ROW_STORAGE_MODE);
+ }
+
+ /**
+ * @param rows Amount of rows in matrix.
+ * @param cols Amount of columns in matrix.
+ * @param acsMode Storage order (row or column-based).
+ */
+ public DenseLocalOnHeapMatrix(int rows, int cols, int acsMode) {
assert rows > 0;
assert cols > 0;
- setStorage(new ArrayMatrixStorage(rows, cols));
+ setStorage(new ArrayMatrixStorage(rows, cols, acsMode));
+ }
+
+ /**
+ * @param mtx Backing data array.
+ * @param acsMode Access mode.
+ */
+ public DenseLocalOnHeapMatrix(double[][] mtx, int acsMode) {
+ assert mtx != null;
+
+ setStorage(new ArrayMatrixStorage(mtx, acsMode));
}
/**
* @param mtx Backing data array.
*/
public DenseLocalOnHeapMatrix(double[][] mtx) {
+ this(mtx, StorageConstants.ROW_STORAGE_MODE);
+ }
+
+ /**
+ * @param mtx Backing data array.
+ * @param acsMode Access mode.
+ */
+ public DenseLocalOnHeapMatrix(double[] mtx, int rows, int acsMode) {
assert mtx != null;
- setStorage(new ArrayMatrixStorage(mtx));
+ setStorage(new ArrayMatrixStorage(mtx, rows, acsMode));
}
/**
- * @param orig Original matrix.
+ * Build new matrix from flat raw array.
*/
+ public DenseLocalOnHeapMatrix(double[] mtx, int rows) {
+ this(mtx, StorageConstants.ROW_STORAGE_MODE, rows);
+ }
+
+ /** */
private DenseLocalOnHeapMatrix(DenseLocalOnHeapMatrix orig) {
+ this(orig, orig.accessMode());
+ }
+
+ /**
+ * @param orig Original matrix.
+ * @param acsMode Access mode.
+ */
+ private DenseLocalOnHeapMatrix(DenseLocalOnHeapMatrix orig, int acsMode) {
assert orig != null;
- setStorage(new ArrayMatrixStorage(orig.rowSize(), orig.columnSize()));
+ setStorage(new ArrayMatrixStorage(orig.rowSize(), orig.columnSize(), acsMode));
assign(orig);
}
/** {@inheritDoc} */
@Override public Matrix copy() {
- return new DenseLocalOnHeapMatrix(this);
+ return new DenseLocalOnHeapMatrix(this, accessMode());
}
/** {@inheritDoc} */
@Override public Matrix like(int rows, int cols) {
- return new DenseLocalOnHeapMatrix(rows, cols);
+ return new DenseLocalOnHeapMatrix(rows, cols, getStorage() != null ? accessMode() : StorageConstants.ROW_STORAGE_MODE);
}
/** {@inheritDoc} */
@Override public Vector likeVector(int crd) {
return new DenseLocalOnHeapVector(crd);
}
+
+ /** */
+ @Override public int accessMode() {
+ return ((ArrayMatrixStorage)getStorage()).accessMode();
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
index d711295..d0a5937 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseLocalOnHeapMatrix.java
@@ -17,10 +17,14 @@
package org.apache.ignite.ml.math.impls.matrix;
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.ints.IntIterator;
+import it.unimi.dsi.fastutil.ints.IntSet;
import org.apache.ignite.ml.math.Matrix;
import org.apache.ignite.ml.math.MatrixStorage;
import org.apache.ignite.ml.math.StorageConstants;
import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
import org.apache.ignite.ml.math.impls.storage.matrix.SparseLocalOnHeapMatrixStorage;
import org.apache.ignite.ml.math.impls.vector.SparseLocalVector;
@@ -62,6 +66,24 @@ public class SparseLocalOnHeapMatrix extends AbstractMatrix implements StorageCo
}
/** {@inheritDoc} */
+ @Override public int nonZeroElements() {
+ int res = 0;
+ IntIterator rowIter = indexesMap().keySet().iterator();
+
+ while (rowIter.hasNext()) {
+ int row = rowIter.nextInt();
+ res += indexesMap().get(row).size();
+ }
+
+ return res;
+ }
+
+ /** */
+ public Int2ObjectArrayMap<IntSet> indexesMap() {
+ return ((SparseLocalOnHeapMatrixStorage)getStorage()).indexesMap();
+ }
+
+ /** {@inheritDoc} */
@Override public Matrix copy() {
Matrix cp = like(rowSize(), columnSize());
@@ -69,4 +91,9 @@ public class SparseLocalOnHeapMatrix extends AbstractMatrix implements StorageCo
return cp;
}
+
+ /** {@inheritDoc} */
+ @Override public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
+ ((SparseLocalOnHeapMatrixStorage)getStorage()).compute(row, col, f);
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
index 397bf93..1f337fd 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/ArrayMatrixStorage.java
@@ -22,17 +22,24 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Arrays;
import org.apache.ignite.ml.math.MatrixStorage;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.functions.IgniteIntIntToIntBiFunction;
+import org.apache.ignite.ml.math.util.MatrixUtil;
/**
* Array based {@link MatrixStorage} implementation.
*/
public class ArrayMatrixStorage implements MatrixStorage {
/** Backing data array. */
- private double[][] data;
+ private double[] data;
/** Amount of rows in the matrix. */
private int rows;
/** Amount of columns in the matrix. */
private int cols;
+ /** Mode specifying if this matrix is row-major or column-major. */
+ private int acsMode;
+ /** Index mapper */
+ private IgniteIntIntToIntBiFunction idxMapper;
/**
*
@@ -46,32 +53,62 @@ public class ArrayMatrixStorage implements MatrixStorage {
* @param cols Amount of columns in the matrix.
*/
public ArrayMatrixStorage(int rows, int cols) {
+ this(rows, cols, StorageConstants.ROW_STORAGE_MODE);
+ }
+
+ /** */
+ public ArrayMatrixStorage(int rows, int cols, int acsMode) {
assert rows > 0;
assert cols > 0;
- this.data = new double[rows][cols];
+ this.data = new double[rows * cols];
this.rows = rows;
this.cols = cols;
+ idxMapper = indexMapper(acsMode);
+ this.acsMode = acsMode;
+ }
+
+ /**
+ * @param data Backing data array.
+ */
+ public ArrayMatrixStorage(double[][] data, int acsMode) {
+ this(MatrixUtil.flatten(data, acsMode), data.length, acsMode);
}
/**
* @param data Backing data array.
*/
public ArrayMatrixStorage(double[][] data) {
+ this(MatrixUtil.flatten(data, StorageConstants.ROW_STORAGE_MODE), data.length);
+ }
+
+ /**
+ * @param data Backing data array.
+ */
+ public ArrayMatrixStorage(double[] data, int rows, int acsMode) {
assert data != null;
- assert data[0] != null;
+ assert data.length % rows == 0;
this.data = data;
- this.rows = data.length;
- this.cols = data[0].length;
+ this.rows = rows;
+ this.cols = data.length / rows;
+ idxMapper = indexMapper(acsMode);
+ this.acsMode = acsMode;
assert rows > 0;
assert cols > 0;
}
+ /**
+ * @param data Backing data array.
+ */
+ public ArrayMatrixStorage(double[] data, int rows) {
+ this(data, rows, StorageConstants.ROW_STORAGE_MODE);
+ }
+
/** {@inheritDoc} */
@Override public double get(int x, int y) {
- return data[x][y];
+ return data[idxMapper.apply(x, y)];
}
/** {@inheritDoc} */
@@ -96,7 +133,7 @@ public class ArrayMatrixStorage implements MatrixStorage {
/** {@inheritDoc} */
@Override public void set(int x, int y, double v) {
- data[x][y] = v;
+ data[idxMapper.apply(x, y)] = v;
}
/** {@inheritDoc} */
@@ -115,14 +152,25 @@ public class ArrayMatrixStorage implements MatrixStorage {
}
/** {@inheritDoc} */
- @Override public double[][] data() {
+ @Override public double[] data() {
return data;
}
+ /**
+ * Get the index mapper for given access mode.
+ *
+ * @param acsMode Access mode.
+ */
+ private IgniteIntIntToIntBiFunction indexMapper(int acsMode) {
+ return acsMode == StorageConstants.ROW_STORAGE_MODE ? (r, c) -> r * cols + c :
+ (r, c) -> c * rows + r;
+ }
+
/** {@inheritDoc} */
@Override public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(rows);
out.writeInt(cols);
+ out.writeInt(acsMode);
out.writeObject(data);
}
@@ -131,8 +179,15 @@ public class ArrayMatrixStorage implements MatrixStorage {
@Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
rows = in.readInt();
cols = in.readInt();
+ acsMode = in.readInt();
+ idxMapper = indexMapper(acsMode);
+
+ data = (double[])in.readObject();
+ }
- data = (double[][])in.readObject();
+ /** Get the access mode of this storage. */
+ public int accessMode() {
+ return acsMode;
}
/** {@inheritDoc} */
@@ -141,7 +196,8 @@ public class ArrayMatrixStorage implements MatrixStorage {
res += res * 37 + rows;
res += res * 37 + cols;
- res += res * 37 + Arrays.deepHashCode(data);
+ res += res * 37 + acsMode;
+ res += res * 37 + Arrays.hashCode(data);
return res;
}
@@ -156,6 +212,6 @@ public class ArrayMatrixStorage implements MatrixStorage {
ArrayMatrixStorage that = (ArrayMatrixStorage)o;
- return Arrays.deepEquals(data, that.data);
+ return acsMode == that.acsMode && Arrays.equals(data, that.data);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
index 7405a4e..f58da65 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java
@@ -122,7 +122,7 @@ public class DenseOffHeapMatrixStorage implements MatrixStorage {
}
/** {@inheritDoc} */
- @Override public double[][] data() {
+ @Override public double[] data() {
return null;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
index 1f77d0f..f185479 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java
@@ -150,7 +150,7 @@ public class MatrixDelegateStorage implements MatrixStorage {
}
/** {@inheritDoc} */
- @Override public double[][] data() {
+ @Override public double[] data() {
return sto.data();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
index 1513502..fc7d969 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
@@ -116,9 +116,7 @@ public class SparseDistributedMatrixStorage extends CacheUtils implements Matrix
// Random cache name.
cfg.setName(ML_CACHE_NAME);
- IgniteCache<IgniteBiTuple<Integer, IgniteUuid>, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(cfg);
-
- return cache;
+ return Ignition.localIgnite().getOrCreateCache(cfg);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
index b33cb26..daf1d4b 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java
@@ -19,6 +19,8 @@ package org.apache.ignite.ml.math.impls.storage.matrix;
import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
+import it.unimi.dsi.fastutil.ints.IntSet;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
@@ -26,6 +28,7 @@ import java.util.HashMap;
import java.util.Map;
import org.apache.ignite.ml.math.MatrixStorage;
import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.functions.IgniteTriFunction;
/**
* Storage for sparse, local, on-heap matrix.
@@ -225,4 +228,19 @@ public class SparseLocalOnHeapMatrixStorage implements MatrixStorage, StorageCon
return rows == that.rows && cols == that.cols && acsMode == that.acsMode && stoMode == that.stoMode
&& (sto != null ? sto.equals(that.sto) : that.sto == null);
}
+
+ /** */
+ public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
+ sto.get(row).compute(col, (c, val) -> f.apply(row, c, val));
+ }
+
+ /** */
+ public Int2ObjectArrayMap<IntSet> indexesMap() {
+ Int2ObjectArrayMap<IntSet> res = new Int2ObjectArrayMap<>();
+
+ for (Integer row : sto.keySet())
+ res.put(row.intValue(), (IntSet)sto.get(row).keySet());
+
+ return res;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
index deef010..3323a07 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ml.math.impls.storage.vector;
import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
+import it.unimi.dsi.fastutil.ints.IntSet;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
@@ -178,4 +179,9 @@ public class SparseLocalOnHeapVectorStorage implements VectorStorage, StorageCon
return res;
}
+
+ /** */
+ public IntSet indexes() {
+ return (IntSet)sto.keySet();
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
index e48542b..1de334f 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java
@@ -22,6 +22,7 @@ import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.VectorStorage;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
import org.apache.ignite.ml.math.impls.matrix.FunctionMatrix;
/**
@@ -122,4 +123,9 @@ public abstract class AbstractReadOnlyVector extends AbstractVector {
return new FunctionVector(size(), (idx) -> Math.log1p(get(idx)) / denominator);
}
+
+ /** {@inheritDoc} */
+ @Override public void compute(int idx, IgniteIntDoubleToDoubleBiFunction f) {
+ throw new UnsupportedOperationException();
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
index 83ac837..131a610 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractVector.java
@@ -38,6 +38,7 @@ import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
import org.apache.ignite.ml.math.functions.Functions;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
import org.apache.ignite.ml.math.impls.matrix.MatrixView;
import org.jetbrains.annotations.NotNull;
@@ -904,4 +905,11 @@ public abstract class AbstractVector implements Vector {
return (sto != null ? sto.equals(that.sto) : that.sto == null);
}
+
+ /** {@inheritDoc} */
+ @Override public void compute(int idx, IgniteIntDoubleToDoubleBiFunction f) {
+ storageSet(idx, f.apply(idx, storageGet(idx)));
+ lenSq = 0.0;
+ maxElm = minElm = null;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
index 48fbd06..1df9acc 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/DelegatingVector.java
@@ -30,6 +30,7 @@ import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.VectorStorage;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.functions.IgniteIntDoubleToDoubleBiFunction;
/**
* Convenient class that can be used to add decorations to an existing vector. Subclasses
@@ -367,6 +368,11 @@ public class DelegatingVector implements Vector {
}
/** {@inheritDoc} */
+ @Override public void compute(int i, IgniteIntDoubleToDoubleBiFunction f) {
+ dlg.compute(i, f);
+ }
+
+ /** {@inheritDoc} */
@Override public void destroy() {
dlg.destroy();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
index 9e345bb..bc1e59d 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseLocalVector.java
@@ -17,7 +17,11 @@
package org.apache.ignite.ml.math.impls.vector;
+import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.Map;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.function.Consumer;
import org.apache.ignite.ml.math.Matrix;
import org.apache.ignite.ml.math.StorageConstants;
import org.apache.ignite.ml.math.Vector;
@@ -77,4 +81,39 @@ public class SparseLocalVector extends AbstractVector implements StorageConstant
else
return super.times(x);
}
+
+ /** Indexes of non-default elements. */
+ public IntSet indexes() {
+ return storage().indexes();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Spliterator<Double> nonZeroSpliterator() {
+ return new Spliterator<Double>() {
+ /** {@inheritDoc} */
+ @Override public boolean tryAdvance(Consumer<? super Double> act) {
+ Set<Integer> indexes = storage().indexes();
+
+ for (Integer index : indexes)
+ act.accept(storageGet(index));
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Spliterator<Double> trySplit() {
+ return null; // No Splitting.
+ }
+
+ /** {@inheritDoc} */
+ @Override public long estimateSize() {
+ return storage().indexes().size();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int characteristics() {
+ return ORDERED | SIZED;
+ }
+ };
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
index 752929d..c727e44 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
@@ -20,12 +20,14 @@ package org.apache.ignite.ml.math.util;
import java.util.List;
import org.apache.ignite.internal.util.GridArgumentCheck;
import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.StorageConstants;
import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.impls.matrix.CacheMatrix;
import org.apache.ignite.ml.math.impls.matrix.DenseLocalOnHeapMatrix;
import org.apache.ignite.ml.math.impls.matrix.MatrixView;
import org.apache.ignite.ml.math.impls.matrix.PivotedMatrixView;
import org.apache.ignite.ml.math.impls.matrix.RandomMatrix;
+import org.apache.ignite.ml.math.impls.matrix.SparseLocalOnHeapMatrix;
import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
/**
@@ -116,6 +118,18 @@ public class MatrixUtil {
}
/** */
+ public static DenseLocalOnHeapMatrix asDense(SparseLocalOnHeapMatrix m, int acsMode) {
+ DenseLocalOnHeapMatrix res = new DenseLocalOnHeapMatrix(m.rowSize(), m.columnSize(), acsMode);
+
+ for (Integer row : m.indexesMap().keySet()) {
+ for (Integer col : m.indexesMap().get(row))
+ res.set(row, col, m.get(row, col));
+ }
+
+ return res;
+ }
+
+ /** */
private static boolean isCopyLikeSupport(Matrix matrix) {
return matrix instanceof RandomMatrix || matrix instanceof MatrixView || matrix instanceof CacheMatrix ||
matrix instanceof PivotedMatrixView;
@@ -152,4 +166,38 @@ public class MatrixUtil {
return res;
}
+
+ /** */
+ public static double[][] unflatten(double[] fArr, int colsCnt) {
+ int rowsCnt = fArr.length / colsCnt;
+
+ double[][] res = new double[rowsCnt][colsCnt];
+
+ for (int i = 0; i < rowsCnt; i++)
+ for (int j = 0; j < colsCnt; j++)
+ res[i][j] = fArr[i * colsCnt + j];
+
+ return res;
+ }
+
+ /** */
+ public static double[] flatten(double[][] arr, int acsMode) {
+ assert arr != null;
+ assert arr[0] != null;
+
+ int size = arr.length * arr[0].length;
+ int rows = acsMode == StorageConstants.ROW_STORAGE_MODE ? arr.length : arr[0].length;
+ int cols = size / rows;
+
+ double[] res = new double[size];
+
+ int iLim = acsMode == StorageConstants.ROW_STORAGE_MODE ? rows : cols;
+ int jLim = acsMode == StorageConstants.ROW_STORAGE_MODE ? cols : rows;
+
+ for (int i = 0; i < iLim; i++)
+ for (int j = 0; j < jLim; j++)
+ res[i * jLim + j] = arr[i][j];
+
+ return res;
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/de259fff/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
index cdc2651..a59b7f9 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/clustering/KMeansDistributedClustererTest.java
@@ -130,8 +130,8 @@ public class KMeansDistributedClustererTest extends GridCommonAbstractTest {
Vector[] mc = new Vector[centersCnt];
Arrays.fill(mc, VectorUtils.zeroes(2));
- int centIndex = 0;
- int totalCount = 0;
+ int centIdx = 0;
+ int totalCnt = 0;
List<Vector> massCenters = new ArrayList<>();
@@ -140,12 +140,12 @@ public class KMeansDistributedClustererTest extends GridCommonAbstractTest {
DenseLocalOnHeapVector pnt = (DenseLocalOnHeapVector)new DenseLocalOnHeapVector(2).assign(centers.get(count));
// pertrubate point on random value.
pnt.map(val -> val + rnd.nextDouble() * squareSideLen / 100);
- mc[centIndex] = mc[centIndex].plus(pnt);
- points.assignRow(permutation.get(totalCount), pnt);
- totalCount++;
+ mc[centIdx] = mc[centIdx].plus(pnt);
+ points.assignRow(permutation.get(totalCnt), pnt);
+ totalCnt++;
}
- massCenters.add(mc[centIndex].times(1 / (double)count));
- centIndex++;
+ massCenters.add(mc[centIdx].times(1 / (double)count));
+ centIdx++;
}
EuclideanDistance dist = new EuclideanDistance();
@@ -169,6 +169,7 @@ public class KMeansDistributedClustererTest extends GridCommonAbstractTest {
/** */
List<Vector> orderedNodes;
+ /** */
public OrderedNodesComparator(Vector[] orderedNodes, DistanceMeasure measure) {
this.orderedNodes = Arrays.asList(orderedNodes);
this.measure = measure;