From 312245394fa321ad4bf2d7bcebd11a6ec7919dd6 Mon Sep 17 00:00:00 2001 From: "[Ed Brown]" <[edwardjmv94@gmail.com]> Date: Mon, 12 Oct 2020 01:42:00 -0500 Subject: [PATCH 1/5] Adding documentation and styling the code The 2 Newton-Raphson algorithms were working ok. I added some documentation and style to make the code more readable. --- arithmetic_analysis/newton_method.py | 26 ++++++++++++++++-------- arithmetic_analysis/newton_raphson.py | 29 +++++++++++++++++---------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/arithmetic_analysis/newton_method.py b/arithmetic_analysis/newton_method.py index a9a94372671e..3f0c6c13db3c 100644 --- a/arithmetic_analysis/newton_method.py +++ b/arithmetic_analysis/newton_method.py @@ -6,13 +6,14 @@ RealFunc = Callable[[float], float] # type alias for a real -> real function -# function is the f(x) and derivative is the f'(x) +# function: f(x) +# derivative: f'(x) def newton( function: RealFunc, derivative: RealFunc, starting_int: int, ) -> float: - """ + """Calculates one root of function by Newton's method starting at x0 = starting_point >>> newton(lambda x: x ** 3 - 2 * x - 5, lambda x: 3 * x ** 2 - 2, 3) 2.0945514815423474 >>> newton(lambda x: x ** 3 - 1, lambda x: 3 * x ** 2, -2) @@ -31,24 +32,33 @@ def newton( ... ZeroDivisionError: Could not find root """ - prev_guess = float(starting_int) + prev_guess = float(starting_int) # sets the starting point for the algorithm while True: try: + # Calculates the next point based on x = x0 - f(x) / f'(x) next_guess = prev_guess - function(prev_guess) / derivative(prev_guess) except ZeroDivisionError: raise ZeroDivisionError("Could not find root") from None + if abs(prev_guess - next_guess) < 10 ** -5: + # The algorithm stops when the difference between the last 2 guesses are less + # than the fixed presition of 10 ** -5 return next_guess prev_guess = next_guess -def f(x: float) -> float: - return (x ** 3) - (2 * x) - 5 +def main(): + def f(x: float) -> float: + return (x ** 3) - (2 * x) - 5 + def f1(x: float) -> float: + return 3 * (x ** 2) - 2 -def f1(x: float) -> float: - return 3 * (x ** 2) - 2 + print(newton(f, f1, 3)) if __name__ == "__main__": - print(newton(f, f1, 3)) + import doctest + + doctest.testmod() + main() \ No newline at end of file diff --git a/arithmetic_analysis/newton_raphson.py b/arithmetic_analysis/newton_raphson.py index 948759a09a2a..a80f8c9213a9 100644 --- a/arithmetic_analysis/newton_raphson.py +++ b/arithmetic_analysis/newton_raphson.py @@ -8,8 +8,8 @@ from sympy import diff -def newton_raphson(func: str, a: int, precision: int = 10 ** -10) -> float: - """Finds root from the point 'a' onwards by Newton-Raphson method +def newton_raphson(func: str, x: int, precision: int = 10 ** -10) -> float: + """Finds root of func by Newton-Raphson method starting at x. >>> newton_raphson("sin(x)", 2) 3.1415926536808043 >>> newton_raphson("x**2 - 5*x +2", 0.4) @@ -19,22 +19,29 @@ def newton_raphson(func: str, a: int, precision: int = 10 ** -10) -> float: >>> newton_raphson("log(x)- 1", 2) 2.718281828458938 """ - x = a + while True: + # Evaluates f in x until it becomes "0" (the value given by the precision) + x = Decimal(x) - (Decimal(eval(func)) / Decimal(eval(str(diff(func))))) - # This number dictates the accuracy of the answer + # The next value of x. x_0 + f(x) / f'(x) + if abs(eval(func)) < precision: + # The algorithm stops when f(x) ~= 0 (precision) return float(x) # Let's Execute if __name__ == "__main__": - # Find root of trigonometric function - # Find value of pi - print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}") + import doctest + + doctest.testmod() + # Find root of trigonometric function (value of pi) + print(f"One root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}") + # Find root of polynomial - print(f"The root of x**2 - 5*x + 2 = 0 is {newton_raphson('x**2 - 5*x + 2', 0.4)}") - # Find Square Root of 5 - print(f"The root of log(x) - 1 = 0 is {newton_raphson('log(x) - 1', 2)}") + print(f"One root of x**2 - 5*x + 2 = 0 is {newton_raphson('x**2 - 5*x + 2', 0.4)}") + # Exponential Roots - print(f"The root of exp(x) - 1 = 0 is {newton_raphson('exp(x) - 1', 0)}") + print(f"One root of log(x) - 1 = 0 is {newton_raphson('log(x) - 1', 2)}") + print(f"One root of exp(x) - 1 = 0 is {newton_raphson('exp(x) - 1', 0)}") From 9679d69c275c46ab6e5dff0d8d2ded8eea6e37c5 Mon Sep 17 00:00:00 2001 From: "[Ed Brown]" <[edwardjmv94@gmail.com]> Date: Mon, 12 Oct 2020 23:45:32 -0500 Subject: [PATCH 2/5] Fix documentation and style on various files --- arithmetic_analysis/bisection.py | 9 ++-- arithmetic_analysis/gaussian_elimination.py | 2 +- arithmetic_analysis/intersection.py | 4 ++ arithmetic_analysis/lu_decomposition.py | 48 +++++++++++++++---- .../newton_forward_interpolation.py | 8 ++-- arithmetic_analysis/secant_method.py | 4 +- 6 files changed, 53 insertions(+), 22 deletions(-) diff --git a/arithmetic_analysis/bisection.py b/arithmetic_analysis/bisection.py index 0ef691678702..a4ee9b478aeb 100644 --- a/arithmetic_analysis/bisection.py +++ b/arithmetic_analysis/bisection.py @@ -25,9 +25,8 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float: return a elif function(b) == 0: return b - elif ( - function(a) * function(b) > 0 - ): # if none of these are root and they are both positive or negative, + elif function(a) * function(b) > 0: + # if none of these are root and they are both positive or negative, # then this algorithm can't find the root raise ValueError("could not find root in given interval.") else: @@ -48,8 +47,8 @@ def f(x: float) -> float: if __name__ == "__main__": - print(bisection(f, 1, 1000)) - import doctest doctest.testmod() + + print(bisection(f, 1, 1000)) \ No newline at end of file diff --git a/arithmetic_analysis/gaussian_elimination.py b/arithmetic_analysis/gaussian_elimination.py index 51207686c12a..b6032e440393 100644 --- a/arithmetic_analysis/gaussian_elimination.py +++ b/arithmetic_analysis/gaussian_elimination.py @@ -10,7 +10,7 @@ def retroactive_resolution(coefficients: np.matrix, vector: np.array) -> np.array: """ This function performs a retroactive linear system resolution - for triangular matrix + for triangular matrix Examples: 2x1 + 2x2 - 1x3 = 5 2x1 + 2x2 = -1 diff --git a/arithmetic_analysis/intersection.py b/arithmetic_analysis/intersection.py index 204dd5d8a935..0af62cd1cf4c 100644 --- a/arithmetic_analysis/intersection.py +++ b/arithmetic_analysis/intersection.py @@ -46,4 +46,8 @@ def f(x: float) -> float: if __name__ == "__main__": + import doctest + + doctest.testmod() + print(intersection(f, 3, 3.5)) diff --git a/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 763ba60f32b7..e06ec5f439b1 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -1,17 +1,41 @@ -"""Lower-Upper (LU) Decomposition.""" - -# lower–upper (LU) decomposition - https://en.wikipedia.org/wiki/LU_decomposition import numpy -def LUDecompose(table): - # Table that contains our data - # Table has to be a square array so we need to check first +def lower_upper_decompose(table: list) -> (list, list): + """Lower–Upper (LU) decomposition - https://en.wikipedia.org/wiki/LU_decomposition + + Args: + table (list): Table that contains our data + + Raises: + ValueError: If table is not an square array. + + Returns: + (list, list): L, U. Lower and upper arrays. + + >>> lower_upper_decompose(numpy.array([[2, -2, 1], [0, 1, 2], [5, 3]])) + Traceback (most recent call last): + ... + ValueError: not enough values to unpack (expected 2, got 1) + >>> lower_upper_decompose(numpy.array([[2, -2], [0, 1], [5, 3]])) + Traceback (most recent call last): + ... + ValueError: Table should be square array. + >>> matrix = numpy.array([[2, -2, 1], [0, 1, 2], [5, 3, -1]]) + >>> lower_upper_decompose(matrix) + (array([[1. , 0. , 0. ], + [0. , 1. , 0. ], + [2.5, 8. , 1. ]]), array([[ 2. , -2. , 1. ], + [ 0. , 1. , 2. ], + [ 0. , 0. , -19.5]])) + """ + # table input has to be a square array so we need to check first rows, columns = numpy.shape(table) + if rows != columns: + raise ValueError("Table should be square array.") + L = numpy.zeros((rows, columns)) U = numpy.zeros((rows, columns)) - if rows != columns: - return [] for i in range(columns): for j in range(i): sum = 0 @@ -28,7 +52,11 @@ def LUDecompose(table): if __name__ == "__main__": - matrix = numpy.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]]) - L, U = LUDecompose(matrix) + import doctest + + doctest.testmod() + + matrix = numpy.array([[2, -2, 1], [0, 1, 2], [5, 3, 3]]) + L, U = lower_upper_decompose(matrix) print(L) print(U) diff --git a/arithmetic_analysis/newton_forward_interpolation.py b/arithmetic_analysis/newton_forward_interpolation.py index d32e3efbd1f2..a83bef6ed8a6 100644 --- a/arithmetic_analysis/newton_forward_interpolation.py +++ b/arithmetic_analysis/newton_forward_interpolation.py @@ -20,7 +20,7 @@ def ucal(u, p): def main(): - n = int(input("enter the numbers of values: ")) + n = int(input("enter the numbers of values: ").strip()) y = [] for i in range(n): y.append([]) @@ -30,13 +30,13 @@ def main(): y[i][j] = 0 print("enter the values of parameters in a list: ") - x = list(map(int, input().split())) + x = list(map(int, input().strip().split())) print("enter the values of corresponding parameters: ") for i in range(n): - y[i][0] = float(input()) + y[i][0] = float(input().strip()) - value = int(input("enter the value to interpolate: ")) + value = int(input("enter the value to interpolate: ").strip()) u = (value - x[0]) / (x[1] - x[0]) # for calculating forward difference table diff --git a/arithmetic_analysis/secant_method.py b/arithmetic_analysis/secant_method.py index b05d44c627d8..73a651bda349 100644 --- a/arithmetic_analysis/secant_method.py +++ b/arithmetic_analysis/secant_method.py @@ -13,7 +13,7 @@ def f(x): return 8 * x - 2 * exp(-x) -def SecantMethod(lower_bound, upper_bound, repeats): +def secant_method(lower_bound, upper_bound, repeats): """ >>> SecantMethod(1, 3, 2) 0.2139409276214589 @@ -25,4 +25,4 @@ def SecantMethod(lower_bound, upper_bound, repeats): return x1 -print(f"The solution is: {SecantMethod(1, 3, 2)}") +print(f"The solution is: {secant_method(1, 3, 2)}") From 9098e62ce073d361eafbe9aa3acb396faca1ff3d Mon Sep 17 00:00:00 2001 From: "[Ed Brown]" <[edwardjmv94@gmail.com]> Date: Tue, 13 Oct 2020 21:28:31 -0500 Subject: [PATCH 3/5] Correct function name --- arithmetic_analysis/secant_method.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arithmetic_analysis/secant_method.py b/arithmetic_analysis/secant_method.py index 73a651bda349..1f36d560c970 100644 --- a/arithmetic_analysis/secant_method.py +++ b/arithmetic_analysis/secant_method.py @@ -15,7 +15,7 @@ def f(x): def secant_method(lower_bound, upper_bound, repeats): """ - >>> SecantMethod(1, 3, 2) + >>> secant_method(1, 3, 2) 0.2139409276214589 """ x0 = lower_bound From 36a491762d02357b34cae4225a641dfba5819d04 Mon Sep 17 00:00:00 2001 From: "[Ed Brown]" <[edwardjmv94@gmail.com]> Date: Tue, 13 Oct 2020 22:38:50 -0500 Subject: [PATCH 4/5] New line at the end of the file and line too long correction --- arithmetic_analysis/bisection.py | 3 ++- arithmetic_analysis/newton_method.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/arithmetic_analysis/bisection.py b/arithmetic_analysis/bisection.py index a4ee9b478aeb..bbb847018f82 100644 --- a/arithmetic_analysis/bisection.py +++ b/arithmetic_analysis/bisection.py @@ -51,4 +51,5 @@ def f(x: float) -> float: doctest.testmod() - print(bisection(f, 1, 1000)) \ No newline at end of file + print(bisection(f, 1, 1000)) + \ No newline at end of file diff --git a/arithmetic_analysis/newton_method.py b/arithmetic_analysis/newton_method.py index 3f0c6c13db3c..26ae205ab720 100644 --- a/arithmetic_analysis/newton_method.py +++ b/arithmetic_analysis/newton_method.py @@ -41,8 +41,8 @@ def newton( raise ZeroDivisionError("Could not find root") from None if abs(prev_guess - next_guess) < 10 ** -5: - # The algorithm stops when the difference between the last 2 guesses are less - # than the fixed presition of 10 ** -5 + # The algorithm stops when the difference between the last 2 guesses are + # less than the fixed presition of 10 ** -5 return next_guess prev_guess = next_guess @@ -61,4 +61,4 @@ def f1(x: float) -> float: import doctest doctest.testmod() - main() \ No newline at end of file + main() From 0dce2cd59b43ce62a3a740807e2a3a3fd998a77b Mon Sep 17 00:00:00 2001 From: "[Ed Brown]" <[edwardjmv94@gmail.com]> Date: Tue, 13 Oct 2020 22:43:28 -0500 Subject: [PATCH 5/5] Trailing whitespaces --- arithmetic_analysis/bisection.py | 1 - 1 file changed, 1 deletion(-) diff --git a/arithmetic_analysis/bisection.py b/arithmetic_analysis/bisection.py index bbb847018f82..1cf19db67ac8 100644 --- a/arithmetic_analysis/bisection.py +++ b/arithmetic_analysis/bisection.py @@ -52,4 +52,3 @@ def f(x: float) -> float: doctest.testmod() print(bisection(f, 1, 1000)) - \ No newline at end of file