http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/UnsupportedOperationException.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/UnsupportedOperationException.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/UnsupportedOperationException.java new file mode 100644 index 0000000..0fea255 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/UnsupportedOperationException.java @@ -0,0 +1,44 @@ +/* + * 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.exceptions; + +import org.apache.ignite.IgniteException; + +/** + * Indicate that a specific operation is not supported by the underlying implementation. + * In some cases, an operation may be unsupported only in certain cases where, for example, + * it could not be deterministically completed in polynomial time. + */ +public class UnsupportedOperationException extends IgniteException { + /** */ + private static final long serialVersionUID = 0L; + + /** + * @param errMsg Error message. + */ + public UnsupportedOperationException(String errMsg) { + super(errMsg); + } + + /** + * + */ + public UnsupportedOperationException() { + this("Unsupported operation."); + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/package-info.java new file mode 100644 index 0000000..1990a8a --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/exceptions/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 exceptions for distributed code algebra. + */ +package org.apache.ignite.ml.math.exceptions; \ 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/functions/Functions.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java new file mode 100644 index 0000000..cd48daa --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.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.functions; + +/** + * Compatibility with Apache Mahout. + */ +public final class Functions { + /** Function that returns {@code Math.abs(a)}. */ + public static final IgniteDoubleFunction<Double> ABS = Math::abs; + + /** Function that returns its argument. */ + public static final IgniteDoubleFunction<Double> IDENTITY = (a) -> a; + + /** Function that returns {@code Math.log(a) / Math.log(2)}. */ + public static final IgniteDoubleFunction<Double> LOG2 = (a) -> Math.log(a) * 1.4426950408889634; + + /** Function that returns {@code -a}. */ + public static final IgniteDoubleFunction<Double> NEGATE = (a) -> -a; + + /** Function that returns {@code a < 0 ? -1 : a > 0 ? 1 : 0 }. */ + public static final IgniteDoubleFunction<Double> SIGN = (a) -> a < 0.0 ? -1.0 : a > 0.0 ? 1.0 : 0.0; + + /** Function that returns {@code a * a}. */ + public static final IgniteDoubleFunction<Double> SQUARE = (a) -> a * a; + + /** Function that returns {@code 1 / (1 + exp(-a) } */ + public static final IgniteDoubleFunction<Double> SIGMOID = (a) -> 1.0 / (1.0 + Math.exp(-a)); + + /** Function that returns {@code 1 / a } */ + public static final IgniteDoubleFunction<Double> INV = (a) -> 1.0 / a; + + /** Function that returns {@code a * (1-a) } */ + public static final IgniteDoubleFunction<Double> SIGMOIDGRADIENT = (a) -> a * (1.0 - a); + + /** Function that returns {@code a % b}. */ + public static final IgniteBiFunction<Double, Double, Double> MOD = (a, b) -> a % b; + + /** Function that returns {@code a * b}. */ + public static final IgniteBiFunction<Double, Double, Double> MULT = (a, b) -> a * b; + + /** Function that returns {@code Math.log(a) / Math.log(b)}. */ + public static final IgniteBiFunction<Double, Double, Double> LG = (a, b) -> Math.log(a) / Math.log(b); + + /** Function that returns {@code a + b}. */ + public static final IgniteBiFunction<Double, Double, Double> PLUS = (a, b) -> a + b; + + /** Function that returns {@code a - b}. */ + public static final IgniteBiFunction<Double, Double, Double> MINUS = (a, b) -> a - b; + + /** Function that returns {@code abs(a - b)}. */ + public static final IgniteBiFunction<Double, Double, Double> MINUS_ABS = (a, b) -> Math.abs(a - b); + + /** Function that returns {@code max(abs(a), abs(b))}. */ + public static final IgniteBiFunction<Double, Double, Double> MAX_ABS = (a, b) -> Math.max(Math.abs(a), Math.abs(b)); + + /** Function that returns {@code min(abs(a), abs(b))}. */ + public static final IgniteBiFunction<Double, Double, Double> MIN_ABS = (a, b) -> Math.min(Math.abs(a), Math.abs(b)); + + /** Function that returns {@code Math.abs(a) + Math.abs(b)}. */ + public static final IgniteBiFunction<Double, Double, Double> PLUS_ABS = (a, b) -> Math.abs(a) + Math.abs(b); + + /** Function that returns {@code (a - b) * (a - b)} */ + public static final IgniteBiFunction<Double, Double, Double> MINUS_SQUARED = (a, b) -> (a - b) * (a - b); + + /** + * Function that returns {@code a < b ? -1 : a > b ? 1 : 0}. + */ + public static final IgniteBiFunction<Double, Double, Double> COMPARE = (a, b) -> a < b ? -1.0 : a > b ? 1.0 : 0.0; + + /** + * Function that returns {@code a + b}. {@code a} is a variable, {@code b} is fixed. + * + * @param b + */ + public static IgniteDoubleFunction<Double> plus(final double b) { + return (a) -> a + b; + } + + /** + * Function that returns {@code a * b}. {@code a} is a variable, {@code b} is fixed. + * + * @param b + */ + public static IgniteDoubleFunction<Double> mult(final double b) { + return (a) -> a * b; + } + + /** Function that returns {@code a / b}. {@code a} is a variable, {@code b} is fixed. */ + public static IgniteDoubleFunction<Double> div(double b) { + return mult(1 / b); + } + + /** + * Function that returns {@code a + b*constant}. {@code a} and {@code b} are variables, + * {@code constant} is fixed. + */ + public static IgniteBiFunction<Double, Double, Double> plusMult(double constant) { + return (a, b) -> a + b * constant; + } + + /** + * Function that returns {@code a - b*constant}. {@code a} and {@code b} are variables, + * {@code constant} is fixed. + */ + public static IgniteBiFunction<Double, Double, Double> minusMult(double constant) { + return (a, b) -> a - b * constant; + } + + /** + * @param b + */ + public static IgniteDoubleFunction<Double> pow(final double b) { + return (a) -> { + if (b == 2) + return a * a; + else + return Math.pow(a, b); + }; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiConsumer.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiConsumer.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiConsumer.java new file mode 100644 index 0000000..f3303cd --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiConsumer.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +import java.io.Serializable; +import java.util.function.BiConsumer; + +/** + * Serializable binary consumer. + * + * @see java.util.function.BiConsumer + */ +public interface IgniteBiConsumer<T, U> extends BiConsumer<T, U>, Serializable { +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiFunction.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiFunction.java new file mode 100644 index 0000000..dc49739 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteBiFunction.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +import java.io.Serializable; +import java.util.function.BiFunction; + +/** + * Serializable binary function. + * + * @see java.util.function.BiFunction + */ +public interface IgniteBiFunction<A, B, T> extends BiFunction<A, B, T>, Serializable { +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteConsumer.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteConsumer.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteConsumer.java new file mode 100644 index 0000000..1d52e1d --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteConsumer.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +import java.io.Serializable; +import java.util.function.Consumer; + +/** + * Serializable consumer. + * + * @see java.util.function.Consumer + */ +public interface IgniteConsumer<T> extends Consumer<T>, Serializable { +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteDoubleFunction.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteDoubleFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteDoubleFunction.java new file mode 100644 index 0000000..dfbf393 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteDoubleFunction.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +import java.io.Serializable; +import java.util.function.DoubleFunction; + +/** + * Serializable double function. + * + * @see java.util.function.DoubleFunction + */ +public interface IgniteDoubleFunction<Double> extends DoubleFunction<Double>, Serializable { +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteFunction.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteFunction.java new file mode 100644 index 0000000..9d19592 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IgniteFunction.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +import java.io.Serializable; +import java.util.function.Function; + +/** + * Serializable function. + * + * @see java.util.function.Function + */ +public interface IgniteFunction<T, R> extends Function<T, R>, Serializable { + +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntDoubleToVoidFunction.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntDoubleToVoidFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntDoubleToVoidFunction.java new file mode 100644 index 0000000..981e0c5 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntDoubleToVoidFunction.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +/** + * Setter function for the vector. + */ +public interface IntDoubleToVoidFunction extends IgniteBiConsumer<Integer, Double> { + +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntDoubleToVoidFunction.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntDoubleToVoidFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntDoubleToVoidFunction.java new file mode 100644 index 0000000..a9b3f9c --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntDoubleToVoidFunction.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +import java.io.Serializable; + +/** + * Setter function for matrices. + */ +public interface IntIntDoubleToVoidFunction extends Serializable { + /** */ + public void apply(int x, int y, double v); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntToDoubleFunction.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntToDoubleFunction.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntToDoubleFunction.java new file mode 100644 index 0000000..5fabfb7 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/IntIntToDoubleFunction.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.functions; + +/** + * Getters functions for matrices. + */ +public interface IntIntToDoubleFunction extends IgniteBiFunction<Integer, Integer, Double> { +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/package-info.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/package-info.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/package-info.java new file mode 100644 index 0000000..d41f94d --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/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 serializable functions for distributed code algebra. + */ +package org.apache.ignite.ml.math.functions; \ 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/CacheUtils.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/CacheUtils.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/CacheUtils.java new file mode 100644 index 0000000..cfb01be --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/CacheUtils.java @@ -0,0 +1,356 @@ +/* + * 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; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import javax.cache.Cache; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.Ignition; +import org.apache.ignite.cache.affinity.Affinity; +import org.apache.ignite.cache.query.ScanQuery; +import org.apache.ignite.cluster.ClusterGroup; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.lang.IgniteCallable; +import org.apache.ignite.lang.IgniteRunnable; +import org.apache.ignite.ml.math.KeyMapper; +import org.apache.ignite.ml.math.ValueMapper; +import org.apache.ignite.ml.math.functions.IgniteBiFunction; +import org.apache.ignite.ml.math.functions.IgniteConsumer; +import org.apache.ignite.ml.math.functions.IgniteFunction; + +/** + * Distribution-related misc. support. + */ +public class CacheUtils { + /** + * Cache entry support. + * + * @param <K> + * @param <V> + */ + public static class CacheEntry<K, V> { + /** */ + private Cache.Entry<K, V> entry; + /** */ + private IgniteCache<K, V> cache; + + /** + * @param entry Original cache entry. + * @param cache Cache instance. + */ + CacheEntry(Cache.Entry<K, V> entry, IgniteCache<K, V> cache) { + this.entry = entry; + this.cache = cache; + } + + /** + * + * + */ + public Cache.Entry<K, V> entry() { + return entry; + } + + /** + * + * + */ + public IgniteCache<K, V> cache() { + return cache; + } + } + + /** + * Gets local Ignite instance. + */ + public static Ignite ignite() { + return Ignition.localIgnite(); + } + + /** + * @param cacheName Cache name. + * @param k Key into the cache. + * @param <K> Key type. + * @return Cluster group for given key. + */ + public static <K> ClusterGroup groupForKey(String cacheName, K k) { + return ignite().cluster().forNode(ignite().affinity(cacheName).mapKeyToNode(k)); + } + + /** + * @param cacheName Cache name. + * @param keyMapper {@link KeyMapper} to validate cache key. + * @param valMapper {@link ValueMapper} to obtain double value for given cache key. + * @param <K> Cache key object type. + * @param <V> Cache value object type. + * @return Sum of the values obtained for valid keys. + */ + public static <K, V> double sum(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) { + Collection<Double> subSums = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> { + if (keyMapper.isValid(ce.entry().getKey())) { + double v = valMapper.toDouble(ce.entry().getValue()); + + return acc == null ? v : acc + v; + } + else + return acc; + }); + + return sum(subSums); + } + + /** + * @param cacheName Cache name. + * @return Sum obtained using sparse logic. + */ + public static <K, V> double sparseSum(String cacheName) { + Collection<Double> subSums = fold(cacheName, (CacheEntry<Integer, Map<Integer, Double>> ce, Double acc) -> { + Map<Integer, Double> map = ce.entry().getValue(); + + double sum = sum(map.values()); + + return acc == null ? sum : acc + sum; + }); + + return sum(subSums); + } + + /** + * @param c {@link Collection} of double values to sum. + * @return Sum of the values. + */ + private static double sum(Collection<Double> c) { + double sum = 0.0; + + for (double d : c) + sum += d; + + return sum; + } + + /** + * @param cacheName Cache name. + * @param keyMapper {@link KeyMapper} to validate cache key. + * @param valMapper {@link ValueMapper} to obtain double value for given cache key. + * @param <K> Cache key object type. + * @param <V> Cache value object type. + * @return Minimum value for valid keys. + */ + public static <K, V> double min(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) { + Collection<Double> mins = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> { + if (keyMapper.isValid(ce.entry().getKey())) { + double v = valMapper.toDouble(ce.entry().getValue()); + + if (acc == null) + return v; + else + return Math.min(acc, v); + } + else + return acc; + }); + + return Collections.min(mins); + } + + /** + * @param cacheName Cache name. + * @return Minimum value obtained using sparse logic. + */ + public static <K, V> double sparseMin(String cacheName) { + Collection<Double> mins = fold(cacheName, (CacheEntry<Integer, Map<Integer, Double>> ce, Double acc) -> { + Map<Integer, Double> map = ce.entry().getValue(); + + double min = Collections.min(map.values()); + + if (acc == null) + return min; + else + return Math.min(acc, min); + }); + + return Collections.min(mins); + } + + /** + * @param cacheName Cache name. + * @return Maximum value obtained using sparse logic. + */ + public static <K, V> double sparseMax(String cacheName) { + Collection<Double> maxes = fold(cacheName, (CacheEntry<Integer, Map<Integer, Double>> ce, Double acc) -> { + Map<Integer, Double> map = ce.entry().getValue(); + + double max = Collections.max(map.values()); + + if (acc == null) + return max; + else + return Math.max(acc, max); + }); + + return Collections.max(maxes); + } + + /** + * @param cacheName Cache name. + * @param keyMapper {@link KeyMapper} to validate cache key. + * @param valMapper {@link ValueMapper} to obtain double value for given cache key. + * @param <K> Cache key object type. + * @param <V> Cache value object type. + * @return Maximum value for valid keys. + */ + public static <K, V> double max(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) { + Collection<Double> maxes = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> { + if (keyMapper.isValid(ce.entry().getKey())) { + double v = valMapper.toDouble(ce.entry().getValue()); + + if (acc == null) + return v; + else + return Math.max(acc, v); + } + else + return acc; + }); + + return Collections.max(maxes); + } + + /** + * @param cacheName Cache name. + * @param keyMapper {@link KeyMapper} to validate cache key. + * @param valMapper {@link ValueMapper} to obtain double value for given cache key. + * @param mapper Mapping {@link IgniteFunction}. + * @param <K> Cache key object type. + * @param <V> Cache value object type. + */ + public static <K, V> void map(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper, + IgniteFunction<Double, Double> mapper) { + foreach(cacheName, (CacheEntry<K, V> ce) -> { + K k = ce.entry().getKey(); + + if (keyMapper.isValid(k)) + // Actual assignment. + ce.cache().put(k, valMapper.fromDouble(mapper.apply(valMapper.toDouble(ce.entry().getValue())))); + }); + } + + /** + * @param cacheName Cache name. + * @param mapper Mapping {@link IgniteFunction}. + */ + public static <K, V> void sparseMap(String cacheName, IgniteFunction<Double, Double> mapper) { + foreach(cacheName, (CacheEntry<Integer, Map<Integer, Double>> ce) -> { + Integer k = ce.entry().getKey(); + Map<Integer, Double> v = ce.entry().getValue(); + + for (Map.Entry<Integer, Double> e : v.entrySet()) + e.setValue(mapper.apply(e.getValue())); + + ce.cache().put(k, v); + }); + } + + /** + * @param cacheName Cache name. + * @param fun An operation that accepts a cache entry and processes it. + * @param <K> Cache key object type. + * @param <V> Cache value object type. + */ + public static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun) { + bcast(cacheName, () -> { + Ignite ignite = Ignition.localIgnite(); + IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName); + + int partsCnt = ignite.affinity(cacheName).partitions(); + + // Use affinity in filter for scan query. Otherwise we accept consumer in each node which is wrong. + Affinity affinity = ignite.affinity(cacheName); + ClusterNode locNode = ignite.cluster().localNode(); + + // Iterate over all partitions. Some of them will be stored on that local node. + for (int part = 0; part < partsCnt; part++) { + int p = part; + + // Iterate over given partition. + // Query returns an empty cursor if this partition is not stored on this node. + for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part, + (k, v) -> affinity.mapPartitionToNode(p) == locNode))) + fun.accept(new CacheEntry<>(entry, cache)); + } + }); + } + + /** + * <b>Currently fold supports only commutative operations.<b/> + * + * @param cacheName Cache name. + * @param folder Fold function operating over cache entries. + * @param <K> Cache key object type. + * @param <V> Cache value object type. + * @param <A> Fold result type. + * @return Fold operation result. + */ + public static <K, V, A> Collection<A> fold(String cacheName, IgniteBiFunction<CacheEntry<K, V>, A, A> folder) { + return bcast(cacheName, () -> { + Ignite ignite = Ignition.localIgnite(); + IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName); + + int partsCnt = ignite.affinity(cacheName).partitions(); + + // Use affinity in filter for ScanQuery. Otherwise we accept consumer in each node which is wrong. + Affinity affinity = ignite.affinity(cacheName); + ClusterNode locNode = ignite.cluster().localNode(); + + A a = null; + + // Iterate over all partitions. Some of them will be stored on that local node. + for (int part = 0; part < partsCnt; part++) { + int p = part; + + // Iterate over given partition. + // Query returns an empty cursor if this partition is not stored on this node. + for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part, + (k, v) -> affinity.mapPartitionToNode(p) == locNode))) + a = folder.apply(new CacheEntry<>(entry, cache), a); + } + + return a; + }); + } + + /** + * @param cacheName Cache name. + * @param run {@link Runnable} to broadcast to cache nodes for given cache name. + */ + public static void bcast(String cacheName, IgniteRunnable run) { + ignite().compute(ignite().cluster().forCacheNodes(cacheName)).broadcast(run); + } + + /** + * @param cacheName Cache name. + * @param call {@link IgniteCallable} to broadcast to cache nodes for given cache name. + * @param <A> Type returned by the callable. + */ + public static <A> Collection<A> bcast(String cacheName, IgniteCallable<A> call) { + return ignite().compute(ignite().cluster().forCacheNodes(cacheName)).broadcast(call); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java new file mode 100644 index 0000000..c5edeb1 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java @@ -0,0 +1,880 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import org.apache.ignite.lang.IgniteUuid; +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.MatrixStorage; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.decompositions.LUDecomposition; +import org.apache.ignite.ml.math.exceptions.CardinalityException; +import org.apache.ignite.ml.math.exceptions.ColumnIndexException; +import org.apache.ignite.ml.math.exceptions.RowIndexException; +import org.apache.ignite.ml.math.functions.Functions; +import org.apache.ignite.ml.math.functions.IgniteBiFunction; +import org.apache.ignite.ml.math.functions.IgniteDoubleFunction; +import org.apache.ignite.ml.math.functions.IgniteFunction; +import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction; +import org.apache.ignite.ml.math.impls.vector.MatrixVectorView; + +/** + * This class provides a helper implementation of the {@link Matrix} + * interface to minimize the effort required to implement it. + * Subclasses may override some of the implemented methods if a more + * specific or optimized implementation is desirable. + * + * TODO: add row/column optimization. + */ +public abstract class AbstractMatrix implements Matrix { + // Stochastic sparsity analysis. + /** */ + private static final double Z95 = 1.959964; + /** */ + private static final double Z80 = 1.281552; + /** */ + private static final int MAX_SAMPLES = 500; + /** */ + private static final int MIN_SAMPLES = 15; + + /** Cached minimum element. */ + private Element minElm; + /** Cached maximum element. */ + private Element maxElm = null; + + /** Matrix storage implementation. */ + private MatrixStorage sto; + + /** Meta attributes storage. */ + private Map<String, Object> meta = new HashMap<>(); + + /** Matrix's GUID. */ + private IgniteUuid guid = IgniteUuid.randomUuid(); + + /** + * @param sto Backing {@link MatrixStorage}. + */ + public AbstractMatrix(MatrixStorage sto) { + this.sto = sto; + } + + /** + * + */ + public AbstractMatrix() { + // No-op. + } + + /** + * @param sto Backing {@link MatrixStorage}. + */ + protected void setStorage(MatrixStorage sto) { + assert sto != null; + + this.sto = sto; + } + + /** + * @param row Row index in the matrix. + * @param col Column index in the matrix. + * @param v Value to set. + */ + protected void storageSet(int row, int col, double v) { + sto.set(row, col, v); + + // Reset cached values. + minElm = maxElm = null; + } + + /** + * @param row Row index in the matrix. + * @param col Column index in the matrix. + */ + protected double storageGet(int row, int col) { + return sto.get(row, col); + } + + /** {@inheritDoc} */ + @Override public Element maxElement() { + if (maxElm == null) { + double max = Double.NEGATIVE_INFINITY; + int row = 0, col = 0; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) { + double d = storageGet(x, y); + + if (d > max) { + max = d; + row = x; + col = y; + } + } + + maxElm = mkElement(row, col); + } + + return maxElm; + } + + /** {@inheritDoc} */ + @Override public Element minElement() { + if (minElm == null) { + double min = Double.MAX_VALUE; + int row = 0, col = 0; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) { + double d = storageGet(x, y); + + if (d < min) { + min = d; + row = x; + col = y; + } + } + + minElm = mkElement(row, col); + } + + return minElm; + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + return maxElement().get(); + } + + /** {@inheritDoc} */ + @Override public double minValue() { + return minElement().get(); + } + + /** + * @param row Row index in the matrix. + * @param col Column index in the matrix. + */ + private Element mkElement(int row, int col) { + return new Element() { + /** {@inheritDoc} */ + @Override public double get() { + return storageGet(row, col); + } + + /** {@inheritDoc} */ + @Override public int row() { + return row; + } + + /** {@inheritDoc} */ + @Override public int column() { + return col; + } + + /** {@inheritDoc} */ + @Override public void set(double d) { + storageSet(row, col, d); + } + }; + } + + /** {@inheritDoc} */ + @Override public Element getElement(int row, int col) { + return mkElement(row, col); + } + + /** {@inheritDoc} */ + @Override public Matrix swapRows(int row1, int row2) { + checkRowIndex(row1); + checkRowIndex(row2); + + int cols = columnSize(); + + for (int y = 0; y < cols; y++) { + double v = getX(row1, y); + + setX(row1, y, getX(row2, y)); + setX(row2, y, v); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix swapColumns(int col1, int col2) { + checkColumnIndex(col1); + checkColumnIndex(col2); + + int rows = rowSize(); + + for (int x = 0; x < rows; x++) { + double v = getX(x, col1); + + setX(x, col1, getX(x, col2)); + setX(x, col2, v); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public MatrixStorage getStorage() { + return sto; + } + + /** {@inheritDoc} */ + @Override public boolean isSequentialAccess() { + return sto.isSequentialAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDense() { + return sto.isDense(); + } + + /** {@inheritDoc} */ + @Override public boolean isRandomAccess() { + return sto.isRandomAccess(); + } + + /** {@inheritDoc} */ + @Override public boolean isDistributed() { + return sto.isDistributed(); + } + + /** {@inheritDoc} */ + @Override public boolean isArrayBased() { + return sto.isArrayBased(); + } + + /** + * Check row index bounds. + * + * @param row Row index. + */ + private void checkRowIndex(int row) { + if (row < 0 || row >= rowSize()) + throw new RowIndexException(row); + } + + /** + * Check column index bounds. + * + * @param col Column index. + */ + private void checkColumnIndex(int col) { + if (col < 0 || col >= columnSize()) + throw new ColumnIndexException(col); + } + + /** + * Check column and row index bounds. + * + * @param row Row index. + * @param col Column index. + */ + protected void checkIndex(int row, int col) { + checkRowIndex(row); + checkColumnIndex(col); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(sto); + out.writeObject(meta); + out.writeObject(guid); + } + + /** {@inheritDoc} */ + @Override public Map<String, Object> getMetaStorage() { + return meta; + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + sto = (MatrixStorage)in.readObject(); + meta = (Map<String, Object>)in.readObject(); + guid = (IgniteUuid)in.readObject(); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double val) { + if (sto.isArrayBased()) + for (double[] column : sto.data()) + Arrays.fill(column, val); + else { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, val); + } + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assign(IntIntToDoubleFunction fun) { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, fun.apply(x, y)); + + return this; + } + + /** */ + private void checkCardinality(Matrix mtx) { + checkCardinality(mtx.rowSize(), mtx.columnSize()); + } + + /** */ + private void checkCardinality(int rows, int cols) { + if (rows != rowSize()) + throw new CardinalityException(rowSize(), rows); + + if (cols != columnSize()) + throw new CardinalityException(columnSize(), cols); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double[][] vals) { + checkCardinality(vals.length, vals[0].length); + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, vals[x][y]); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assign(Matrix mtx) { + checkCardinality(mtx); + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, mtx.getX(x, y)); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix map(IgniteDoubleFunction<Double> fun) { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, fun.apply(storageGet(x, y))); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix map(Matrix mtx, IgniteBiFunction<Double, Double, Double> fun) { + checkCardinality(mtx); + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + storageSet(x, y, fun.apply(storageGet(x, y), mtx.getX(x, y))); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assignColumn(int col, Vector vec) { + checkColumnIndex(col); + + int rows = rowSize(); + + for (int x = 0; x < rows; x++) + storageSet(x, col, vec.getX(x)); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix assignRow(int row, Vector vec) { + checkRowIndex(row); + + int cols = columnSize(); + + if (cols != vec.size()) + throw new CardinalityException(cols, vec.size()); + + if (sto.isArrayBased() && vec.getStorage().isArrayBased()) + System.arraycopy(vec.getStorage().data(), 0, sto.data()[row], 0, cols); + else + for (int y = 0; y < cols; y++) + storageSet(row, y, vec.getX(y)); + + return this; + } + + /** {@inheritDoc} */ + @Override public Vector foldRows(IgniteFunction<Vector, Double> fun) { + int rows = rowSize(); + + Vector vec = likeVector(rows); + + for (int i = 0; i < rows; i++) + vec.setX(i, fun.apply(viewRow(i))); + + return vec; + } + + /** {@inheritDoc} */ + @Override public Vector foldColumns(IgniteFunction<Vector, Double> fun) { + int cols = columnSize(); + + Vector vec = likeVector(cols); + + for (int i = 0; i < cols; i++) + vec.setX(i, fun.apply(viewColumn(i))); + + return vec; + } + + /** {@inheritDoc} */ + @Override public <T> T foldMap(IgniteBiFunction<T, Double, T> foldFun, IgniteDoubleFunction<Double> mapFun, + T zeroVal) { + T res = zeroVal; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + res = foldFun.apply(res, mapFun.apply(storageGet(x, y))); + + return res; + } + + /** {@inheritDoc} */ + @Override public int columnSize() { + return sto.columnSize(); + } + + /** {@inheritDoc} */ + @Override public int rowSize() { + return sto.rowSize(); + } + + /** {@inheritDoc} */ + @Override public double determinant() { + //TODO: This decomposition should be cached + LUDecomposition dec = new LUDecomposition(this); + double res = dec.determinant(); + dec.destroy(); + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix inverse() { + if (rowSize() != columnSize()) + throw new CardinalityException(rowSize(), columnSize()); + + //TODO: This decomposition should be cached + LUDecomposition dec = new LUDecomposition(this); + + Matrix res = dec.solve(likeIdentity()); + dec.destroy(); + + return res; + } + + /** */ + protected Matrix likeIdentity() { + int n = rowSize(); + Matrix res = like(n, n); + + for (int i = 0; i < n; i++) + res.setX(i, i, 1.0); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix divide(double d) { + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + setX(x, y, getX(x, y) / d); + + return this; + } + + /** {@inheritDoc} */ + @Override public double get(int row, int col) { + checkIndex(row, col); + + return storageGet(row, col); + } + + /** {@inheritDoc} */ + @Override public double getX(int row, int col) { + return storageGet(row, col); + } + + /** {@inheritDoc} */ + @Override public Matrix minus(Matrix mtx) { + int rows = rowSize(); + int cols = columnSize(); + + checkCardinality(rows, cols); + + Matrix res = like(rows, cols); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + res.setX(x, y, getX(x, y) - mtx.getX(x, y)); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix plus(double x) { + Matrix cp = copy(); + + cp.map(Functions.plus(x)); + + return cp; + } + + /** {@inheritDoc} */ + @Override public Matrix plus(Matrix mtx) { + int rows = rowSize(); + int cols = columnSize(); + + checkCardinality(rows, cols); + + Matrix res = like(rows, cols); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + res.setX(x, y, getX(x, y) + mtx.getX(x, y)); + + return res; + + } + + /** {@inheritDoc} */ + @Override public IgniteUuid guid() { + return guid; + } + + /** {@inheritDoc} */ + @Override public Matrix set(int row, int col, double val) { + checkIndex(row, col); + + storageSet(row, col, val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix setRow(int row, double[] data) { + checkRowIndex(row); + + int cols = columnSize(); + + if (cols != data.length) + throw new CardinalityException(cols, data.length); + + if (sto.isArrayBased()) + System.arraycopy(data, 0, sto.data()[row], 0, cols); + else + for (int y = 0; y < cols; y++) + setX(row, y, data[y]); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix setColumn(int col, double[] data) { + checkColumnIndex(col); + + int rows = rowSize(); + + if (rows != data.length) + throw new CardinalityException(rows, data.length); + + for (int x = 0; x < rows; x++) + setX(x, col, data[x]); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix setX(int row, int col, double val) { + storageSet(row, col, val); + + return this; + } + + /** {@inheritDoc} */ + @Override public Matrix times(double x) { + Matrix cp = copy(); + + cp.map(Functions.mult(x)); + + return cp; + } + + /** {@inheritDoc} */ + @Override public double maxAbsRowSumNorm() { + double max = 0.0; + + int rows = rowSize(); + int cols = columnSize(); + + for (int x = 0; x < rows; x++) { + double sum = 0; + + for (int y = 0; y < cols; y++) + sum += Math.abs(getX(x, y)); + + if (sum > max) + max = sum; + } + + return max; + } + + /** {@inheritDoc} */ + @Override public Vector times(Vector vec) { + int cols = columnSize(); + + if (cols != vec.size()) + throw new CardinalityException(cols, vec.size()); + + int rows = rowSize(); + + Vector res = likeVector(rows); + + for (int x = 0; x < rows; x++) + res.setX(x, vec.dot(viewRow(x))); + + return res; + } + + /** {@inheritDoc} */ + @Override public Matrix times(Matrix mtx) { + int cols = columnSize(); + + if (cols != mtx.rowSize()) + throw new CardinalityException(cols, mtx.rowSize()); + + int rows = rowSize(); + + int mtxCols = mtx.columnSize(); + + Matrix res = like(rows, mtxCols); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < mtxCols; y++) { + double sum = 0.0; + + for (int k = 0; k < cols; k++) + sum += getX(x, k) * mtx.getX(k, y); + + res.setX(x, y, sum); + } + + return res; + } + + /** {@inheritDoc} */ + @Override public double sum() { + int rows = rowSize(); + int cols = columnSize(); + + double sum = 0.0; + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + sum += getX(x, y); + + return sum; + } + + /** {@inheritDoc} */ + @Override public Matrix transpose() { + int rows = rowSize(); + int cols = columnSize(); + + Matrix mtx = like(cols, rows); + + for (int x = 0; x < rows; x++) + for (int y = 0; y < cols; y++) + mtx.setX(y, x, getX(x, y)); + + return mtx; + } + + /** {@inheritDoc} */ + @Override public boolean density(double threshold) { + assert threshold >= 0.0 && threshold <= 1.0; + + int n = MIN_SAMPLES; + int rows = rowSize(); + int cols = columnSize(); + + double mean = 0.0; + double pq = threshold * (1 - threshold); + + Random rnd = new Random(); + + for (int i = 0; i < MIN_SAMPLES; i++) + if (getX(rnd.nextInt(rows), rnd.nextInt(cols)) != 0.0) + mean++; + + mean /= MIN_SAMPLES; + + double iv = Z80 * Math.sqrt(pq / n); + + if (mean < threshold - iv) + return false; // Sparse. + else if (mean > threshold + iv) + return true; // Dense. + + while (n < MAX_SAMPLES) { + // Determine upper bound we may need for 'n' to likely relinquish the uncertainty. + // Here, we use confidence interval formula but solved for 'n'. + double ivX = Math.max(Math.abs(threshold - mean), 1e-11); + + double stdErr = ivX / Z80; + double nX = Math.min(Math.max((int)Math.ceil(pq / (stdErr * stdErr)), n), MAX_SAMPLES) - n; + + if (nX < 1.0) // IMPL NOTE this can happen with threshold 1.0 + nX = 1.0; + + double meanNext = 0.0; + + for (int i = 0; i < nX; i++) + if (getX(rnd.nextInt(rows), rnd.nextInt(cols)) != 0.0) + meanNext++; + + mean = (n * mean + meanNext) / (n + nX); + + n += nX; + + // Are we good now? + iv = Z80 * Math.sqrt(pq / n); + + if (mean < threshold - iv) + return false; // Sparse. + else if (mean > threshold + iv) + return true; // Dense. + } + + return mean > threshold; // Dense if mean > threshold. + } + + /** {@inheritDoc} */ + @Override public Matrix viewPart(int[] off, int[] size) { + return new MatrixView(this, off[0], off[1], size[0], size[1]); + } + + /** {@inheritDoc} */ + @Override public Matrix viewPart(int rowOff, int rows, int colOff, int cols) { + return viewPart(new int[] {rowOff, colOff}, new int[] {rows, cols}); + } + + /** {@inheritDoc} */ + @Override public Vector viewRow(int row) { + return new MatrixVectorView(this, row, 0, 0, 1); + } + + /** {@inheritDoc} */ + @Override public Vector viewColumn(int col) { + return new MatrixVectorView(this, 0, col, 1, 0); + } + + /** {@inheritDoc} */ + @Override public Vector viewDiagonal() { + return new MatrixVectorView(this, 0, 0, 1, 1); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + Matrix cp = like(rowSize(), columnSize()); + + cp.assign(this); + + return cp; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = 1; + + res = res * 37 + guid.hashCode(); + res = res * 37 + sto.hashCode(); + res = res * 37 + meta.hashCode(); + + return res; + } + + /** + * {@inheritDoc} + * + * We ignore guid's for comparisons. + */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + AbstractMatrix that = (AbstractMatrix)o; + + MatrixStorage sto = getStorage(); + + return (sto != null ? sto.equals(that.getStorage()) : that.getStorage() == null); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/CacheMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/CacheMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/CacheMatrix.java new file mode 100644 index 0000000..73a3493 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/CacheMatrix.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import org.apache.ignite.IgniteCache; +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.MatrixKeyMapper; +import org.apache.ignite.ml.math.ValueMapper; +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.CacheMatrixStorage; + +/** + * Matrix based on existing cache and key and value mapping functions. + */ +public class CacheMatrix<K, V> extends AbstractMatrix { + /** + * + */ + public CacheMatrix() { + // No-op. + } + + /** + * Creates new matrix over existing cache. + * + * @param rows + * @param cols + * @param cache + * @param keyMapper + * @param valMapper + */ + public CacheMatrix( + int rows, + int cols, + IgniteCache<K, V> cache, + MatrixKeyMapper<K> keyMapper, + ValueMapper<V> valMapper) { + assert rows > 0; + assert cols > 0; + assert cache != null; + assert keyMapper != null; + assert valMapper != null; + + setStorage(new CacheMatrixStorage<>(rows, cols, cache, keyMapper, valMapper)); + } + + /** + * + * + */ + @SuppressWarnings({"unchecked"}) + private CacheMatrixStorage<K, V> storage() { + return (CacheMatrixStorage<K, V>)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param d + */ + @Override public Matrix divide(double d) { + return mapOverValues((Double v) -> v / d); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param x + */ + @Override public Matrix plus(double x) { + return mapOverValues((Double v) -> v + x); + } + + /** + * Return the same matrix with updates values (broken contract). + * + * @param x + */ + @Override public Matrix times(double x) { + return mapOverValues((Double v) -> v * x); + } + + /** {@inheritDoc} */ + @Override public Matrix assign(double val) { + return mapOverValues((Double v) -> val); + } + + /** {@inheritDoc} */ + @Override public Matrix map(IgniteDoubleFunction<Double> fun) { + return mapOverValues(fun::apply); + } + + /** {@inheritDoc} */ + @Override public double sum() { + CacheMatrixStorage<K, V> sto = storage(); + + return CacheUtils.sum(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public double maxValue() { + CacheMatrixStorage<K, V> sto = storage(); + + return CacheUtils.max(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** {@inheritDoc} */ + @Override public double minValue() { + CacheMatrixStorage<K, V> sto = storage(); + + return CacheUtils.min(sto.cache().getName(), sto.keyMapper(), sto.valueMapper()); + } + + /** + * @param mapper + */ + private Matrix mapOverValues(IgniteFunction<Double, Double> mapper) { + CacheMatrixStorage<K, V> sto = storage(); + + CacheUtils.map(sto.cache().getName(), sto.keyMapper(), sto.valueMapper(), mapper); + + return this; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOffHeapMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOffHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOffHeapMatrix.java new file mode 100644 index 0000000..4161228 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOffHeapMatrix.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.impls.storage.matrix.DenseOffHeapMatrixStorage; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOffHeapVector; + +/** + * Dense local off-heap implementation of the {@link Matrix} interface. + */ +public class DenseLocalOffHeapMatrix extends AbstractMatrix { + /** */ + public DenseLocalOffHeapMatrix() { + // No-op. + } + + /** + * @param data Backing data array. + */ + public DenseLocalOffHeapMatrix(double[][] data) { + assert data != null; + + setStorage(new DenseOffHeapMatrixStorage(data)); + } + + /** + * @param rows Amount of rows in matrix. + * @param cols Amount of columns in matrix. + */ + public DenseLocalOffHeapMatrix(int rows, int cols) { + assert rows > 0; + assert cols > 0; + + setStorage(new DenseOffHeapMatrixStorage(rows, cols)); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + DenseLocalOffHeapMatrix cp = new DenseLocalOffHeapMatrix(getStorage().rowSize(), getStorage().columnSize()); + + cp.assign(this); + + return cp; + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return new DenseLocalOffHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return new DenseLocalOffHeapVector(crd); + } + + /** {@inheritDoc} */ + @Override public void destroy() { + getStorage().destroy(); + } + + /** {@inheritDoc} */ + @Override protected Matrix likeIdentity() { + int n = rowSize(); + Matrix res = like(n, n); + + // IMPL NOTE as opposed to on-heap matrices this one isn't initialized with zeroes + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + res.setX(i, j, i == j ? 1.0 : 0.0); + + return res; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java new file mode 100644 index 0000000..f95e0cc --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DenseLocalOnHeapMatrix.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.impls.storage.matrix.ArrayMatrixStorage; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector; + +/** + * Basic implementation for matrix. + * + * This is a trivial implementation for matrix assuming dense logic, local on-heap JVM storage + * based on <code>double[][]</code> array. It is only suitable for data sets where + * local, non-distributed execution is satisfactory and on-heap JVM storage is enough + * to keep the entire data set. + */ +public class DenseLocalOnHeapMatrix extends AbstractMatrix { + /** + * + */ + public DenseLocalOnHeapMatrix() { + // No-op. + } + + /** + * @param rows Amount of rows in matrix. + * @param cols Amount of columns in matrix. + */ + public DenseLocalOnHeapMatrix(int rows, int cols) { + assert rows > 0; + assert cols > 0; + + setStorage(new ArrayMatrixStorage(rows, cols)); + } + + /** + * @param mtx Backing data array. + */ + public DenseLocalOnHeapMatrix(double[][] mtx) { + assert mtx != null; + + setStorage(new ArrayMatrixStorage(mtx)); + } + + /** + * @param orig Original matrix. + */ + private DenseLocalOnHeapMatrix(DenseLocalOnHeapMatrix orig) { + assert orig != null; + + setStorage(new ArrayMatrixStorage(orig.rowSize(), orig.columnSize())); + + assign(orig); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + return new DenseLocalOnHeapMatrix(this); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return new DenseLocalOnHeapMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return new DenseLocalOnHeapVector(crd); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DiagonalMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DiagonalMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DiagonalMatrix.java new file mode 100644 index 0000000..bd9a4a1 --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/DiagonalMatrix.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.impls.storage.matrix.DiagonalMatrixStorage; +import org.apache.ignite.ml.math.impls.vector.ConstantVector; +import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector; +import org.apache.ignite.ml.math.impls.vector.SingleElementVectorView; + +/** + * Implementation of diagonal view of the {@link Matrix}. + * + * <p>See also: <a href="https://en.wikipedia.org/wiki/Diagonal_matrix">Wikipedia article</a>.</p> + */ +public class DiagonalMatrix extends AbstractMatrix { + /** + * + */ + public DiagonalMatrix() { + // No-op. + } + + /** + * @param diagonal Backing {@link Vector}. + */ + public DiagonalMatrix(Vector diagonal) { + super(new DiagonalMatrixStorage(diagonal)); + } + + /** + * @param mtx Backing {@link Matrix}. + */ + public DiagonalMatrix(Matrix mtx) { + super(new DiagonalMatrixStorage(mtx == null ? null : mtx.viewDiagonal())); + } + + /** + * @param vals Backing array of values at diagonal. + */ + public DiagonalMatrix(double[] vals) { + super(new DiagonalMatrixStorage(new DenseLocalOnHeapVector(vals))); + } + + /** + * + * + */ + private DiagonalMatrixStorage storage() { + return (DiagonalMatrixStorage)getStorage(); + } + + /** + * @param size Size of diagonal. + * @param val Constant value at diagonal. + */ + public DiagonalMatrix(int size, double val) { + super(new DiagonalMatrixStorage(new ConstantVector(size, val))); + } + + /** {@inheritDoc} */ + @Override public Vector viewRow(int row) { + return new SingleElementVectorView(storage().diagonal(), row); + } + + /** {@inheritDoc} */ + @Override public Vector viewColumn(int col) { + return new SingleElementVectorView(storage().diagonal(), col); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + return new DiagonalMatrix(storage().diagonal()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + return storage().diagonal().likeMatrix(rows, cols); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + return storage().diagonal().like(crd); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/FunctionMatrix.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/FunctionMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/FunctionMatrix.java new file mode 100644 index 0000000..020d50a --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/FunctionMatrix.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import org.apache.ignite.ml.math.Matrix; +import org.apache.ignite.ml.math.Vector; +import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException; +import org.apache.ignite.ml.math.functions.IntIntDoubleToVoidFunction; +import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction; +import org.apache.ignite.ml.math.impls.storage.matrix.FunctionMatrixStorage; + +/** + * Implementation of {@link Matrix} that maps row and column index to {@link java.util.function} interfaces. + */ +public class FunctionMatrix extends AbstractMatrix { + /** + * + */ + public FunctionMatrix() { + // No-op. + } + + /** + * Creates read-write or read-only function matrix. + * + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param getFunc Function that returns value corresponding to given row and column index. + * @param setFunc Set function. If {@code null} - this will be a read-only matrix. + */ + public FunctionMatrix(int rows, int cols, IntIntToDoubleFunction getFunc, IntIntDoubleToVoidFunction setFunc) { + assert rows > 0; + assert cols > 0; + assert getFunc != null; + + setStorage(new FunctionMatrixStorage(rows, cols, getFunc, setFunc)); + } + + /** + * Creates read-only function matrix. + * + * @param rows Amount of rows in the matrix. + * @param cols Amount of columns in the matrix. + * @param getFunc Function that returns value corresponding to given row and column index. + */ + public FunctionMatrix(int rows, int cols, IntIntToDoubleFunction getFunc) { + assert rows > 0; + assert cols > 0; + assert getFunc != null; + + setStorage(new FunctionMatrixStorage(rows, cols, getFunc)); + } + + /** + * + * + */ + private FunctionMatrixStorage storage() { + return (FunctionMatrixStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + FunctionMatrixStorage sto = storage(); + + return new FunctionMatrix(sto.rowSize(), sto.columnSize(), sto.getFunction(), sto.setFunction()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + FunctionMatrixStorage sto = storage(); + + return new FunctionMatrix(rows, cols, sto.getFunction(), sto.setFunction()); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/d78e071a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixView.java ---------------------------------------------------------------------- diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixView.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixView.java new file mode 100644 index 0000000..89b031e --- /dev/null +++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixView.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ml.math.impls.matrix; + +import java.io.Externalizable; +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 the rectangular view into the parent {@link Matrix}. + */ +public class MatrixView extends AbstractMatrix { + /** + * Constructor for {@link Externalizable} interface. + */ + public MatrixView() { + // No-op. + } + + /** + * @param parent Backing parent {@link Matrix}. + * @param rowOff Row offset to parent matrix. + * @param colOff Column offset to parent matrix. + * @param rows Amount of rows in the view. + * @param cols Amount of columns in the view. + */ + public MatrixView(Matrix parent, int rowOff, int colOff, int rows, int cols) { + this(parent == null ? null : parent.getStorage(), rowOff, colOff, rows, cols); + } + + /** + * @param sto Backing parent {@link MatrixStorage}. + * @param rowOff Row offset to parent storage. + * @param colOff Column offset to parent storage. + * @param rows Amount of rows in the view. + * @param cols Amount of columns in the view. + */ + public MatrixView(MatrixStorage sto, int rowOff, int colOff, int rows, int cols) { + super(new MatrixDelegateStorage(sto, rowOff, colOff, rows, cols)); + } + + /** + * + * + */ + private MatrixDelegateStorage storage() { + return (MatrixDelegateStorage)getStorage(); + } + + /** {@inheritDoc} */ + @Override public Matrix copy() { + MatrixDelegateStorage sto = storage(); + + return new MatrixView(sto.delegate(), sto.rowOffset(), sto.columnOffset(), sto.rowSize(), sto.columnSize()); + } + + /** {@inheritDoc} */ + @Override public Matrix like(int rows, int cols) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override public Vector likeVector(int crd) { + throw new UnsupportedOperationException(); + } +}