From 190afd4669c7c4fc3cfe82b7825913b07f27643b Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Mon, 7 Aug 2023 11:56:41 +0000 Subject: [PATCH 1/7] updating DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index fdcf0ceedf1f..e6a1ff356143 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -585,6 +585,7 @@ * [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py) * [Hexagonal Number](maths/hexagonal_number.py) * [Integration By Simpson Approx](maths/integration_by_simpson_approx.py) + * [Interquartile Range](maths/interquartile_range.py) * [Is Int Palindrome](maths/is_int_palindrome.py) * [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py) * [Is Square Free](maths/is_square_free.py) From 2fb8e12588ce8d518676138efe57d899c307dc4f Mon Sep 17 00:00:00 2001 From: CaedenPH Date: Mon, 14 Aug 2023 11:16:31 +0100 Subject: [PATCH 2/7] types(maths): Fix pylance issues in maths --- .vscode/settings.json | 4 +- .../erosion_operation.py | 6 +-- digital_image_processing/rotation/rotation.py | 4 +- maths/average_median.py | 4 +- maths/euler_modified.py | 2 +- maths/gaussian_error_linear_unit.py | 4 +- maths/jaccard_similarity.py | 40 +++++++++++++------ maths/newton_raphson.py | 2 +- maths/qr_decomposition.py | 2 +- maths/sigmoid.py | 2 +- maths/tanh.py | 4 +- 11 files changed, 47 insertions(+), 27 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ef16fa1aa7ac..283eb10a782a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,7 @@ { "githubPullRequests.ignoredPullRequestBranches": [ "master" - ] + ], + "python.analysis.diagnosticMode": "openFilesOnly", + "python.analysis.typeCheckingMode": "basic" } diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index c2cde2ea6990..c801d216f96e 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -2,7 +2,7 @@ from PIL import Image -def rgb2gray(rgb: np.array) -> np.array: +def rgb2gray(rgb: np.ndarray) -> np.ndarray: """ Return gray image from rgb image >>> rgb2gray(np.array([[[127, 255, 0]]])) @@ -18,7 +18,7 @@ def rgb2gray(rgb: np.array) -> np.array: return 0.2989 * r + 0.5870 * g + 0.1140 * b -def gray2binary(gray: np.array) -> np.array: +def gray2binary(gray: np.ndarray) -> np.ndarray: """ Return binary image from gray image >>> gray2binary(np.array([[127, 255, 0]])) @@ -35,7 +35,7 @@ def gray2binary(gray: np.array) -> np.array: return (gray > 127) & (gray <= 255) -def erosion(image: np.array, kernel: np.array) -> np.array: +def erosion(image: np.ndarray, kernel: np.ndarray) -> np.ndarray: """ Return eroded image >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0]])) diff --git a/digital_image_processing/rotation/rotation.py b/digital_image_processing/rotation/rotation.py index 958d16fafb91..0f5e36ddd5be 100644 --- a/digital_image_processing/rotation/rotation.py +++ b/digital_image_processing/rotation/rotation.py @@ -10,12 +10,12 @@ def get_rotation( ) -> np.ndarray: """ Get image rotation - :param img: np.array + :param img: np.ndarray :param pt1: 3x2 list :param pt2: 3x2 list :param rows: columns image shape :param cols: rows image shape - :return: np.array + :return: np.ndarray """ matrix = cv2.getAffineTransform(pt1, pt2) return cv2.warpAffine(img, matrix, (rows, cols)) diff --git a/maths/average_median.py b/maths/average_median.py index cd1ec1574893..f24e525736b3 100644 --- a/maths/average_median.py +++ b/maths/average_median.py @@ -19,7 +19,9 @@ def median(nums: list) -> int | float: Returns: Median. """ - sorted_list = sorted(nums) + # The sorted function returns list[SupportsRichComparisonT@sorted] + # which does not support `+` + sorted_list: list[int] = sorted(nums) length = len(sorted_list) mid_index = length >> 1 return ( diff --git a/maths/euler_modified.py b/maths/euler_modified.py index 14bddadf4c53..d02123e1e2fb 100644 --- a/maths/euler_modified.py +++ b/maths/euler_modified.py @@ -5,7 +5,7 @@ def euler_modified( ode_func: Callable, y0: float, x0: float, step_size: float, x_end: float -) -> np.array: +) -> np.ndarray: """ Calculate solution at each step to an ODE using Euler's Modified Method The Euler Method is straightforward to implement, but can't give accurate solutions. diff --git a/maths/gaussian_error_linear_unit.py b/maths/gaussian_error_linear_unit.py index 7b5f875143b9..18384bb6c864 100644 --- a/maths/gaussian_error_linear_unit.py +++ b/maths/gaussian_error_linear_unit.py @@ -13,7 +13,7 @@ import numpy as np -def sigmoid(vector: np.array) -> np.array: +def sigmoid(vector: np.ndarray) -> np.ndarray: """ Mathematical function sigmoid takes a vector x of K real numbers as input and returns 1/ (1 + e^-x). @@ -25,7 +25,7 @@ def sigmoid(vector: np.array) -> np.array: return 1 / (1 + np.exp(-vector)) -def gaussian_error_linear_unit(vector: np.array) -> np.array: +def gaussian_error_linear_unit(vector: np.ndarray) -> np.ndarray: """ Implements the Gaussian Error Linear Unit (GELU) function diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index 32054414c0c2..6fde89b2de98 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -14,7 +14,11 @@ """ -def jaccard_similarity(set_a, set_b, alternative_union=False): +def jaccard_similarity( + set_a: set[str] | list[str] | tuple[str], + set_b: set[str] | list[str] | tuple[str], + alternative_union=False, +): """ Finds the jaccard similarity between two sets. Essentially, its intersection over union. @@ -48,30 +52,42 @@ def jaccard_similarity(set_a, set_b, alternative_union=False): >>> set_b = ('c', 'd', 'e', 'f', 'h', 'i') >>> jaccard_similarity(set_a, set_b) 0.375 + + >>> set_a = ('c', 'd', 'e', 'f', 'h', 'i') + >>> set_b = ['a', 'b', 'c', 'd', 'e'] + >>> jaccard_similarity(set_a, set_b) + 0.375 + + >>> set_a = {'a', 'b'} + >>> set_b = ['c', 'd'] + >>> jaccard_similarity(set_a, set_b) + Traceback (most recent call last): + ... + ValueError: Set a and b must either both be sets or be either a list or a tuple. """ if isinstance(set_a, set) and isinstance(set_b, set): - intersection = len(set_a.intersection(set_b)) + intersection_length = len(set_a.intersection(set_b)) if alternative_union: - union = len(set_a) + len(set_b) + union_length = len(set_a) + len(set_b) else: - union = len(set_a.union(set_b)) + union_length = len(set_a.union(set_b)) - return intersection / union + return intersection_length / union_length - if isinstance(set_a, (list, tuple)) and isinstance(set_b, (list, tuple)): + elif isinstance(set_a, (list, tuple)) and isinstance(set_b, (list, tuple)): intersection = [element for element in set_a if element in set_b] if alternative_union: - union = len(set_a) + len(set_b) - return len(intersection) / union + return len(intersection) / len(set_a) + len(set_b) else: - union = set_a + [element for element in set_b if element not in set_a] + # Cast set_a to list because tuples cannot be mutated + union = list(set_a) + [element for element in set_b if element not in set_a] return len(intersection) / len(union) - - return len(intersection) / len(union) - return None + raise ValueError( + "Set a and b must either both be sets or be either a list or a tuple." + ) if __name__ == "__main__": diff --git a/maths/newton_raphson.py b/maths/newton_raphson.py index 2c9cd1de95b0..9caa8583a344 100644 --- a/maths/newton_raphson.py +++ b/maths/newton_raphson.py @@ -36,7 +36,7 @@ def newton_raphson(f, x0=0, maxiter=100, step=0.0001, maxerror=1e-6, logsteps=Fa if logsteps: # If logstep is true, then log intermediate steps return a, error, steps - return a, error + return a, error, [] if __name__ == "__main__": diff --git a/maths/qr_decomposition.py b/maths/qr_decomposition.py index a8414fbece87..670b49206aa7 100644 --- a/maths/qr_decomposition.py +++ b/maths/qr_decomposition.py @@ -1,7 +1,7 @@ import numpy as np -def qr_householder(a): +def qr_householder(a: np.ndarray): """Return a QR-decomposition of the matrix A using Householder reflection. The QR-decomposition decomposes the matrix A of shape (m, n) into an diff --git a/maths/sigmoid.py b/maths/sigmoid.py index 147588e8871f..cb45bde2702c 100644 --- a/maths/sigmoid.py +++ b/maths/sigmoid.py @@ -11,7 +11,7 @@ import numpy as np -def sigmoid(vector: np.array) -> np.array: +def sigmoid(vector: np.ndarray) -> np.ndarray: """ Implements the sigmoid function diff --git a/maths/tanh.py b/maths/tanh.py index ddab3e1ab717..38a369d9118d 100644 --- a/maths/tanh.py +++ b/maths/tanh.py @@ -12,12 +12,12 @@ import numpy as np -def tangent_hyperbolic(vector: np.array) -> np.array: +def tangent_hyperbolic(vector: np.ndarray) -> np.ndarray: """ Implements the tanh function Parameters: - vector: np.array + vector: np.ndarray Returns: tanh (np.array): The input numpy array after applying tanh. From 787b55e5e5939ddc0b42bcdce59d5f30c2667090 Mon Sep 17 00:00:00 2001 From: CaedenPH Date: Mon, 14 Aug 2023 11:23:52 +0100 Subject: [PATCH 3/7] reset(vsc): Reset settings changes --- .vscode/settings.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 283eb10a782a..ef16fa1aa7ac 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,5 @@ { "githubPullRequests.ignoredPullRequestBranches": [ "master" - ], - "python.analysis.diagnosticMode": "openFilesOnly", - "python.analysis.typeCheckingMode": "basic" + ] } From eaa8775a9743037ece94210f21bc095f97cd2dfb Mon Sep 17 00:00:00 2001 From: Caeden Perelli-Harris Date: Mon, 14 Aug 2023 12:09:52 +0100 Subject: [PATCH 4/7] Update maths/jaccard_similarity.py Co-authored-by: Tianyi Zheng --- maths/jaccard_similarity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index 6fde89b2de98..a342ac163941 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -80,7 +80,7 @@ def jaccard_similarity( intersection = [element for element in set_a if element in set_b] if alternative_union: - return len(intersection) / len(set_a) + len(set_b) + return len(intersection) / (len(set_a) + len(set_b)) else: # Cast set_a to list because tuples cannot be mutated union = list(set_a) + [element for element in set_b if element not in set_a] From 280a3bbe6e8de2f448669d7226b864b12fd524ad Mon Sep 17 00:00:00 2001 From: caedenph Date: Mon, 14 Aug 2023 12:12:44 +0100 Subject: [PATCH 5/7] revert(erosion_operation): Revert erosion_operation --- .../morphological_operations/erosion_operation.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/digital_image_processing/morphological_operations/erosion_operation.py b/digital_image_processing/morphological_operations/erosion_operation.py index c801d216f96e..c0e1ef847237 100644 --- a/digital_image_processing/morphological_operations/erosion_operation.py +++ b/digital_image_processing/morphological_operations/erosion_operation.py @@ -2,7 +2,7 @@ from PIL import Image -def rgb2gray(rgb: np.ndarray) -> np.ndarray: +def rgb2gray(rgb: np.array) -> np.array: """ Return gray image from rgb image >>> rgb2gray(np.array([[[127, 255, 0]]])) @@ -18,9 +18,10 @@ def rgb2gray(rgb: np.ndarray) -> np.ndarray: return 0.2989 * r + 0.5870 * g + 0.1140 * b -def gray2binary(gray: np.ndarray) -> np.ndarray: +def gray2binary(gray: np.array) -> np.array: """ Return binary image from gray image + >>> gray2binary(np.array([[127, 255, 0]])) array([[False, True, False]]) >>> gray2binary(np.array([[0]])) @@ -35,7 +36,7 @@ def gray2binary(gray: np.ndarray) -> np.ndarray: return (gray > 127) & (gray <= 255) -def erosion(image: np.ndarray, kernel: np.ndarray) -> np.ndarray: +def erosion(image: np.array, kernel: np.array) -> np.array: """ Return eroded image >>> erosion(np.array([[True, True, False]]), np.array([[0, 1, 0]])) From dcc016ecd4fc3361df02ac0db9cd09b929245968 Mon Sep 17 00:00:00 2001 From: caedenph Date: Mon, 14 Aug 2023 12:13:24 +0100 Subject: [PATCH 6/7] test(jaccard_similarity): Add doctest to test alternative_union --- maths/jaccard_similarity.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/maths/jaccard_similarity.py b/maths/jaccard_similarity.py index a342ac163941..6b6243458fa8 100644 --- a/maths/jaccard_similarity.py +++ b/maths/jaccard_similarity.py @@ -41,23 +41,22 @@ def jaccard_similarity( >>> set_b = {'c', 'd', 'e', 'f', 'h', 'i'} >>> jaccard_similarity(set_a, set_b) 0.375 - >>> jaccard_similarity(set_a, set_a) 1.0 - >>> jaccard_similarity(set_a, set_a, True) 0.5 - >>> set_a = ['a', 'b', 'c', 'd', 'e'] >>> set_b = ('c', 'd', 'e', 'f', 'h', 'i') >>> jaccard_similarity(set_a, set_b) 0.375 - >>> set_a = ('c', 'd', 'e', 'f', 'h', 'i') >>> set_b = ['a', 'b', 'c', 'd', 'e'] >>> jaccard_similarity(set_a, set_b) 0.375 - + >>> set_a = ('c', 'd', 'e', 'f', 'h', 'i') + >>> set_b = ['a', 'b', 'c', 'd'] + >>> jaccard_similarity(set_a, set_b, True) + 0.2 >>> set_a = {'a', 'b'} >>> set_b = ['c', 'd'] >>> jaccard_similarity(set_a, set_b) From 7ced878911415ed407e697016e3a7edde8c0afde Mon Sep 17 00:00:00 2001 From: caedenph Date: Mon, 14 Aug 2023 12:22:05 +0100 Subject: [PATCH 7/7] types(newton_raphson): Add typehints to func bodies --- maths/newton_raphson.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/maths/newton_raphson.py b/maths/newton_raphson.py index 9caa8583a344..f6b227b5c9c1 100644 --- a/maths/newton_raphson.py +++ b/maths/newton_raphson.py @@ -1,16 +1,20 @@ """ - Author: P Shreyas Shetty - Implementation of Newton-Raphson method for solving equations of kind - f(x) = 0. It is an iterative method where solution is found by the expression - x[n+1] = x[n] + f(x[n])/f'(x[n]) - If no solution exists, then either the solution will not be found when iteration - limit is reached or the gradient f'(x[n]) approaches zero. In both cases, exception - is raised. If iteration limit is reached, try increasing maxiter. - """ +Author: P Shreyas Shetty +Implementation of Newton-Raphson method for solving equations of kind +f(x) = 0. It is an iterative method where solution is found by the expression + x[n+1] = x[n] + f(x[n])/f'(x[n]) +If no solution exists, then either the solution will not be found when iteration +limit is reached or the gradient f'(x[n]) approaches zero. In both cases, exception +is raised. If iteration limit is reached, try increasing maxiter. +""" + import math as m +from collections.abc import Callable + +DerivativeFunc = Callable[[float], float] -def calc_derivative(f, a, h=0.001): +def calc_derivative(f: DerivativeFunc, a: float, h: float = 0.001) -> float: """ Calculates derivative at point a for function f using finite difference method @@ -18,7 +22,14 @@ def calc_derivative(f, a, h=0.001): return (f(a + h) - f(a - h)) / (2 * h) -def newton_raphson(f, x0=0, maxiter=100, step=0.0001, maxerror=1e-6, logsteps=False): +def newton_raphson( + f: DerivativeFunc, + x0: float = 0, + maxiter: int = 100, + step: float = 0.0001, + maxerror: float = 1e-6, + logsteps: bool = False, +) -> tuple[float, float, list[float]]: a = x0 # set the initial guess steps = [a] error = abs(f(a))