From 8a9a0e160939e4fd60d3a131e957080d0e2e89bc Mon Sep 17 00:00:00 2001 From: e-strauss Date: Thu, 5 Sep 2024 12:21:11 +0200 Subject: [PATCH] [SYSTEMDS-3743] Python API Builtin cov Closes #2097 --- src/main/python/generator/generator.py | 2 +- .../systemds/operator/algorithm/__init__.py | 2 + .../operator/algorithm/builtin/cov.py | 39 ++++++++++ src/main/python/tests/algorithms/test_cov.py | 75 +++++++++++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/main/python/systemds/operator/algorithm/builtin/cov.py create mode 100644 src/main/python/tests/algorithms/test_cov.py diff --git a/src/main/python/generator/generator.py b/src/main/python/generator/generator.py index 2fbcd49b6bc..cb502d74c80 100644 --- a/src/main/python/generator/generator.py +++ b/src/main/python/generator/generator.py @@ -28,7 +28,7 @@ from typing import List, Tuple -manually_added_algorithm_builtins = [] +manually_added_algorithm_builtins = ["cov"] class PythonAPIFileGenerator(object): diff --git a/src/main/python/systemds/operator/algorithm/__init__.py b/src/main/python/systemds/operator/algorithm/__init__.py index baf2976e49f..b3273a818a5 100644 --- a/src/main/python/systemds/operator/algorithm/__init__.py +++ b/src/main/python/systemds/operator/algorithm/__init__.py @@ -37,6 +37,7 @@ from .builtin.components import components from .builtin.confusionMatrix import confusionMatrix from .builtin.cor import cor +from .builtin.cov import cov from .builtin.cox import cox from .builtin.cspline import cspline from .builtin.csplineCG import csplineCG @@ -210,6 +211,7 @@ 'components', 'confusionMatrix', 'cor', + 'cov', 'cox', 'cspline', 'csplineCG', diff --git a/src/main/python/systemds/operator/algorithm/builtin/cov.py b/src/main/python/systemds/operator/algorithm/builtin/cov.py new file mode 100644 index 00000000000..6dea3a94ca0 --- /dev/null +++ b/src/main/python/systemds/operator/algorithm/builtin/cov.py @@ -0,0 +1,39 @@ +# ------------------------------------------------------------- +# +# 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. +# +# ------------------------------------------------------------- + + +from systemds.operator import Matrix, Scalar + + +def cov(x: Matrix, y: Matrix, w: Matrix = None) -> "Scalar": + """ + Returns the covariance between two 1-dimensional column matrices X and Y. The function takes an optional weights + parameter W. All column matrices X, Y, and W (when specified) must have the exact same dimension. + + :param x: 1-dimensional column matrices x + :param y: 1-dimensional column matrices y + :param w: (optional) 1-dimensional weight column matrix + :return: Covariance of the input matrices + """ + if w is None: + return Scalar(x.sds_context, "cov", [x, y]) + else: + return Scalar(x.sds_context, "cov", [x, y, w]) diff --git a/src/main/python/tests/algorithms/test_cov.py b/src/main/python/tests/algorithms/test_cov.py new file mode 100644 index 00000000000..7a3e10be133 --- /dev/null +++ b/src/main/python/tests/algorithms/test_cov.py @@ -0,0 +1,75 @@ +# ------------------------------------------------------------- +# +# 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. +# +# ------------------------------------------------------------- + +import unittest + +import numpy as np + +from systemds.context import SystemDSContext +from systemds.operator.algorithm import cov + + +A = np.array([2, 4, 4, 2]) +B = np.array([2, 4, 2, 4]) +W = np.array([7, 1, 1, 1]) +C = np.array([0, 1, 2]) +D = np.array([2, 1, 0]) +E = np.array([2, 1, 0]) +F = np.array([2, 1, 0]) + + +class TestCOV(unittest.TestCase): + + sds: SystemDSContext = None + + @classmethod + def setUpClass(cls): + cls.sds = SystemDSContext() + + @classmethod + def tearDownClass(cls): + cls.sds.close() + + def test_cov1(self): + sds_result = cov(self.sds.from_numpy(A), self.sds.from_numpy(B)).compute() + np_result = np.cov(A, B) + self.assertTrue(np.allclose(sds_result, np_result[0, 1], 1e-9)) + + def test_cov2(self): + sds_result = cov(self.sds.from_numpy(C), self.sds.from_numpy(D)).compute() + np_result = np.cov(C, D) + self.assertTrue(np.allclose(sds_result, np_result[0, 1], 1e-9)) + + def test_cov3(self): + sds_result = cov(self.sds.from_numpy(E), self.sds.from_numpy(F)).compute() + np_result = np.cov(E, F) + self.assertTrue(np.allclose(sds_result, np_result[0, 1], 1e-9)) + + def test_cov4(self): + sds_result = cov( + self.sds.from_numpy(A), self.sds.from_numpy(B), self.sds.from_numpy(W) + ).compute() + np_result = np.cov(A, B, fweights=W) + self.assertTrue(np.allclose(sds_result, np_result[0, 1], 1e-9)) + + +if __name__ == "__main__": + unittest.main(exit=False)