http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/package-info.java new file mode 100644 index 0000000..e0a760c --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/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 specific implementations for matrix storage models. + */ +package org.apache.ignite.ml.math.impls.storage.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/storage/vector/ArrayVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/ArrayVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/ArrayVectorStorage.java new file mode 100644 index 0000000..dc23611 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/ArrayVectorStorage.java @@ -0,0 +1,135 @@ +/* + * 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.vector; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.ml.math.VectorStorage; + +/** + * Array based {@link VectorStorage} implementation. + */ +public class ArrayVectorStorage implements VectorStorage { + /** Backing data array. */ + private double[] data; + + /** + * IMPL NOTE required by {@link Externalizable}. + */ + public ArrayVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + */ + public ArrayVectorStorage(int size) { + assert size > 0; + + data = new double[size]; + } + + /** + * @param data Backing data array. + */ + public ArrayVectorStorage(double[] data) { + assert data != null; + + this.data = data; + } + + /** {@inheritDoc} */ + @Override public int size() { + return data == null ? 0 : data.length; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return data[i]; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + data[i] = v; + } + + /** {@inheritDoc}} */ + @Override public boolean isArrayBased() { + return true; + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return data; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@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 writeExternal(ObjectOutput out) throws IOException { + out.writeObject(data); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + data = (double[])in.readObject(); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + Arrays.hashCode(data); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (this == obj) + return true; + + if (obj == null || getClass() != obj.getClass()) + return false; + + ArrayVectorStorage that = (ArrayVectorStorage)obj; + + return Arrays.equals(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/vector/CacheVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/CacheVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/CacheVectorStorage.java new file mode 100644 index 0000000..7aa317c --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/CacheVectorStorage.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.vector; + +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.ValueMapper; +import org.apache.ignite.ml.math.VectorKeyMapper; +import org.apache.ignite.ml.math.VectorStorage; + +/** + * Vector storage based on existing cache and index and value mapping functions. + */ +public class CacheVectorStorage<K, V> implements VectorStorage { + /** Storage size. */ + private int size; + /** Key mapper. */ + private VectorKeyMapper<K> keyMapper; + /** Value mapper. */ + private ValueMapper<V> valMapper; + /** Underlying ignite cache. */ + private IgniteCache<K, V> cache; + + /** + * + */ + public CacheVectorStorage() { + // No-op. + } + + /** + * @param size + * @param cache + * @param keyMapper + * @param valMapper + */ + public CacheVectorStorage(int size, IgniteCache<K, V> cache, VectorKeyMapper<K> keyMapper, + ValueMapper<V> valMapper) { + assert size > 0; + assert cache != null; + assert keyMapper != null; + assert valMapper != null; + + this.size = size; + this.cache = cache; + this.keyMapper = keyMapper; + this.valMapper = valMapper; + } + + /** + * + * + */ + public IgniteCache<K, V> cache() { + return cache; + } + + /** + * + * + */ + public VectorKeyMapper<K> keyMapper() { + return keyMapper; + } + + /** + * + * + */ + public ValueMapper<V> valueMapper() { + return valMapper; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return valMapper.toDouble(cache.get(keyMapper.apply(i))); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + cache.put(keyMapper.apply(i), valMapper.fromDouble(v)); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeObject(keyMapper); + out.writeObject(valMapper); + out.writeUTF(cache.getName()); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + keyMapper = (VectorKeyMapper<K>)in.readObject(); + valMapper = (ValueMapper<V>)in.readObject(); + cache = Ignition.localIgnite().getOrCreateCache(in.readUTF()); + } + + /** {@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 + size(); + res = res * 37 + keyMapper.hashCode(); + res = res * 37 + valMapper.hashCode(); + 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; + + CacheVectorStorage that = (CacheVectorStorage)obj; + + return size == that.size + && (keyMapper != null ? keyMapper.getClass().equals(that.keyMapper.getClass()) : that.keyMapper == null) + && (valMapper != null ? valMapper.getClass().equals(that.valMapper.getClass()) : that.valMapper == null) + && (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/vector/ConstantVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/ConstantVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/ConstantVectorStorage.java new file mode 100644 index 0000000..31469ea --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/ConstantVectorStorage.java @@ -0,0 +1,133 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; + +/** + * Constant read-only vector storage. + */ +public class ConstantVectorStorage implements VectorStorage { + /** */ private int size; + /** */ private double val; + + /** + * + */ + public ConstantVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + * @param val Value to set for vector elements. + */ + public ConstantVectorStorage(int size, double val) { + assert size > 0; + + this.size = size; + this.val = val; + } + + /** + * + * + */ + public double constant() { + return val; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return val; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + throw new UnsupportedOperationException("Can't set value into constant vector."); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeDouble(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + val = in.readDouble(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@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 + size; + res = res * 37 + Double.hashCode(val); + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + ConstantVectorStorage that = (ConstantVectorStorage)o; + + return size == that.size && val == that.val; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DelegateVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DelegateVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DelegateVectorStorage.java new file mode 100644 index 0000000..c431bdb --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DelegateVectorStorage.java @@ -0,0 +1,157 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.VectorStorage; + +/** + * {@link VectorStorage} implementation that delegates to parent matrix. + */ +public class DelegateVectorStorage implements VectorStorage { + /** Parent vector storage. */ + private VectorStorage sto; + + /** Offset in the parent vector. */ + private int off; + + /** Size of the vector. */ + private int len; + + /** + * + */ + public DelegateVectorStorage() { + // No-op. + } + + /** + * @param sto Vector storage to delegate to. + * @param off Offset in the parent vector. + * @param len Size of the vector. + */ + public DelegateVectorStorage(VectorStorage sto, int off, int len) { + assert sto != null; + assert off >= 0; + assert len > 0; + + this.sto = sto; + this.off = off; + this.len = len; + } + + /** */ + public VectorStorage delegate() { + return sto; + } + + /** */ + public int offset() { + return off; + } + + /** */ + public int length() { + return len; + } + + /** {@inheritDoc} */ + @Override public int size() { + return len; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return sto.get(off + i); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + sto.set(off + i, v); + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return sto.data(); + } + + /** {@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(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeInt(off); + out.writeInt(len); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (VectorStorage)in.readObject(); + off = in.readInt(); + len = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DelegateVectorStorage that = (DelegateVectorStorage)o; + + return len == that.len && off == that.off && (sto != null ? sto.equals(that.sto) : that.sto == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + off; + res = res * 37 + len; + res = res * 37 + sto.hashCode(); + + 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/vector/DenseLocalOffHeapVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java new file mode 100644 index 0000000..a9965cc --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/DenseLocalOffHeapVectorStorage.java @@ -0,0 +1,172 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.stream.IntStream; +import org.apache.ignite.internal.util.GridUnsafe; +import org.apache.ignite.ml.math.VectorStorage; + +/** + * Local, dense off-heap vector storage. + */ +public class DenseLocalOffHeapVectorStorage implements VectorStorage { + /** Vector size. */ + private int size; + + /** */ + private transient long ptr; + //TODO: temp solution. + /** */ + private int ptrInitHash; + + /** + * + */ + public DenseLocalOffHeapVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + */ + public DenseLocalOffHeapVectorStorage(int size) { + assert size > 0; + + this.size = size; + + allocateMemory(size); + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return GridUnsafe.getDouble(pointerOffset(i)); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + GridUnsafe.putDouble(pointerOffset(i), v); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return null; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@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 writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(ptrInitHash); + + for (int i = 0; i < size; i++) + out.writeDouble(get(i)); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + + allocateMemory(size); + + ptrInitHash = in.readInt(); + + for (int i = 0; i < size; i++) + set(i, in.readDouble()); + } + + /** {@inheritDoc} */ + @Override public void destroy() { + GridUnsafe.freeMemory(ptr); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + size; + res = res * 37 + ptrInitHash; + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DenseLocalOffHeapVectorStorage that = (DenseLocalOffHeapVectorStorage)o; + + return size == that.size && isMemoryEquals(that); + } + + /** */ + private boolean isMemoryEquals(DenseLocalOffHeapVectorStorage otherStorage) { + return IntStream.range(0, size).parallel().noneMatch(idx -> Double.compare(get(idx), otherStorage.get(idx)) != 0); + } + + /** + * Pointer offset for specific index. + * + * @param i Offset index. + */ + private long pointerOffset(int i) { + return ptr + i * Double.BYTES; + } + + /** */ + private void allocateMemory(int size) { + ptr = GridUnsafe.allocateMemory(size * 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/vector/FunctionVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/FunctionVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/FunctionVectorStorage.java new file mode 100644 index 0000000..0f13bb6 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/FunctionVectorStorage.java @@ -0,0 +1,141 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.math.functions.IgniteFunction; +import org.apache.ignite.ml.math.functions.IntDoubleToVoidFunction; + +/** + * Read-only or read-write function-based vector storage. + */ +public class FunctionVectorStorage implements VectorStorage { + /** */ private IgniteFunction<Integer, Double> getFunc; + /** */ private IntDoubleToVoidFunction setFunc; + /** */ private int size; + + /** + * + */ + public FunctionVectorStorage() { + // No-op. + } + + /** + * Creates read-only or read-write storage. + * + * @param size Cardinality of this vector storage. + * @param getFunc Get function. + * @param setFunc Optional set function ({@code null} for read-only storage). + */ + public FunctionVectorStorage(int size, IgniteFunction<Integer, Double> getFunc, IntDoubleToVoidFunction setFunc) { + assert size > 0; + assert getFunc != null; // At least get function is required. + + this.size = size; + this.getFunc = getFunc; + this.setFunc = setFunc; + } + + /** + * + * + */ + public IgniteFunction<Integer, Double> getFunction() { + return getFunc; + } + + /** + * + * + */ + public IntDoubleToVoidFunction setFunction() { + return setFunc; + } + + /** + * Creates read-only storage. + * + * @param size Cardinality of this vector storage. + * @param getFunc Get function. + */ + public FunctionVectorStorage(int size, IgniteFunction<Integer, Double> getFunc) { + this(size, getFunc, null); + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return getFunc.apply(i); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (setFunc != null) + setFunc.accept(i, v); + else + throw new UnsupportedOperationException("Cannot set into read-only vector."); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(setFunc); + out.writeObject(getFunc); + out.writeInt(size); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + setFunc = (IntDoubleToVoidFunction)in.readObject(); + getFunc = (IgniteFunction<Integer, Double>)in.readObject(); + size = 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; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/MatrixVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/MatrixVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/MatrixVectorStorage.java new file mode 100644 index 0000000..a7d7e26 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/MatrixVectorStorage.java @@ -0,0 +1,185 @@ +/* + * 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.vector; + +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.VectorStorage; +import org.apache.ignite.ml.math.exceptions.IndexException; + +/** + * Row, column or diagonal vector-based view of the matrix + */ +public class MatrixVectorStorage implements VectorStorage { + /** */ private Matrix parent; + + /** */ private int row; + /** */ private int col; + + /** */ private int rowStride; + /** */ private int colStride; + + /** */ private int size; + + /** + * + */ + public MatrixVectorStorage() { + // No-op. + } + + /** + * @param parent + * @param row + * @param col + * @param rowStride + * @param colStride + */ + public MatrixVectorStorage(Matrix parent, int row, int col, int rowStride, int colStride) { + assert parent != null; + assert rowStride >= 0; + assert colStride >= 0; + assert rowStride > 0 || colStride > 0; + + if (row < 0 || row >= parent.rowSize()) + throw new IndexException(row); + if (col < 0 || col >= parent.columnSize()) + throw new IndexException(col); + + this.parent = parent; + + this.row = row; + this.col = col; + + this.rowStride = rowStride; + this.colStride = colStride; + + this.size = getSize(); + } + + /** + * + * + */ + int row() { + return row; + } + + /** + * + * + */ + int column() { + return col; + } + + /** + * + * + */ + int rowStride() { + return rowStride; + } + + /** + * + * + */ + int columnStride() { + return colStride; + } + + /** + * + * + */ + private int getSize() { + if (rowStride != 0 && colStride != 0) { + int n1 = (parent.rowSize() - row) / rowStride; + int n2 = (parent.columnSize() - col) / colStride; + + return Math.min(n1, n2); + } + else if (rowStride > 0) + return (parent.rowSize() - row) / rowStride; + else + return (parent.columnSize() - col) / colStride; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return parent.get(row + i * rowStride, col + i * colStride); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + parent.set(row + i * rowStride, col + i * colStride, v); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return parent.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return parent.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return parent.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return parent.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(parent); + out.writeInt(row); + out.writeInt(col); + out.writeInt(rowStride); + out.writeInt(colStride); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + parent = (Matrix)in.readObject(); + row = in.readInt(); + col = in.readInt(); + rowStride = in.readInt(); + colStride = in.readInt(); + + size = getSize(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/PivotedVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/PivotedVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/PivotedVectorStorage.java new file mode 100644 index 0000000..a524838 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/PivotedVectorStorage.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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import org.apache.ignite.ml.math.VectorStorage; + +/** + * Pivoted (index mapped) view over another vector storage implementation. + */ +public class PivotedVectorStorage implements VectorStorage { + /** */ private VectorStorage sto; + + /** */ private int[] pivot; + /** */ private int[] unpivot; + + /** + * @param pivot Pivot array. + */ + private static int[] reverse(int[] pivot) { + int[] res = new int[pivot.length]; + + for (int i = 0; i < pivot.length; i++) + res[pivot[i]] = i; + + return res; + } + + /** + * + * + */ + public int[] pivot() { + return pivot; + } + + /** + * + * + */ + public int[] unpivot() { + return unpivot; + } + + /** + * @param sto Backing vector storage. + * @param pivot Mapping from external index to internal. + * @param unpivot Mapping from internal index to external. + */ + public PivotedVectorStorage(VectorStorage sto, int[] pivot, int[] unpivot) { + assert sto != null; + assert pivot != null; + assert unpivot != null; + + this.sto = sto; + this.pivot = pivot; + this.unpivot = unpivot; + } + + /** + * @param sto Backing vector storage. + * @param pivot Mapping from external index to internal. + */ + public PivotedVectorStorage(VectorStorage sto, int[] pivot) { + this(sto, pivot, reverse(pivot)); + } + + /** + * + */ + public PivotedVectorStorage() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public int size() { + return sto.size(); + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return sto.get(pivot[i]); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + sto.set(pivot[i], v); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(pivot); + out.writeObject(unpivot); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (VectorStorage)in.readObject(); + pivot = (int[])in.readObject(); + unpivot = (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 sto.isArrayBased(); + } + + /** {@inheritDoc} */ + @Override public double[] data() { + return isArrayBased() ? sto.data() : null; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + PivotedVectorStorage that = (PivotedVectorStorage)o; + + return (sto != null ? sto.equals(that.sto) : that.sto == null) && Arrays.equals(pivot, that.pivot) + && Arrays.equals(unpivot, that.unpivot); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = sto != null ? sto.hashCode() : 0; + + res = 31 * res + Arrays.hashCode(pivot); + res = 31 * res + Arrays.hashCode(unpivot); + + 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/vector/RandomVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/RandomVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/RandomVectorStorage.java new file mode 100644 index 0000000..be1ad91 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/RandomVectorStorage.java @@ -0,0 +1,152 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import java.util.Random; +import org.apache.ignite.ml.math.MurmurHash; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; + +/** + * {@link VectorStorage} implementation with random values in the vector elements. + */ +public class RandomVectorStorage implements VectorStorage { + /** */ + private static final long SCALE = 1L << 32; + /** */ + private static final int PRIME = 104047; + + /** Random generation seed. */ + private int seed; + + /** Vector size. */ + private int size; + + /** Whether fast hash is used, in {@link #get(int)}. */ + private boolean fastHash; + + /** */ + public RandomVectorStorage() { + // No-op. + } + + /** + * @param size Size of the storage. + * @param fastHash Whether or not to use fast hashing or Murmur hashing. + */ + public RandomVectorStorage(int size, boolean fastHash) { + assert size > 0; + + this.size = size; + this.fastHash = fastHash; + + seed = new Random().nextInt(); + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + if (!fastHash) { + ByteBuffer buf = ByteBuffer.allocate(4); + + buf.putInt(i); + 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 (((i * PRIME) & 8) * 0.25) - 1; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + throw new UnsupportedOperationException("Random vector storage is a read-only storage."); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(seed); + out.writeBoolean(fastHash); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + seed = in.readInt(); + fastHash = in.readBoolean(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@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 + size; + + return res; + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + RandomVectorStorage that = (RandomVectorStorage)o; + + return size == that.size && 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/vector/SingleElementVectorDelegateStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SingleElementVectorDelegateStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SingleElementVectorDelegateStorage.java new file mode 100644 index 0000000..d472e3a --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SingleElementVectorDelegateStorage.java @@ -0,0 +1,145 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; + +/** + * Single value view storage over another vector. + */ +public class SingleElementVectorDelegateStorage implements VectorStorage { + /** */ private int idx; + /** */ private Vector vec; + + /** + * + */ + public SingleElementVectorDelegateStorage() { + // No-op. + } + + /** + * @param vec Parent vector. + * @param idx Element index. + */ + public SingleElementVectorDelegateStorage(Vector vec, int idx) { + assert vec != null; + assert idx >= 0; + + this.vec = vec; + this.idx = idx; + } + + /** + * + * + */ + public int index() { + return idx; + } + + /** + * + * + */ + public Vector delegate() { + return vec; + } + + /** {@inheritDoc} */ + @Override public int size() { + return vec.size(); + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return i == idx ? vec.get(i) : 0.0; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (i == idx) + vec.set(i, v); + else + throw new UnsupportedOperationException("Can't set element outside of index: " + idx); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(vec); + out.writeInt(idx); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + vec = (Vector)in.readObject(); + idx = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@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 boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SingleElementVectorDelegateStorage that = (SingleElementVectorDelegateStorage)o; + + return idx == that.idx && (vec != null ? vec.equals(that.vec) : that.vec == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = idx; + + res = 31 * res + (vec != null ? vec.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/vector/SingleElementVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SingleElementVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SingleElementVectorStorage.java new file mode 100644 index 0000000..854b732 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SingleElementVectorStorage.java @@ -0,0 +1,143 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; + +/** + * Vector storage holding a single non-zero value at some index. + */ +public class SingleElementVectorStorage implements VectorStorage { + /** */ private int idx; + /** */ private double val; + /** */ private int size; + + /** + * + */ + public SingleElementVectorStorage() { + // No-op. + } + + /** + * @param size Parent vector size. + * @param idx Element index in the parent vector. + * @param val Value of the element. + */ + public SingleElementVectorStorage(int size, int idx, double val) { + assert size > 0; + assert idx >= 0; + + this.size = size; + this.idx = idx; + this.val = val; + } + + /** + * + * @return Index of the element in the parent vector. + */ + public int index() { + return idx; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return i == idx ? val : 0.0; + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (i == idx) + val = v; + else + throw new UnsupportedOperationException("Can't set element outside of index: " + idx); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(idx); + out.writeDouble(val); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + idx = in.readInt(); + val = in.readDouble(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return true; + } + + /** {@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 boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + SingleElementVectorStorage that = (SingleElementVectorStorage)o; + + return idx == that.idx && Double.compare(that.val, val) == 0 && size == that.size; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = idx; + long temp = Double.doubleToLongBits(val); + + res = 31 * res + (int)(temp ^ (temp >>> 32)); + res = 31 * res + size; + + 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/vector/SparseLocalOffHeapVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java new file mode 100644 index 0000000..7b3da78 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOffHeapVectorStorage.java @@ -0,0 +1,149 @@ +/* + * 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.vector; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.nio.ByteBuffer; +import org.apache.ignite.internal.util.offheap.GridOffHeapMap; +import org.apache.ignite.internal.util.offheap.GridOffHeapMapFactory; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.math.impls.vector.SparseLocalOffHeapVector; + +/** + * {@link VectorStorage} implementation for {@link SparseLocalOffHeapVector}. + */ +public class SparseLocalOffHeapVectorStorage implements VectorStorage { + /** Assume 10% density. */ + private static final int INIT_DENSITY = 10; + /** Storage capacity. */ + private int size; + /** Local off heap map. */ + private GridOffHeapMap gridOffHeapMap; + + /** */ + public SparseLocalOffHeapVectorStorage() { + //No-op. + } + + /** */ + public SparseLocalOffHeapVectorStorage(int cap) { + assert cap > 0; + + gridOffHeapMap = GridOffHeapMapFactory.unsafeMap(cap / INIT_DENSITY); + size = cap; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + byte[] bytes = gridOffHeapMap.get(hash(i), intToByteArray(i)); + return bytes == null ? 0 : ByteBuffer.wrap(bytes).getDouble(); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (v != 0.0) + gridOffHeapMap.put(hash(i), intToByteArray(i), doubleToByteArray(v)); + else if (gridOffHeapMap.contains(hash(i), intToByteArray(i))) + gridOffHeapMap.remove(hash(i), intToByteArray(i)); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + throw new UnsupportedOperationException(); // TODO: add externalization support. + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return false; + } + + /** {@inheritDoc} */ + @Override public void destroy() { + gridOffHeapMap.destruct(); + } + + /** */ + private int hash(int h) { + // Apply base step of MurmurHash; see http://code.google.com/p/smhasher/ + // Despite two multiplies, this is often faster than others + // with comparable bit-spread properties. + h ^= h >>> 16; + h *= 0x85ebca6b; + h ^= h >>> 13; + h *= 0xc2b2ae35; + + return (h >>> 16) ^ h; + } + + /** */ + private byte[] intToByteArray(int val) { + return new byte[] { + (byte)(val >>> 24), + (byte)(val >>> 16), + (byte)(val >>> 8), + (byte)val}; + } + + /** */ + private byte[] doubleToByteArray(double val) { + long l = Double.doubleToRawLongBits(val); + return new byte[] { + (byte)((l >> 56) & 0xff), + (byte)((l >> 48) & 0xff), + (byte)((l >> 40) & 0xff), + (byte)((l >> 32) & 0xff), + (byte)((l >> 24) & 0xff), + (byte)((l >> 16) & 0xff), + (byte)((l >> 8) & 0xff), + (byte)((l) & 0xff), + }; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java new file mode 100644 index 0000000..75318d6 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseLocalOnHeapVectorStorage.java @@ -0,0 +1,152 @@ +/* + * 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.vector; + +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.ml.math.StorageConstants; +import org.apache.ignite.ml.math.VectorStorage; + +/** + * Sparse, local, on-heap vector storage. + */ +public class SparseLocalOnHeapVectorStorage implements VectorStorage, StorageConstants { + /** */ private int size; + /** */ private int acsMode; + + /** Actual map storage. */ + private Map<Integer, Double> sto; + + /** + * + */ + public SparseLocalOnHeapVectorStorage() { + // No-op. + } + + /** + * @param size Vector size. + * @param acsMode Access mode. + */ + public SparseLocalOnHeapVectorStorage(int size, int acsMode) { + assert size > 0; + assertAccessMode(acsMode); + + this.size = size; + this.acsMode = acsMode; + + if (acsMode == SEQUENTIAL_ACCESS_MODE) + sto = new Int2DoubleRBTreeMap(); + else + sto = new Int2DoubleOpenHashMap(); + } + + /** + * + * + */ + public int getAccessMode() { + return acsMode; + } + + /** {@inheritDoc} */ + @Override public int size() { + return size; + } + + /** {@inheritDoc} */ + @Override public double get(int i) { + return sto.getOrDefault(i, 0.0); + } + + /** {@inheritDoc} */ + @Override public void set(int i, double v) { + if (v != 0.0) + sto.put(i, v); + else if (sto.containsKey(i)) + sto.remove(i); + + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeInt(size); + out.writeInt(acsMode); + out.writeObject(sto); + } + + /** {@inheritDoc} */ + @SuppressWarnings({"unchecked"}) + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + size = in.readInt(); + acsMode = in.readInt(); + sto = (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 true; + } + + /** {@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; + + SparseLocalOnHeapVectorStorage that = (SparseLocalOnHeapVectorStorage)o; + + return size == that.size && acsMode == that.acsMode && (sto != null ? sto.equals(that.sto) : that.sto == null); + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = size; + + res = 31 * res + acsMode; + res = 31 * res + (sto != null ? sto.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/vector/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/package-info.java new file mode 100644 index 0000000..a9825b3 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/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 vector storage models. + */ +package org.apache.ignite.ml.math.impls.storage.vector; \ 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/vector/AbstractReadOnlyVector.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java new file mode 100644 index 0000000..e48542b --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/AbstractReadOnlyVector.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.vector; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.VectorStorage; +import org.apache.ignite.ml.math.functions.IgniteBiFunction; +import org.apache.ignite.ml.math.functions.IgniteDoubleFunction; +import org.apache.ignite.ml.math.impls.matrix.FunctionMatrix; + +/** + * This class provides a helper implementation of the read-only implementation of {@link Vector} + * 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. + */ +public abstract class AbstractReadOnlyVector extends AbstractVector { + /** */ + public AbstractReadOnlyVector() { + // No-op. + } + + /** + * @param sto Storage. + */ + public AbstractReadOnlyVector(VectorStorage sto) { + super(true, sto); + } + + /** {@inheritDoc} */ + @Override public Matrix cross(Vector vec) { + return new FunctionMatrix(size(), vec.size(), + (row, col) -> vec.get(col) * get(row)); + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrix(boolean rowLike) { + return new FunctionMatrix(rowLike ? 1 : size(), rowLike ? size() : 1, + (row, col) -> rowLike ? get(col) : get(row)); + } + + /** {@inheritDoc} */ + @Override public Matrix toMatrixPlusOne(boolean rowLike, double zeroVal) { + return new FunctionMatrix(rowLike ? 1 : size() + 1, rowLike ? size() + 1 : 1, (row, col) -> { + if (row == 0 && col == 0) + return zeroVal; + + return rowLike ? get(col - 1) : get(row - 1); + }); + } + + /** {@inheritDoc} */ + @Override public Vector copy() { + return this; // This exploits read-only feature of this type vector. + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize() { + return logNormalize(2.0, Math.sqrt(getLengthSquared())); + } + + /** {@inheritDoc} */ + @Override public Vector logNormalize(double power) { + return logNormalize(power, kNorm(power)); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteDoubleFunction<Double> fun) { + return new FunctionVector(size(), (i) -> fun.apply(get(i))); + } + + /** {@inheritDoc} */ + @Override public Vector map(Vector vec, IgniteBiFunction<Double, Double, Double> fun) { + checkCardinality(vec); + + return new FunctionVector(size(), (i) -> fun.apply(get(i), vec.get(i))); + } + + /** {@inheritDoc} */ + @Override public Vector map(IgniteBiFunction<Double, Double, Double> fun, double y) { + return new FunctionVector(size(), (i) -> fun.apply(get(i), y)); + } + + /** {@inheritDoc} */ + @Override public Vector divide(double x) { + if (x == 1.0) + return this; + + return new FunctionVector(size(), (i) -> get(i) / x); + } + + /** {@inheritDoc} */ + @Override public Vector times(double x) { + return x == 0 ? new ConstantVector(size(), 0) : new FunctionVector(size(), (i) -> get(i) * x); + } + + /** + * @param power Power. + * @param normLen Normalized length. + * @return logNormalized value. + */ + private Vector logNormalize(double power, double normLen) { + assert !(Double.isInfinite(power) || power <= 1.0); + + double denominator = normLen * Math.log(power); + + return new FunctionVector(size(), (idx) -> Math.log1p(get(idx)) / denominator); + } +}