http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/PivotedMatrixView.java new file mode 100644 index 0000000..b9a3b17 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.exceptions.IndexException; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.math.impls.storage.matrix.PivotedMatrixStorage; +import org.apache.ignite.ml.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/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/RandomMatrix.java new file mode 100644 index 0000000..ece4ca9 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.impls.storage.matrix.RandomMatrixStorage; +import org.apache.ignite.ml.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/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java new file mode 100644 index 0000000..8a7cffe --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.matrix; + +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.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.math.functions.IgniteDoubleFunction; +import org.apache.ignite.ml.math.functions.IgniteFunction; +import org.apache.ignite.ml.math.impls.CacheUtils; +import org.apache.ignite.ml.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/d78e071a/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 new file mode 100644 index 0000000..d711295 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.matrix; + +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.impls.storage.matrix.SparseLocalOnHeapMatrixStorage; +import org.apache.ignite.ml.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/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/TransposedMatrixView.java new file mode 100644 index 0000000..309570b --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.matrix; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.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/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/package-info.java new file mode 100644 index 0000000..9eabf80 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.matrix; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/package-info.java new file mode 100644 index 0000000..d531014 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/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 new file mode 100644 index 0000000..397bf93 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.ml.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/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/CacheMatrixStorage.java new file mode 100644 index 0000000..510c4cf --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.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.ml.math.MatrixKeyMapper; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.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/d78e071a/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 new file mode 100644 index 0000000..74952a9 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/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.ml.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.ml.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); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java new file mode 100644 index 0000000..9daacee --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/DiagonalMatrixStorage.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; + +/** + * {@link MatrixStorage} implementation for diagonal Matrix view. + */ +public class DiagonalMatrixStorage implements MatrixStorage { + /** Backing vector for matrix diagonal. */ + private Vector diagonal; + + /** + * + */ + public DiagonalMatrixStorage() { + // No-op. + } + + /** + * @param diagonal Backing {@link Vector} for matrix diagonal. + */ + public DiagonalMatrixStorage(Vector diagonal) { + assert diagonal != null; + + this.diagonal = diagonal; + } + + /** + * + */ + public Vector diagonal() { + return diagonal; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return x == y ? diagonal.get(x) : 0.0; + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + if (x == y) + diagonal.set(x, v); + else + throw new UnsupportedOperationException("Can't set off-diagonal element."); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return diagonal.size(); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return diagonal.size(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(diagonal); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + diagonal = (Vector)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return diagonal.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return diagonal.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return diagonal.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return diagonal.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + diagonal.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DiagonalMatrixStorage that = (DiagonalMatrixStorage)o; + + return diagonal.equals(that.diagonal); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java new file mode 100644 index 0000000..acd7c29 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/FunctionMatrixStorage.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.math.functions.IntIntDoubleToVoidFunction; +import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction; + +/** + * Read-only or read-write function-based matrix storage. + */ +public class FunctionMatrixStorage implements MatrixStorage { + /** */ private int rows; + /** */ private int cols; + + /** */ private IntIntToDoubleFunction getFunc; + /** */ private IntIntDoubleToVoidFunction setFunc; + + /** + * + */ + public FunctionMatrixStorage() { + // No-op. + } + + /** + * @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 FunctionMatrixStorage(int rows, int cols, IntIntToDoubleFunction getFunc, + IntIntDoubleToVoidFunction setFunc) { + assert rows > 0; + assert cols > 0; + assert getFunc != null; + + this.rows = rows; + this.cols = cols; + this.getFunc = getFunc; + this.setFunc = setFunc; + } + + /** + * @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 FunctionMatrixStorage(int rows, int cols, IntIntToDoubleFunction getFunc) { + this(rows, cols, getFunc, null); + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return getFunc.apply(x, y); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + if (setFunc != null) + setFunc.apply(x, y, v); + else + throw new UnsupportedOperationException("Cannot set into read-only matrix."); + } + + /** + * + */ + public IntIntToDoubleFunction getFunction() { + return getFunc; + } + + /** + * + */ + public IntIntDoubleToVoidFunction setFunction() { + return setFunc; + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(setFunc); + out.writeObject(getFunc); + out.writeInt(rows); + out.writeInt(cols); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + setFunc = (IntIntDoubleToVoidFunction)in.readObject(); + getFunc = (IntIntToDoubleFunction)in.readObject(); + rows = in.readInt(); + cols = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + FunctionMatrixStorage that = (FunctionMatrixStorage)o; + + return rows == that.rows && cols == that.cols + && (getFunc != null ? getFunc.equals(that.getFunc) : that.getFunc == null) + && (setFunc != null ? setFunc.equals(that.setFunc) : that.setFunc == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = rows; + + res = 31 * res + cols; + res = 31 * res + (getFunc != null ? getFunc.hashCode() : 0); + res = 31 * res + (setFunc != null ? setFunc.hashCode() : 0); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/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 new file mode 100644 index 0000000..1f77d0f --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MatrixDelegateStorage.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.MatrixStorage; + +/** + * {@link MatrixStorage} implementation that delegates to parent matrix. + */ +public class MatrixDelegateStorage implements MatrixStorage { + /** Parent matrix storage. */ + private MatrixStorage sto; + + /** Row offset in the parent matrix. */ + private int rowOff; + /** Column offset in the parent matrix. */ + private int colOff; + + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** + * + */ + public MatrixDelegateStorage() { + // No-op. + } + + /** + * @param sto Backing parent storage. + * @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 MatrixDelegateStorage(MatrixStorage sto, int rowOff, int colOff, int rows, int cols) { + assert sto != null; + assert rowOff >= 0; + assert colOff >= 0; + assert rows > 0; + assert cols > 0; + + this.sto = sto; + + this.rowOff = rowOff; + this.colOff = colOff; + + this.rows = rows; + this.cols = cols; + } + + /** + * + */ + public MatrixStorage delegate() { + return sto; + } + + /** + * + */ + public int rowOffset() { + return rowOff; + } + + /** + * + */ + public int columnOffset() { + return colOff; + } + + /** + * + */ + public int rowsLength() { + return rows; + } + + /** + * + */ + public int columnsLength() { + return cols; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return sto.get(rowOff + x, colOff + y); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + sto.set(rowOff + x, colOff + y, v); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return cols; + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return rows; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased() && rowOff == 0 && colOff == 0; + } + + /** {@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 double[][] data() { + return sto.data(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + + out.writeInt(rowOff); + out.writeInt(colOff); + + out.writeInt(rows); + out.writeInt(cols); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (MatrixStorage)in.readObject(); + + rowOff = in.readInt(); + colOff = in.readInt(); + + rows = in.readInt(); + cols = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + rows; + res = res * 37 + cols; + res = res * 37 + rowOff; + res = res * 37 + colOff; + res = res * 37 + sto.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + MatrixDelegateStorage that = (MatrixDelegateStorage)o; + + return rows == that.rows && cols == that.cols && rowOff == that.rowOff && colOff == that.colOff && + (sto != null ? sto.equals(that.sto) : that.sto == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java new file mode 100644 index 0000000..ab9b871 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/PivotedMatrixStorage.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.ml.math.MatrixStorage; + +/** + * Pivoted (index mapped) view over another matrix storage implementation. + */ +public class PivotedMatrixStorage implements MatrixStorage { + /** Matrix storage. */ + private MatrixStorage sto; + + /** */ + private int[] rowPivot; + /** */ + private int[] colPivot; + /** */ + private int[] rowUnpivot; + /** */ + private int[] colUnpivot; + + /** + * + */ + public PivotedMatrixStorage() { + // No-op. + } + + /** + * @param sto Matrix storage. + * @param rowPivot Pivot array for rows. + * @param colPivot Pivot array for columns. + */ + public PivotedMatrixStorage(MatrixStorage sto, int[] rowPivot, int[] colPivot) { + assert sto != null; + assert rowPivot != null; + assert colPivot != null; + + this.sto = sto; + this.rowPivot = rowPivot; + this.colPivot = colPivot; + + rowUnpivot = invert(rowPivot); + colUnpivot = invert(colPivot); + } + + /** + * + */ + public int[] rowPivot() { + return rowPivot; + } + + /** + * + */ + public int[] columnPivot() { + return colPivot; + } + + /** + * + */ + public int[] rowUnpivot() { + return rowUnpivot; + } + + /** + * + */ + public int[] columnUnpivot() { + return colUnpivot; + } + + /** + * @param sto Matrix storage. + * @param pivot Pivot array. + */ + public PivotedMatrixStorage(MatrixStorage sto, int[] pivot) { + this(sto, pivot, pivot == null ? null : java.util.Arrays.copyOf(pivot, pivot.length)); + } + + /** + * @param sto Matrix storage. + */ + public PivotedMatrixStorage(MatrixStorage sto) { + this(sto, sto == null ? null : identityPivot(sto.rowSize()), sto == null ? null : identityPivot(sto.columnSize())); + } + + /** + * @param i First row index to swap. + * @param j Second row index to swap. + */ + public void swapRows(int i, int j) { + if (i != j) { + int tmp = rowPivot[i]; + + rowPivot[i] = rowPivot[j]; + rowPivot[j] = tmp; + + rowUnpivot[rowPivot[i]] = i; + rowUnpivot[rowPivot[j]] = j; + } + } + + /** + * @param i First column index to swap. + * @param j Second column index to swap. + */ + public void swapColumns(int i, int j) { + if (i != j) { + int tmp = colPivot[i]; + + colPivot[i] = colPivot[j]; + colPivot[j] = tmp; + + colUnpivot[colPivot[i]] = i; + colUnpivot[colPivot[j]] = j; + } + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + return sto.get(rowPivot[x], colPivot[y]); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + sto.set(rowPivot[x], colPivot[y], v); + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return sto.columnSize(); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return sto.rowSize(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(rowPivot); + out.writeObject(colPivot); + out.writeObject(rowUnpivot); + out.writeObject(colUnpivot); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (MatrixStorage)in.readObject(); + rowPivot = (int[])in.readObject(); + colPivot = (int[])in.readObject(); + rowUnpivot = (int[])in.readObject(); + colUnpivot = (int[])in.readObject(); + } + + /** {@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 false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + sto.hashCode(); + res = res * 37 + Arrays.hashCode(rowPivot); + res = res * 37 + Arrays.hashCode(rowUnpivot); + res = res * 37 + Arrays.hashCode(colPivot); + res = res * 37 + Arrays.hashCode(colUnpivot); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + PivotedMatrixStorage that = (PivotedMatrixStorage)obj; + + return Arrays.equals(rowPivot, that.rowPivot) && Arrays.equals(rowUnpivot, that.rowUnpivot) + && Arrays.equals(colPivot, that.colPivot) && Arrays.equals(colUnpivot, that.colUnpivot) + && (sto != null ? sto.equals(that.sto) : that.sto == null); + } + + /** + * @param n Pivot array length. + */ + private static int[] identityPivot(int n) { + int[] pivot = new int[n]; + + for (int i = 0; i < n; i++) + pivot[i] = i; + + return pivot; + } + + /** + * @param pivot Pivot array to be inverted. + */ + private static int[] invert(int[] pivot) { + int[] x = new int[pivot.length]; + + for (int i = 0; i < pivot.length; i++) + x[pivot[i]] = i; + + return x; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java new file mode 100644 index 0000000..7e0ef27 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/RandomMatrixStorage.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.MurmurHash; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; + +/** + * {@link MatrixStorage} implementation with random values in the matrix elements. + */ +public class RandomMatrixStorage implements MatrixStorage { + /** */ + private static final int PRIME1 = 104047; + /** */ + private static final int PRIME2 = 101377; + /** */ + private static final int PRIME3 = 64661; + /** */ + private static final long SCALE = 1L << 32; + + /** Random generation seed. */ + private int seed; + + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** Whether fast hash is used, in {@link #get(int, int)}. */ + private boolean fastHash; + + /** + * For externalization. + */ + public RandomMatrixStorage() { + // No-op. + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param fastHash Whether fast hash is used. + */ + public RandomMatrixStorage(int rows, int cols, boolean fastHash) { + assert rows > 0; + assert cols > 0; + + this.rows = rows; + this.cols = cols; + this.fastHash = fastHash; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + if (!fastHash) { + ByteBuffer buf = ByteBuffer.allocate(8); + + buf.putInt(x); + buf.putInt(y); + buf.flip(); + + return (MurmurHash.hash64A(buf, seed) & (SCALE - 1)) / (double)SCALE; + } + else + // This isn't a fantastic random number generator, but it is just fine for random projections. + return ((((x * PRIME1) + y * PRIME2 + x * y * PRIME3) & 8) * 0.25) - 1; + } + + /** + * + */ + public boolean isFastHash() { + return fastHash; + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + throw new UnsupportedOperationException("Random matrix storage is a read-only storage."); + } + + /** {@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.writeInt(seed); + out.writeBoolean(fastHash); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + seed = in.readInt(); + fastHash = in.readBoolean(); + } + + /** {@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 boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + Boolean.hashCode(fastHash); + res = res * 37 + seed; + res = res * 37 + cols; + res = res * 37 + rows; + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + RandomMatrixStorage that = (RandomMatrixStorage)o; + + return rows == that.rows && cols == that.cols && seed == that.seed && fastHash == that.fastHash; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/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 new file mode 100644 index 0000000..cf200c7 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java @@ -0,0 +1,290 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Map; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.CachePeekMode; +import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.StorageConstants; +import org.apache.ignite.ml.math.impls.CacheUtils; +import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix; + +/** + * {@link MatrixStorage} implementation for {@link SparseDistributedMatrix}. + */ +public class SparseDistributedMatrixStorage extends CacheUtils implements MatrixStorage, StorageConstants { + /** Amount of rows in the matrix. */ + private int rows; + /** Amount of columns in the matrix. */ + private int cols; + + /** Row or column based storage mode. */ + private int stoMode; + /** Random or sequential access mode. */ + private int acsMode; + + /** Actual distributed storage. */ + private IgniteCache< + Integer /* Row or column index. */, + Map<Integer, Double> /* Map-based row or column. */ + > cache = null; + + /** + * + */ + public SparseDistributedMatrixStorage() { + // No-op. + } + + /** + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param stoMode Row or column based storage mode. + * @param acsMode Random or sequential access mode. + */ + public SparseDistributedMatrixStorage(int rows, int cols, int stoMode, int acsMode) { + assert rows > 0; + assert cols > 0; + assertAccessMode(acsMode); + assertStorageMode(stoMode); + + this.rows = rows; + this.cols = cols; + this.stoMode = stoMode; + this.acsMode = acsMode; + + cache = newCache(); + } + + /** + * + * + */ + private IgniteCache<Integer, Map<Integer, Double>> newCache() { + CacheConfiguration<Integer, Map<Integer, Double>> cfg = new CacheConfiguration<>(); + + // Assume 10% density. + cfg.setStartSize(Math.max(1024, (rows * cols) / 10)); + + // Write to primary. + cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC); + + // Atomic transactions only. + cfg.setAtomicityMode(CacheAtomicityMode.ATOMIC); + + // No eviction. + cfg.setEvictionPolicy(null); + + // No copying of values. + cfg.setCopyOnRead(false); + + // Cache is partitioned. + cfg.setCacheMode(CacheMode.PARTITIONED); + + // Random cache name. + cfg.setName(new IgniteUuid().shortString()); + + return Ignition.localIgnite().getOrCreateCache(cfg); + } + + /** + * + * + */ + public IgniteCache<Integer, Map<Integer, Double>> cache() { + return cache; + } + + /** + * + * + */ + public int accessMode() { + return acsMode; + } + + /** + * + * + */ + public int storageMode() { + return stoMode; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + if (stoMode == ROW_STORAGE_MODE) + return matrixGet(cache.getName(), x, y); + else + return matrixGet(cache.getName(), y, x); + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + if (stoMode == ROW_STORAGE_MODE) + matrixSet(cache.getName(), x, y, v); + else + matrixSet(cache.getName(), y, x, v); + } + + /** + * Distributed matrix get. + * + * @param cacheName Matrix's cache. + * @param a Row or column index. + * @param b Row or column index. + * @return Matrix value at (a, b) index. + */ + private double matrixGet(String cacheName, int a, int b) { + // Remote get from the primary node (where given row or column is stored locally). + return ignite().compute(groupForKey(cacheName, a)).call(() -> { + IgniteCache<Integer, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(cacheName); + + // Local get. + Map<Integer, Double> map = cache.localPeek(a, CachePeekMode.PRIMARY); + + return (map == null || !map.containsKey(b)) ? 0.0 : map.get(b); + }); + } + + /** + * Distributed matrix set. + * + * @param cacheName Matrix's cache. + * @param a Row or column index. + * @param b Row or column index. + * @param v New value to set. + */ + private void matrixSet(String cacheName, int a, int b, double v) { + // Remote set on the primary node (where given row or column is stored locally). + ignite().compute(groupForKey(cacheName, a)).run(() -> { + IgniteCache<Integer, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(cacheName); + + // Local get. + Map<Integer, Double> map = cache.localPeek(a, CachePeekMode.PRIMARY); + + if (map == null) + map = acsMode == SEQUENTIAL_ACCESS_MODE ? new Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap(); + + if (v != 0.0) + map.put(b, v); + else if (map.containsKey(b)) + map.remove(b); + + // Local put. + cache.put(a, map); + }); + } + + /** {@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.writeInt(acsMode); + out.writeInt(stoMode); + out.writeUTF(cache.getName()); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + acsMode = in.readInt(); + stoMode = in.readInt(); + cache = ignite().getOrCreateCache(in.readUTF()); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return acsMode == SEQUENTIAL_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return acsMode == RANDOM_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** Destroy underlying cache. */ + @Override public void destroy() { + cache.destroy(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + cols; + res = res * 37 + rows; + res = res * 37 + acsMode; + res = res * 37 + stoMode; + res = res * 37 + cache.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + SparseDistributedMatrixStorage that = (SparseDistributedMatrixStorage)obj; + + return rows == that.rows && cols == that.cols && acsMode == that.acsMode && stoMode == that.stoMode + && (cache != null ? cache.equals(that.cache) : that.cache == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/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 new file mode 100644 index 0000000..4530900 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseLocalOnHeapMatrixStorage.java @@ -0,0 +1,226 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.storage.matrix; + +import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.HashMap; +import java.util.Map; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.StorageConstants; + +/** + * Storage for sparse, local, on-heap matrix. + */ +public class SparseLocalOnHeapMatrixStorage implements MatrixStorage, StorageConstants { + /** Default zero value. */ + private static final double DEFAULT_VALUE = 0.0; + + /** */ private int rows; + /** */ private int cols; + + /** */ private int acsMode; + /** */ private int stoMode; + + /** Actual map storage. */ + private Map<Integer, Map<Integer, Double>> sto; + + /** */ + public SparseLocalOnHeapMatrixStorage() { + // No-op. + } + + /** */ + public SparseLocalOnHeapMatrixStorage(int rows, int cols, int acsMode, int stoMode) { + assert rows > 0; + assert cols > 0; + assertAccessMode(acsMode); + assertStorageMode(stoMode); + + this.rows = rows; + this.cols = cols; + this.acsMode = acsMode; + this.stoMode = stoMode; + + sto = new HashMap<>(); + } + + /** + * + * + */ + public int getStorageMode() { + return stoMode; + } + + /** + * + * + */ + public int getAccessMode() { + return acsMode; + } + + /** {@inheritDoc} */ + @Override public double get(int x, int y) { + if (stoMode == ROW_STORAGE_MODE) { + Map<Integer, Double> row = sto.get(x); + + if (row != null) { + Double val = row.get(y); + + if (val != null) + return val; + } + + return DEFAULT_VALUE; + } + else { + Map<Integer, Double> col = sto.get(y); + + if (col != null) { + Double val = col.get(x); + + if (val != null) + return val; + } + + return DEFAULT_VALUE; + } + } + + /** {@inheritDoc} */ + @Override public void set(int x, int y, double v) { + // Ignore default values (currently 0.0). + if (v != DEFAULT_VALUE) { + if (stoMode == ROW_STORAGE_MODE) { + Map<Integer, Double> row = sto.computeIfAbsent(x, k -> + acsMode == SEQUENTIAL_ACCESS_MODE ? new Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap()); + + row.put(y, v); + } + else { + Map<Integer, Double> col = sto.computeIfAbsent(y, k -> + acsMode == SEQUENTIAL_ACCESS_MODE ? new Int2DoubleRBTreeMap() : new Int2DoubleOpenHashMap()); + + col.put(x, v); + } + } + else { + if (stoMode == ROW_STORAGE_MODE) { + if (sto.containsKey(x)) { + Map<Integer, Double> row = sto.get(x); + + if (row.containsKey(y)) + row.remove(y); + } + + } + else { + if (sto.containsKey(y)) { + Map<Integer, Double> col = sto.get(y); + + if (col.containsKey(x)) + col.remove(x); + } + } + } + } + + /** {@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.writeInt(acsMode); + out.writeInt(stoMode); + out.writeObject(sto); + } + + /** {@inheritDoc} */ + @SuppressWarnings({"unchecked"}) + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + rows = in.readInt(); + cols = in.readInt(); + acsMode = in.readInt(); + stoMode = in.readInt(); + sto = (Map<Integer, Map<Integer, Double>>)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return acsMode == SEQUENTIAL_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return acsMode == RANDOM_ACCESS_MODE; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@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 + sto.hashCode(); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SparseLocalOnHeapMatrixStorage that = (SparseLocalOnHeapMatrixStorage)o; + + return rows == that.rows && cols == that.cols && acsMode == that.acsMode && stoMode == that.stoMode + && (sto != null ? sto.equals(that.sto) : that.sto == null); + } +}