http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/AbstractMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/AbstractMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/AbstractMatrix.java new file mode 100644 index 0000000..ca11e81 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/AbstractMatrix.java @@ -0,0 +1,880 @@ +/* + * 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.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.decompositions.LUDecomposition; +import org.apache.ignite.math.exceptions.CardinalityException; +import org.apache.ignite.math.exceptions.ColumnIndexException; +import org.apache.ignite.math.exceptions.RowIndexException; +import org.apache.ignite.math.functions.Functions; +import org.apache.ignite.math.functions.IgniteBiFunction; +import org.apache.ignite.math.functions.IgniteDoubleFunction; +import org.apache.ignite.math.functions.IgniteFunction; +import org.apache.ignite.math.functions.IntIntToDoubleFunction; +import org.apache.ignite.math.impls.vector.MatrixVectorView; + +/** + * This class provides a helper implementation of the {@link Matrix} + * interface to minimize the effort required to implement it. + * Subclasses may override some of the implemented methods if a more + * specific or optimized implementation is desirable. + * + * TODO: add row/column optimization. + */ +public abstract class AbstractMatrix implements Matrix { + // Stochastic sparsity analysis. + /** */ + private static final double Z95 = 1.959964; + /** */ + private static final double Z80 = 1.281552; + /** */ + private static final int MAX_SAMPLES = 500; + /** */ + private static final int MIN_SAMPLES = 15; + + /** Cached minimum element. */ + private Element minElm; + /** Cached maximum element. */ + private Element maxElm = null; + + /** Matrix storage implementation. */ + private MatrixStorage sto; + + /** Meta attributes storage. */ + private Map<String, Object> meta = new HashMap<>(); + + /** Matrix's GUID. */ + private IgniteUuid guid = IgniteUuid.randomUuid(); + + /** + * @param sto Backing {@link MatrixStorage}. + */ + public AbstractMatrix(MatrixStorage sto) { + this.sto = sto; + } + + /** + * + */ + public AbstractMatrix() { + // No-op. + } + + /** + * @param sto Backing {@link MatrixStorage}. + */ + protected void setStorage(MatrixStorage sto) { + assert sto != null; + + this.sto = sto; + } + + /** + * @param row Row index in the matrix. + * @param col Column index in the matrix. + * @param v Value to set. + */ + protected void storageSet(int row, int col, double v) { + sto.set(row, col, v); + + // Reset cached values. + minElm = maxElm = null; + } + + /** + * @param row Row index in the matrix. + * @param col Column index in the matrix. + */ + protected double storageGet(int row, int col) { + return sto.get(row, col); + } + + /** {@inheritDoc} */ + @Override public Element maxElement() { + if (maxElm == null) { + double max = Double.NEGATIVE_INFINITY; + int row = 0, col = 0; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) { + double d = storageGet(x, y); + + if (d > max) { + max = d; + row = x; + col = y; + } + } + + maxElm = mkElement(row, col); + } + + return maxElm; + } + + /** {@inheritDoc} */ + @Override public Element minElement() { + if (minElm == null) { + double min = Double.MAX_VALUE; + int row = 0, col = 0; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) { + double d = storageGet(x, y); + + if (d < min) { + min = d; + row = x; + col = y; + } + } + + minElm = mkElement(row, col); + } + + return minElm; + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + return maxElement().get(); + } + + /** {@inheritDoc} */ + @Override public double minValue() { + return minElement().get(); + } + + /** + * @param row Row index in the matrix. + * @param col Column index in the matrix. + */ + private Element mkElement(int row, int col) { + return new Element() { + /** {@inheritDoc} */ + @Override public double get() { + return storageGet(row, col); + } + + /** {@inheritDoc} */ + @Override public int row() { + return row; + } + + /** {@inheritDoc} */ + @Override public int column() { + return col; + } + + /** {@inheritDoc} */ + @Override public void set(double d) { + storageSet(row, col, d); + } + }; + } + + /** {@inheritDoc} */ + @Override public Element getElement(int row, int col) { + return mkElement(row, col); + } + + /** {@inheritDoc} */ + @Override public Matrix swapRows(int row1, int row2) { + checkRowIndex(row1); + checkRowIndex(row2); + + int cols = columnSize(); + + for (int y = 0; y < cols; y++) { + double v = getX(row1, y); + + setX(row1, y, getX(row2, y)); + setX(row2, y, v); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix swapColumns(int col1, int col2) { + checkColumnIndex(col1); + checkColumnIndex(col2); + + int rows = rowSize(); + + for (int x = 0; x < rows; x++) { + double v = getX(x, col1); + + setX(x, col1, getX(x, col2)); + setX(x, col2, v); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public MatrixStorage getStorage() { + return sto; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased(); + } + + /** + * Check row index bounds. + * + * @param row Row index. + */ + private void checkRowIndex(int row) { + if (row < 0 || row >= rowSize()) + throw new RowIndexException(row); + } + + /** + * Check column index bounds. + * + * @param col Column index. + */ + private void checkColumnIndex(int col) { + if (col < 0 || col >= columnSize()) + throw new ColumnIndexException(col); + } + + /** + * Check column and row index bounds. + * + * @param row Row index. + * @param col Column index. + */ + protected void checkIndex(int row, int col) { + checkRowIndex(row); + checkColumnIndex(col); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(meta); + out.writeObject(guid); + } + + /** {@inheritDoc} */ + @Override public Map<String, Object> getMetaStorage() { + return meta; + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (MatrixStorage)in.readObject(); + meta = (Map<String, Object>)in.readObject(); + guid = (IgniteUuid)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double val) { + if (sto.isArrayBased()) + for (double[] column : sto.data()) + Arrays.fill(column, val); + else { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, val); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assign(IntIntToDoubleFunction fun) { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, fun.apply(x, y)); + + return this; + } + + /** */ + private void checkCardinality(Matrix mtx) { + checkCardinality(mtx.rowSize(), mtx.columnSize()); + } + + /** */ + private void checkCardinality(int rows, int cols) { + if (rows != rowSize()) + throw new CardinalityException(rowSize(), rows); + + if (cols != columnSize()) + throw new CardinalityException(columnSize(), cols); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double[][] vals) { + checkCardinality(vals.length, vals[0].length); + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, vals[x][y]); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assign(Matrix mtx) { + checkCardinality(mtx); + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, mtx.getX(x, y)); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix map(IgniteDoubleFunction<Double> fun) { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, fun.apply(storageGet(x, y))); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix map(Matrix mtx, IgniteBiFunction<Double, Double, Double> fun) { + checkCardinality(mtx); + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, fun.apply(storageGet(x, y), mtx.getX(x, y))); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assignColumn(int col, org.apache.ignite.math.Vector vec) { + checkColumnIndex(col); + + int rows = rowSize(); + + for (int x = 0; x < rows; x++) + storageSet(x, col, vec.getX(x)); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assignRow(int row, Vector vec) { + checkRowIndex(row); + + int cols = columnSize(); + + if (cols != vec.size()) + throw new CardinalityException(cols, vec.size()); + + if (sto.isArrayBased() && vec.getStorage().isArrayBased()) + System.arraycopy(vec.getStorage().data(), 0, sto.data()[row], 0, cols); + else + for (int y = 0; y < cols; y++) + storageSet(row, y, vec.getX(y)); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector foldRows(IgniteFunction<Vector, Double> fun) { + int rows = rowSize(); + + Vector vec = likeVector(rows); + + for (int i = 0; i < rows; i++) + vec.setX(i, fun.apply(viewRow(i))); + + return vec; + } + + /** {@inheritDoc} */ + @Override public Vector foldColumns(IgniteFunction<Vector, Double> fun) { + int cols = columnSize(); + + Vector vec = likeVector(cols); + + for (int i = 0; i < cols; i++) + vec.setX(i, fun.apply(viewColumn(i))); + + return vec; + } + + /** {@inheritDoc} */ + @Override public <T> T foldMap(IgniteBiFunction<T, Double, T> foldFun, IgniteDoubleFunction<Double> mapFun, + T zeroVal) { + T res = zeroVal; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + res = foldFun.apply(res, mapFun.apply(storageGet(x, y))); + + return res; + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return sto.columnSize(); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return sto.rowSize(); + } + + /** {@inheritDoc} */ + @Override public double determinant() { + //TODO: This decomposition should be cached + LUDecomposition dec = new LUDecomposition(this); + double res = dec.determinant(); + dec.destroy(); + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix inverse() { + if (rowSize() != columnSize()) + throw new CardinalityException(rowSize(), columnSize()); + + //TODO: This decomposition should be cached + LUDecomposition dec = new LUDecomposition(this); + + Matrix res = dec.solve(likeIdentity()); + dec.destroy(); + + return res; + } + + /** */ + protected Matrix likeIdentity() { + int n = rowSize(); + Matrix res = like(n, n); + + for (int i = 0; i < n; i++) + res.setX(i, i, 1.0); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix divide(double d) { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + setX(x, y, getX(x, y) / d); + + return this; + } + + /** {@inheritDoc} */ + @Override public double get(int row, int col) { + checkIndex(row, col); + + return storageGet(row, col); + } + + /** {@inheritDoc} */ + @Override public double getX(int row, int col) { + return storageGet(row, col); + } + + /** {@inheritDoc} */ + @Override public Matrix minus(Matrix mtx) { + int rows = rowSize(); + int cols = columnSize(); + + checkCardinality(rows, cols); + + Matrix res = like(rows, cols); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + res.setX(x, y, getX(x, y) - mtx.getX(x, y)); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix plus(double x) { + Matrix cp = copy(); + + cp.map(Functions.plus(x)); + + return cp; + } + + /** {@inheritDoc} */ + @Override public Matrix plus(Matrix mtx) { + int rows = rowSize(); + int cols = columnSize(); + + checkCardinality(rows, cols); + + Matrix res = like(rows, cols); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + res.setX(x, y, getX(x, y) + mtx.getX(x, y)); + + return res; + + } + + /** {@inheritDoc} */ + @Override public IgniteUuid guid() { + return guid; + } + + /** {@inheritDoc} */ + @Override public Matrix set(int row, int col, double val) { + checkIndex(row, col); + + storageSet(row, col, val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix setRow(int row, double[] data) { + checkRowIndex(row); + + int cols = columnSize(); + + if (cols != data.length) + throw new CardinalityException(cols, data.length); + + if (sto.isArrayBased()) + System.arraycopy(data, 0, sto.data()[row], 0, cols); + else + for (int y = 0; y < cols; y++) + setX(row, y, data[y]); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix setColumn(int col, double[] data) { + checkColumnIndex(col); + + int rows = rowSize(); + + if (rows != data.length) + throw new CardinalityException(rows, data.length); + + for (int x = 0; x < rows; x++) + setX(x, col, data[x]); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix setX(int row, int col, double val) { + storageSet(row, col, val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix times(double x) { + Matrix cp = copy(); + + cp.map(Functions.mult(x)); + + return cp; + } + + /** {@inheritDoc} */ + @Override public double maxAbsRowSumNorm() { + double max = 0.0; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) { + double sum = 0; + + for (int y = 0; y < cols; y++) + sum += Math.abs(getX(x, y)); + + if (sum > max) + max = sum; + } + + return max; + } + + /** {@inheritDoc} */ + @Override public Vector times(Vector vec) { + int cols = columnSize(); + + if (cols != vec.size()) + throw new CardinalityException(cols, vec.size()); + + int rows = rowSize(); + + Vector res = likeVector(rows); + + for (int x = 0; x < rows; x++) + res.setX(x, vec.dot(viewRow(x))); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix times(Matrix mtx) { + int cols = columnSize(); + + if (cols != mtx.rowSize()) + throw new CardinalityException(cols, mtx.rowSize()); + + int rows = rowSize(); + + int mtxCols = mtx.columnSize(); + + Matrix res = like(rows, mtxCols); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < mtxCols; y++) { + double sum = 0.0; + + for (int k = 0; k < cols; k++) + sum += getX(x, k) * mtx.getX(k, y); + + res.setX(x, y, sum); + } + + return res; + } + + /** {@inheritDoc} */ + @Override public double sum() { + int rows = rowSize(); + int cols = columnSize(); + + double sum = 0.0; + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + sum += getX(x, y); + + return sum; + } + + /** {@inheritDoc} */ + @Override public Matrix transpose() { + int rows = rowSize(); + int cols = columnSize(); + + Matrix mtx = like(cols, rows); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + mtx.setX(y, x, getX(x, y)); + + return mtx; + } + + /** {@inheritDoc} */ + @Override public boolean density(double threshold) { + assert threshold >= 0.0 && threshold <= 1.0; + + int n = MIN_SAMPLES; + int rows = rowSize(); + int cols = columnSize(); + + double mean = 0.0; + double pq = threshold * (1 - threshold); + + Random rnd = new Random(); + + for (int i = 0; i < MIN_SAMPLES; i++) + if (getX(rnd.nextInt(rows), rnd.nextInt(cols)) != 0.0) + mean++; + + mean /= MIN_SAMPLES; + + double iv = Z80 * Math.sqrt(pq / n); + + if (mean < threshold - iv) + return false; // Sparse. + else if (mean > threshold + iv) + return true; // Dense. + + while (n < MAX_SAMPLES) { + // Determine upper bound we may need for 'n' to likely relinquish the uncertainty. + // Here, we use confidence interval formula but solved for 'n'. + double ivX = Math.max(Math.abs(threshold - mean), 1e-11); + + double stdErr = ivX / Z80; + double nX = Math.min(Math.max((int)Math.ceil(pq / (stdErr * stdErr)), n), MAX_SAMPLES) - n; + + if (nX < 1.0) // IMPL NOTE this can happen with threshold 1.0 + nX = 1.0; + + double meanNext = 0.0; + + for (int i = 0; i < nX; i++) + if (getX(rnd.nextInt(rows), rnd.nextInt(cols)) != 0.0) + meanNext++; + + mean = (n * mean + meanNext) / (n + nX); + + n += nX; + + // Are we good now? + iv = Z80 * Math.sqrt(pq / n); + + if (mean < threshold - iv) + return false; // Sparse. + else if (mean > threshold + iv) + return true; // Dense. + } + + return mean > threshold; // Dense if mean > threshold. + } + + /** {@inheritDoc} */ + @Override public Matrix viewPart(int[] off, int[] size) { + return new MatrixView(this, off[0], off[1], size[0], size[1]); + } + + /** {@inheritDoc} */ + @Override public Matrix viewPart(int rowOff, int rows, int colOff, int cols) { + return viewPart(new int[] {rowOff, colOff}, new int[] {rows, cols}); + } + + /** {@inheritDoc} */ + @Override public Vector viewRow(int row) { + return new MatrixVectorView(this, row, 0, 0, 1); + } + + /** {@inheritDoc} */ + @Override public Vector viewColumn(int col) { + return new MatrixVectorView(this, 0, col, 1, 0); + } + + /** {@inheritDoc} */ + @Override public Vector viewDiagonal() { + return new MatrixVectorView(this, 0, 0, 1, 1); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + Matrix cp = like(rowSize(), columnSize()); + + cp.assign(this); + + return cp; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + guid.hashCode(); + res = res * 37 + sto.hashCode(); + res = res * 37 + meta.hashCode(); + + return res; + } + + /** + * {@inheritDoc} + * + * We ignore guid's for comparisons. + */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + AbstractMatrix that = (AbstractMatrix)o; + + MatrixStorage sto = getStorage(); + + return (sto != null ? sto.equals(that.getStorage()) : that.getStorage() == null); + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/CacheMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/CacheMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/CacheMatrix.java new file mode 100644 index 0000000..8ce1192 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/CacheMatrix.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.math.impls.matrix; + +import org.apache.ignite.IgniteCache; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixKeyMapper; +import org.apache.ignite.math.ValueMapper; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IgniteDoubleFunction; +import org.apache.ignite.math.functions.IgniteFunction; +import org.apache.ignite.math.impls.CacheUtils; +import org.apache.ignite.math.impls.storage.matrix.CacheMatrixStorage; + +/** + * Matrix based on existing cache and key and value mapping functions. + */ +public class CacheMatrix<K, V> extends AbstractMatrix { + /** + * + */ + public CacheMatrix() { + // No-op. + } + + /** + * Creates new matrix over existing cache. + * + * @param rows + * @param cols + * @param cache + * @param keyMapper + * @param valMapper + */ + public CacheMatrix( + int rows, + int cols, + IgniteCache<K, V> cache, + MatrixKeyMapper<K> keyMapper, + ValueMapper<V> valMapper) { + assert rows > 0; + assert cols > 0; + assert cache != null; + assert keyMapper != null; + assert valMapper != null; + + setStorage(new CacheMatrixStorage<>(rows, cols, cache, keyMapper, valMapper)); + } + + /** + * + * + */ + @SuppressWarnings({"unchecked"}) + private CacheMatrixStorage<K, V> storage() { + return (CacheMatrixStorage<K, V>)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param d + */ + @Override public Matrix divide(double d) { + return mapOverValues((Double v) -> v / d); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param x + */ + @Override public Matrix plus(double x) { + return mapOverValues((Double v) -> v + x); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param x + */ + @Override public Matrix times(double x) { + return mapOverValues((Double v) -> v * x); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double val) { + return mapOverValues((Double v) -> val); + } + + /** {@inheritDoc} */ + @Override public Matrix map(IgniteDoubleFunction<Double> fun) { + return mapOverValues(fun::apply); + } + + /** {@inheritDoc} */ + @Override public double sum() { + CacheMatrixStorage<K, V> sto = storage(); + + return CacheUtils.sum(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + CacheMatrixStorage<K, V> sto = storage(); + + return CacheUtils.max(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public double minValue() { + CacheMatrixStorage<K, V> sto = storage(); + + return CacheUtils.min(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** + * @param mapper + */ + private Matrix mapOverValues(IgniteFunction<Double, Double> mapper) { + CacheMatrixStorage<K, V> sto = storage(); + + CacheUtils.map(sto.cache().getName(), sto.keyMapper(), sto.valueMapper(), mapper); + + return this; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOffHeapMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOffHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOffHeapMatrix.java new file mode 100644 index 0000000..d5f8eca --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOffHeapMatrix.java @@ -0,0 +1,90 @@ +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.impls.storage.matrix.DenseOffHeapMatrixStorage; +import org.apache.ignite.math.impls.vector.DenseLocalOffHeapVector; + +/** + * Dense local off-heap implementation of the {@link Matrix} interface. + */ +public class DenseLocalOffHeapMatrix extends AbstractMatrix { + /** */ + public DenseLocalOffHeapMatrix() { + // No-op. + } + + /** + * @param data Backing data array. + */ + public DenseLocalOffHeapMatrix(double[][] data) { + assert data != null; + + setStorage(new DenseOffHeapMatrixStorage(data)); + } + + /** + * @param rows Amount of rows in matrix. + * @param cols Amount of columns in matrix. + */ + public DenseLocalOffHeapMatrix(int rows, int cols) { + assert rows > 0; + assert cols > 0; + + setStorage(new DenseOffHeapMatrixStorage(rows, cols)); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + DenseLocalOffHeapMatrix cp = new DenseLocalOffHeapMatrix(getStorage().rowSize(), getStorage().columnSize()); + + cp.assign(this); + + return cp; + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return new DenseLocalOffHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return new DenseLocalOffHeapVector(crd); + } + + /** {@inheritDoc} */ + @Override public void destroy() { + getStorage().destroy(); + } + + /** {@inheritDoc} */ + @Override protected Matrix likeIdentity() { + int n = rowSize(); + Matrix res = like(n, n); + + // IMPL NOTE as opposed to on-heap matrices this one isn't initialized with zeroes + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + res.setX(i, j, i == j ? 1.0 : 0.0); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOnHeapMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOnHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOnHeapMatrix.java new file mode 100644 index 0000000..3cc3e4f --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DenseLocalOnHeapMatrix.java @@ -0,0 +1,86 @@ +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.impls.storage.matrix.ArrayMatrixStorage; +import org.apache.ignite.math.impls.vector.DenseLocalOnHeapVector; + +/** + * Basic implementation for matrix. + * + * This is a trivial implementation for matrix assuming dense logic, local on-heap JVM storage + * based on <code>double[][]</code> array. It is only suitable for data sets where + * 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 DenseLocalOnHeapMatrix() { + // No-op. + } + + /** + * @param rows Amount of rows in matrix. + * @param cols Amount of columns in matrix. + */ + public DenseLocalOnHeapMatrix(int rows, int cols) { + assert rows > 0; + assert cols > 0; + + setStorage(new ArrayMatrixStorage(rows, cols)); + } + + /** + * @param mtx Backing data array. + */ + public DenseLocalOnHeapMatrix(double[][] mtx) { + assert mtx != null; + + setStorage(new ArrayMatrixStorage(mtx)); + } + + /** + * @param orig Original matrix. + */ + private DenseLocalOnHeapMatrix(DenseLocalOnHeapMatrix orig) { + assert orig != null; + + setStorage(new ArrayMatrixStorage(orig.rowSize(), orig.columnSize())); + + assign(orig); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + return new DenseLocalOnHeapMatrix(this); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return new DenseLocalOnHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return new DenseLocalOnHeapVector(crd); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DiagonalMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DiagonalMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DiagonalMatrix.java new file mode 100644 index 0000000..0b1f97e --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/DiagonalMatrix.java @@ -0,0 +1,101 @@ +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.impls.storage.matrix.DiagonalMatrixStorage; +import org.apache.ignite.math.impls.vector.ConstantVector; +import org.apache.ignite.math.impls.vector.DenseLocalOnHeapVector; +import org.apache.ignite.math.impls.vector.SingleElementVectorView; + +/** + * Implementation of diagonal view of the {@link Matrix}. + * + * <p>See also: <a href="https://en.wikipedia.org/wiki/Diagonal_matrix">Wikipedia article</a>.</p> + */ +public class DiagonalMatrix extends AbstractMatrix { + /** + * + */ + public DiagonalMatrix() { + // No-op. + } + + /** + * @param diagonal Backing {@link Vector}. + */ + public DiagonalMatrix(Vector diagonal) { + super(new DiagonalMatrixStorage(diagonal)); + } + + /** + * @param mtx Backing {@link Matrix}. + */ + public DiagonalMatrix(Matrix mtx) { + super(new DiagonalMatrixStorage(mtx == null ? null : mtx.viewDiagonal())); + } + + /** + * @param vals Backing array of values at diagonal. + */ + public DiagonalMatrix(double[] vals) { + super(new DiagonalMatrixStorage(new DenseLocalOnHeapVector(vals))); + } + + /** + * + * + */ + private DiagonalMatrixStorage storage() { + return (DiagonalMatrixStorage)getStorage(); + } + + /** + * @param size Size of diagonal. + * @param val Constant value at diagonal. + */ + public DiagonalMatrix(int size, double val) { + super(new DiagonalMatrixStorage(new ConstantVector(size, val))); + } + + /** {@inheritDoc} */ + @Override public Vector viewRow(int row) { + return new SingleElementVectorView(storage().diagonal(), row); + } + + /** {@inheritDoc} */ + @Override public Vector viewColumn(int col) { + return new SingleElementVectorView(storage().diagonal(), col); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + return new DiagonalMatrix(storage().diagonal()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return storage().diagonal().likeMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return storage().diagonal().like(crd); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/FunctionMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/FunctionMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/FunctionMatrix.java new file mode 100644 index 0000000..b180b5b --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/FunctionMatrix.java @@ -0,0 +1,95 @@ +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IntIntDoubleToVoidFunction; +import org.apache.ignite.math.functions.IntIntToDoubleFunction; +import org.apache.ignite.math.impls.storage.matrix.FunctionMatrixStorage; + +/** + * Implementation of {@link Matrix} that maps row and column index to {@link java.util.function} interfaces. + */ +public class FunctionMatrix extends AbstractMatrix { + /** + * + */ + public FunctionMatrix() { + // No-op. + } + + /** + * Creates read-write or read-only function matrix. + * + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param getFunc Function that returns value corresponding to given row and column index. + * @param setFunc Set function. If {@code null} - this will be a read-only matrix. + */ + public FunctionMatrix(int rows, int cols, IntIntToDoubleFunction getFunc, IntIntDoubleToVoidFunction setFunc) { + assert rows > 0; + assert cols > 0; + assert getFunc != null; + + setStorage(new FunctionMatrixStorage(rows, cols, getFunc, setFunc)); + } + + /** + * Creates read-only function matrix. + * + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param getFunc Function that returns value corresponding to given row and column index. + */ + public FunctionMatrix(int rows, int cols, IntIntToDoubleFunction getFunc) { + assert rows > 0; + assert cols > 0; + assert getFunc != null; + + setStorage(new FunctionMatrixStorage(rows, cols, getFunc)); + } + + /** + * + * + */ + private FunctionMatrixStorage storage() { + return (FunctionMatrixStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + FunctionMatrixStorage sto = storage(); + + return new FunctionMatrix(sto.rowSize(), sto.columnSize(), sto.getFunction(), sto.setFunction()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + FunctionMatrixStorage sto = storage(); + + return new FunctionMatrix(rows, cols, sto.getFunction(), sto.setFunction()); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/MatrixView.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/MatrixView.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/MatrixView.java new file mode 100644 index 0000000..7b04dde --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/MatrixView.java @@ -0,0 +1,84 @@ +/* + * 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.matrix; + +import java.io.Externalizable; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.impls.storage.matrix.MatrixDelegateStorage; + +/** + * Implements the rectangular view into the parent {@link Matrix}. + */ +public class MatrixView extends AbstractMatrix { + /** + * Constructor for {@link Externalizable} interface. + */ + public MatrixView() { + // No-op. + } + + /** + * @param parent Backing parent {@link Matrix}. + * @param rowOff Row offset to parent matrix. + * @param colOff Column offset to parent matrix. + * @param rows Amount of rows in the view. + * @param cols Amount of columns in the view. + */ + public MatrixView(Matrix parent, int rowOff, int colOff, int rows, int cols) { + this(parent == null ? null : parent.getStorage(), rowOff, colOff, rows, cols); + } + + /** + * @param sto Backing parent {@link MatrixStorage}. + * @param rowOff Row offset to parent storage. + * @param colOff Column offset to parent storage. + * @param rows Amount of rows in the view. + * @param cols Amount of columns in the view. + */ + public MatrixView(MatrixStorage sto, int rowOff, int colOff, int rows, int cols) { + super(new MatrixDelegateStorage(sto, rowOff, colOff, rows, cols)); + } + + /** + * + * + */ + private MatrixDelegateStorage storage() { + return (MatrixDelegateStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + MatrixDelegateStorage sto = storage(); + + return new MatrixView(sto.delegate(), sto.rowOffset(), sto.columnOffset(), sto.rowSize(), sto.columnSize()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/PivotedMatrixView.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/PivotedMatrixView.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/PivotedMatrixView.java new file mode 100644 index 0000000..1f7b008 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/PivotedMatrixView.java @@ -0,0 +1,243 @@ +/* + * 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.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.IndexException; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.impls.storage.matrix.PivotedMatrixStorage; +import org.apache.ignite.math.impls.vector.PivotedVectorView; + +/** + * Pivoted (index mapped) view over another matrix implementation. + */ +public class PivotedMatrixView extends AbstractMatrix { + /** Pivoted matrix. */ + private Matrix mtx; + + /** + * + */ + public PivotedMatrixView() { + // No-op. + } + + /** + * @param mtx + * @param rowPivot + * @param colPivot + */ + public PivotedMatrixView(Matrix mtx, int[] rowPivot, int[] colPivot) { + super(new PivotedMatrixStorage(mtx == null ? null : mtx.getStorage(), rowPivot, colPivot)); + + this.mtx = mtx; + } + + /** + * @param mtx + */ + public PivotedMatrixView(Matrix mtx) { + super(new PivotedMatrixStorage(mtx == null ? null : mtx.getStorage())); + + this.mtx = mtx; + } + + /** + * @param mtx + * @param pivot + */ + public PivotedMatrixView(Matrix mtx, int[] pivot) { + super(new PivotedMatrixStorage(mtx == null ? null : mtx.getStorage(), pivot)); + + this.mtx = mtx; + } + + /** + * Swaps indexes {@code i} and {@code j} for both both row and column. + * + * @param i First index to swap. + * @param j Second index to swap. + */ + public Matrix swap(int i, int j) { + swapRows(i, j); + swapColumns(i, j); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix swapRows(int i, int j) { + if (i < 0 || i >= storage().rowPivot().length) + throw new IndexException(i); + if (j < 0 || j >= storage().rowPivot().length) + throw new IndexException(j); + + storage().swapRows(i, j); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix swapColumns(int i, int j) { + if (i < 0 || i >= storage().columnPivot().length) + throw new IndexException(i); + if (j < 0 || j >= storage().columnPivot().length) + throw new IndexException(j); + + storage().swapColumns(i, j); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector viewRow(int row) { + return new PivotedVectorView( + mtx.viewRow(storage().rowPivot()[row]), + storage().columnPivot(), + storage().columnUnpivot() + ); + } + + /** {@inheritDoc} */ + @Override public Vector viewColumn(int col) { + return new PivotedVectorView( + mtx.viewColumn(storage().columnPivot()[col]), + storage().rowPivot(), + storage().rowUnpivot() + ); + } + + /** + * + * + */ + public Matrix getBaseMatrix() { + return mtx; + } + + /** + * + * + */ + public int[] rowPivot() { + return storage().rowPivot(); + } + + /** + * + * + */ + public int[] columnPivot() { + return storage().columnPivot(); + } + + /** + * @param i + */ + public int rowPivot(int i) { + return storage().rowPivot()[i]; + } + + /** + * @param i + */ + public int columnPivot(int i) { + return storage().columnPivot()[i]; + } + + /** + * @param i + */ + public int rowUnpivot(int i) { + return storage().rowUnpivot()[i]; + } + + /** + * @param i + */ + public int columnUnpivot(int i) { + return storage().columnUnpivot()[i]; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + + out.writeObject(mtx); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + + mtx = (Matrix)in.readObject(); + } + + /** + * + * + */ + private PivotedMatrixStorage storage() { + return (PivotedMatrixStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + return new PivotedMatrixView(mtx, storage().rowPivot(), storage().columnPivot()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + mtx.hashCode(); + res = res * 37 + getStorage().hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + PivotedMatrixView that = (PivotedMatrixView)o; + + MatrixStorage sto = storage(); + + return mtx.equals(that.mtx) && sto.equals(that.storage()); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/RandomMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/RandomMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/RandomMatrix.java new file mode 100644 index 0000000..2c3dcb2 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/RandomMatrix.java @@ -0,0 +1,97 @@ +/* + * 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.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.impls.storage.matrix.RandomMatrixStorage; +import org.apache.ignite.math.impls.vector.RandomVector; + +/** + * Implementation of {@link Matrix} with random values in the elements. + */ +public class RandomMatrix extends AbstractMatrix { + /** Whether fast hash is used, see {@link RandomMatrixStorage}. */ + private boolean fastHash; + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param fastHash Whether fast hash is used. + */ + private MatrixStorage mkStorage(int rows, int cols, boolean fastHash) { + this.fastHash = fastHash; + + return new RandomMatrixStorage(rows, cols, fastHash); + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param fastHash Whether fast hash is used. + */ + public RandomMatrix(int rows, int cols, boolean fastHash) { + setStorage(mkStorage(rows, cols, fastHash)); + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + */ + public RandomMatrix(int rows, int cols) { + this(rows, cols, true); + } + + /** */ + public RandomMatrix() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + return new RandomMatrix(rowSize(), columnSize(), fastHash); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return new RandomMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return new RandomVector(crd); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + + out.writeBoolean(fastHash); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + + fastHash = in.readBoolean(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrix.java new file mode 100644 index 0000000..5c40d70 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseDistributedMatrix.java @@ -0,0 +1,155 @@ +// @java.file.header + +/* _________ _____ __________________ _____ + * __ ____/___________(_)______ /__ ____/______ ____(_)_______ + * _ / __ __ ___/__ / _ __ / _ / __ _ __ `/__ / __ __ \ + * / /_/ / _ / _ / / /_/ / / /_/ / / /_/ / _ / _ / / / + * \____/ /_/ /_/ \_,__/ \____/ \__,_/ /_/ /_/ /_/ + */ + +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.StorageConstants; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.functions.IgniteDoubleFunction; +import org.apache.ignite.math.functions.IgniteFunction; +import org.apache.ignite.math.impls.CacheUtils; +import org.apache.ignite.math.impls.storage.matrix.SparseDistributedMatrixStorage; + +/** + * Sparse distributed matrix implementation based on data grid. + * + * Unlike {@link CacheMatrix} that is based on existing cache, this implementation creates distributed + * cache internally and doesn't rely on pre-existing cache. + * + * You also need to call {@link #destroy()} to remove the underlying cache when you no longer need this + * matrix. + * + * <b>Currently fold supports only commutative operations.<b/> + */ +public class SparseDistributedMatrix extends AbstractMatrix implements StorageConstants { + /** + * + */ + public SparseDistributedMatrix() { + // No-op. + } + + /** + * @param rows + * @param cols + * @param stoMode + * @param acsMode + */ + public SparseDistributedMatrix(int rows, int cols, int stoMode, int acsMode) { + assert rows > 0; + assert cols > 0; + assertAccessMode(acsMode); + assertStorageMode(stoMode); + + setStorage(new SparseDistributedMatrixStorage(rows, cols, stoMode, acsMode)); + } + + /** + * + * + */ + private SparseDistributedMatrixStorage storage() { + return (SparseDistributedMatrixStorage)getStorage(); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param d + */ + @Override public Matrix divide(double d) { + return mapOverValues((Double v) -> v / d); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param x + */ + @Override public Matrix plus(double x) { + return mapOverValues((Double v) -> v + x); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param x + */ + @Override public Matrix times(double x) { + return mapOverValues((Double v) -> v * x); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double val) { + return mapOverValues((Double v) -> val); + } + + /** {@inheritDoc} */ + @Override public Matrix map(IgniteDoubleFunction<Double> fun) { + return mapOverValues(fun::apply); + } + + /** + * @param mapper + */ + private Matrix mapOverValues(IgniteFunction<Double, Double> mapper) { + CacheUtils.sparseMap(storage().cache().getName(), mapper); + + return this; + } + + /** {@inheritDoc} */ + @Override public double sum() { + return CacheUtils.sparseSum(storage().cache().getName()); + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + return CacheUtils.sparseMax(storage().cache().getName()); + } + + /** {@inheritDoc} */ + @Override public double minValue() { + return CacheUtils.sparseMin(storage().cache().getName()); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrix.java new file mode 100644 index 0000000..cb08939 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/SparseLocalOnHeapMatrix.java @@ -0,0 +1,72 @@ +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.StorageConstants; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.impls.storage.matrix.SparseLocalOnHeapMatrixStorage; +import org.apache.ignite.math.impls.vector.SparseLocalVector; + +/** + * Sparse local onheap matrix with {@link SparseLocalVector} as rows. + */ +public class SparseLocalOnHeapMatrix extends AbstractMatrix implements StorageConstants { + /** + * + */ + public SparseLocalOnHeapMatrix() { + // No-op. + } + + /** + * Construct new {@link SparseLocalOnHeapMatrix}. + * + * By default storage sets in row optimized mode and in random access mode. + */ + public SparseLocalOnHeapMatrix(int rows, int cols) { + setStorage(mkStorage(rows, cols)); + } + + /** + * Create new {@link SparseLocalOnHeapMatrixStorage}. + */ + private MatrixStorage mkStorage(int rows, int cols) { + return new SparseLocalOnHeapMatrixStorage(rows, cols, StorageConstants.RANDOM_ACCESS_MODE, StorageConstants.ROW_STORAGE_MODE); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return new SparseLocalOnHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return new SparseLocalVector(crd, StorageConstants.RANDOM_ACCESS_MODE); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + Matrix cp = like(rowSize(), columnSize()); + + cp.assign(this); + + return cp; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/TransposedMatrixView.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/TransposedMatrixView.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/TransposedMatrixView.java new file mode 100644 index 0000000..9da909b --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/TransposedMatrixView.java @@ -0,0 +1,84 @@ +/* + * 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.matrix; + +import org.apache.ignite.math.Matrix; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.Vector; +import org.apache.ignite.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.math.impls.storage.matrix.MatrixDelegateStorage; + +/** + * Implements transposed view of the parent {@link Matrix}. + */ +public class TransposedMatrixView extends AbstractMatrix { + /** */ + public TransposedMatrixView() { + //No-op. + } + + /** + * @param mtx Parent matrix. + */ + public TransposedMatrixView(Matrix mtx) { + this(mtx == null ? null : mtx.getStorage()); + } + + /** */ + private TransposedMatrixView(MatrixStorage sto) { + super(new MatrixDelegateStorage(sto, 0, 0, + sto == null ? 0 : sto.rowSize(), sto == null ? 0 : sto.columnSize())); + } + + /** {@inheritDoc} */ + @Override protected void storageSet(int row, int col, double v) { + super.storageSet(col, row, v); + } + + /** {@inheritDoc} */ + @Override protected double storageGet(int row, int col) { + return super.storageGet(col, row); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return getStorage().columnSize(); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return getStorage().rowSize(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + MatrixDelegateStorage sto = (MatrixDelegateStorage)getStorage(); + + return new TransposedMatrixView(sto.delegate()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/package-info.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/package-info.java new file mode 100644 index 0000000..75d7532 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/matrix/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Contains several matrix implementations. + */ +package org.apache.ignite.math.impls.matrix; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/package-info.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/package-info.java new file mode 100644 index 0000000..f1b2e36 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Contains specific implementations for core algebra. + */ +package org.apache.ignite.math.impls; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/ArrayMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/ArrayMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/ArrayMatrixStorage.java new file mode 100644 index 0000000..eb65b1d --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/ArrayMatrixStorage.java @@ -0,0 +1,161 @@ +/* + * 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.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.math.MatrixStorage; + +/** + * Array based {@link MatrixStorage} implementation. + */ +public class ArrayMatrixStorage implements MatrixStorage { + /** Backing data array. */ + private double[][] data; + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** + * + */ + public ArrayMatrixStorage() { + // No-op. + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + */ + public ArrayMatrixStorage(int rows, int cols) { + assert rows > 0; + assert cols > 0; + + this.data = new double[rows][cols]; + this.rows = rows; + this.cols = cols; + } + + /** + * @param data Backing data array. + */ + public ArrayMatrixStorage(double[][] data) { + assert data != null; + assert data[0] != null; + + this.data = data; + this.rows = data.length; + this.cols = data[0].length; + + assert rows > 0; + assert cols > 0; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return data[x][y]; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + data[x][y] = v; + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return true; + } + + /** {@inheritDoc} */ + @Override public double[][] data() { + return data; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(rows); + out.writeInt(cols); + + out.writeObject(data); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + + data = (double[][])in.readObject(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res += res * 37 + rows; + res += res * 37 + cols; + res += res * 37 + Arrays.deepHashCode(data); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + ArrayMatrixStorage that = (ArrayMatrixStorage)o; + + return Arrays.deepEquals(data, that.data); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/CacheMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/CacheMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/CacheMatrixStorage.java new file mode 100644 index 0000000..7aefa2c --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/CacheMatrixStorage.java @@ -0,0 +1,180 @@ +/* + * 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.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.math.MatrixKeyMapper; +import org.apache.ignite.math.MatrixStorage; +import org.apache.ignite.math.ValueMapper; + +/** + * Matrix storage based on arbitrary cache and key and value mapping functions. + */ +public class CacheMatrixStorage<K, V> implements MatrixStorage { + /** */ private int rows; + /** */ private int cols; + /** */ private IgniteCache<K, V> cache; + /** */ private MatrixKeyMapper<K> keyMapper; + /** */ private ValueMapper<V> valMapper; + + /** + * + */ + public CacheMatrixStorage() { + // No-op. + } + + /** + * @param rows + * @param cols + * @param cache + * @param keyMapper + * @param valMapper + */ + public CacheMatrixStorage(int rows, int cols, IgniteCache<K, V> cache, MatrixKeyMapper<K> keyMapper, + ValueMapper<V> valMapper) { + assert rows > 0; + assert cols > 0; + assert cache != null; + assert keyMapper != null; + assert valMapper != null; + + this.rows = rows; + this.cols = cols; + this.cache = cache; + this.keyMapper = keyMapper; + this.valMapper = valMapper; + } + + /** + * @return Ignite cache. + */ + public IgniteCache<K, V> cache() { + return cache; + } + + /** + * @return Key mapper. + */ + public MatrixKeyMapper<K> keyMapper() { + return keyMapper; + } + + /** + * @return Value mapper. + */ + public ValueMapper<V> valueMapper() { + return valMapper; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return valMapper.toDouble(cache.get(keyMapper.apply(x, y))); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + cache.put(keyMapper.apply(x, y), valMapper.fromDouble(v)); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(rows); + out.writeInt(cols); + out.writeUTF(cache.getName()); + out.writeObject(keyMapper); + out.writeObject(valMapper); + } + + /** {@inheritDoc} */ + @SuppressWarnings({"unchecked"}) + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + cache = Ignition.localIgnite().getOrCreateCache(in.readUTF()); + keyMapper = (MatrixKeyMapper<K>)in.readObject(); + valMapper = (ValueMapper<V>)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + rows; + res = res * 37 + cols; + res = res * 37 + cache.hashCode(); + res = res * 37 + keyMapper.hashCode(); + res = res * 37 + valMapper.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + CacheMatrixStorage that = (CacheMatrixStorage)o; + + return (cache != null ? cache.equals(that.cache) : that.cache == null) && + (keyMapper != null ? keyMapper.equals(that.keyMapper) : that.keyMapper == null) && + (valMapper != null ? valMapper.equals(that.valMapper) : that.valMapper == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/732dfea9/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java new file mode 100644 index 0000000..6695bc2 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/math/impls/storage/matrix/DenseOffHeapMatrixStorage.java @@ -0,0 +1,197 @@ +/* + * 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.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.math.MatrixStorage; + +/** + * Local, dense off-heap matrix storage. + */ +public class DenseOffHeapMatrixStorage implements MatrixStorage { + /** */ private int rows; + /** */ private int cols; + /** */ private transient long ptr; + //TODO: temp solution. + /** */ private int ptrInitHash; + + /** */ + public DenseOffHeapMatrixStorage() { + // No-op. + } + + /** */ + public DenseOffHeapMatrixStorage(int rows, int cols) { + assert rows > 0; + assert cols > 0; + + this.rows = rows; + this.cols = cols; + + allocateMemory(rows, cols); + } + + /** */ + public DenseOffHeapMatrixStorage(double[][] data) { + assert data != null; + assert data[0] != null; + + this.rows = data.length; + this.cols = data[0].length; + + assert rows > 0; + assert cols > 0; + + allocateMemory(rows, cols); + + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + set(i, j, data[i][j]); + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return GridUnsafe.getDouble(pointerOffset(x, y)); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + GridUnsafe.putDouble(pointerOffset(x, y), v); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public double[][] data() { + return null; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(rows); + out.writeInt(cols); + out.writeInt(ptrInitHash); + + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + out.writeDouble(get(i, j)); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + + allocateMemory(rows, cols); + + ptrInitHash = in.readInt(); + + for (int i = 0; i < rows; i++) + for (int j = 0; j < cols; j++) + set(i, j, in.readDouble()); + } + + /** {@inheritDoc} */ + @Override public void destroy() { + GridUnsafe.freeMemory(ptr); + } + + /** {@inheritDoc} */ + private long pointerOffset(int x, int y) { + return ptr + x * cols * Double.BYTES + y * Double.BYTES; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + return obj != null && + getClass().equals(obj.getClass()) && + (rows == ((DenseOffHeapMatrixStorage)obj).rows) && + (cols == ((DenseOffHeapMatrixStorage)obj).cols) && + (rows == 0 || cols == 0 || ptr == ((DenseOffHeapMatrixStorage)obj).ptr || isMemoryEquals((DenseOffHeapMatrixStorage)obj)); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + rows; + res = res * 37 + cols; + res = res * 37 + ptrInitHash; + + return res; + } + + /** */ + private boolean isMemoryEquals(DenseOffHeapMatrixStorage otherStorage) { + boolean res = true; + + for (int i = 0; i < otherStorage.rows; i++) { + for (int j = 0; j < otherStorage.cols; j++) { + if (Double.compare(get(i, j), otherStorage.get(i, j)) != 0) { + res = false; + break; + } + } + } + + return res; + } + + /** */ + private void allocateMemory(int rows, int cols) { + ptr = GridUnsafe.allocateMemory(rows * cols * Double.BYTES); + + ptrInitHash = Long.hashCode(ptr); + } +}
