From 3fa1efd4cbe4478469965fab24af294e8147fa53 Mon Sep 17 00:00:00 2001 From: ravi-ivar-7 Date: Thu, 26 Oct 2023 01:49:18 +0530 Subject: [PATCH 1/9] added runge kutta gills method --- maths/numerical_analysis/runge_kutta_gills.py | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 maths/numerical_analysis/runge_kutta_gills.py diff --git a/maths/numerical_analysis/runge_kutta_gills.py b/maths/numerical_analysis/runge_kutta_gills.py new file mode 100644 index 000000000000..0f4e585a1f72 --- /dev/null +++ b/maths/numerical_analysis/runge_kutta_gills.py @@ -0,0 +1,90 @@ +""" +Use the Runge-Kutta-Gill's method of order 4 to solve Ordinary Differential Equations. + + +https://www.geeksforgeeks.org/gills-4th-order-method-to-solve-differential-equations/ +Author : Ravi Kumar +""" +from collections.abc import Callable +from math import sqrt + +import numpy as np + + +def runge_kutta_gills( + func: Callable[[float, float], float], + x_initial: float, + y_initial: float, + step_size: float, + x_final: float, +) -> np.ndarray: + """ + Solve an Ordinary Differential Equations using Runge-Kutta-Gills Method of order 4. + + args: + func: An ordinary differential equation (ODE) as function of x and y. + x_initial: The initial value of x. + y_initial: The initial value of y. + step_size: The increment value of x. + x_final: The final value of x. + + Returns: + Solution of y at each nodal point + + >>> def f(x, y): + ... return (x-y)/2 + >>> y = runge_kutta_gills(f, 0, 3, 0.2, 5) + >>> y[-1] + 3.4104259225717537 + + >>> def f(x,y): + ... return x + >>> y = runge_kutta_gills(f, -1, 0, 0.2, 0) + >>> y + array([ 0. , -0.18, -0.32, -0.42, -0.48, -0.5 ]) + + >>> def f(x, y): + ... return x + y + >>> y = runge_kutta_gills(f, 0, 0, 0.2, -1) + Traceback (most recent call last): + ... + ValueError: The final value of x must be greater than initial value of x. + + >>> def f(x, y): + ... return x + >>> y = runge_kutta_gills(f, -1, 0, -0.2, 0) + Traceback (most recent call last): + ... + ValueError: Step size must be positive. + """ + if x_initial >= x_final: + raise ValueError( + "The final value of x must be greater than initial value of x." + ) + + if step_size <= 0: + raise ValueError("Step size must be positive.") + + n = int((x_final - x_initial) / step_size) + y = np.zeros(n + 1) + y[0] = y_initial + for i in range(n): + k1 = step_size * func(x_initial, y[i]) + k2 = step_size * func(x_initial + step_size / 2, y[i] + k1 / 2) + k3 = step_size * func( + x_initial + step_size / 2, + y[i] + (-0.5 + 1 / sqrt(2)) * k1 + (1 - 1 / sqrt(2)) * k2, + ) + k4 = step_size * func( + x_initial + step_size, y[i] - (1 / sqrt(2)) * k2 + (1 + 1 / sqrt(2)) * k3 + ) + + y[i + 1] = y[i] + (k1 + (2 - sqrt(2)) * k2 + (2 + sqrt(2)) * k3 + k4) / 6 + x_initial = step_size + x_initial + return y + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 418693c02b34ae7c171ab0f1132fd4edc3224870 Mon Sep 17 00:00:00 2001 From: ravi-ivar-7 Date: Thu, 26 Oct 2023 01:55:09 +0530 Subject: [PATCH 2/9] added adams-bashforth method of order 2, 3, 4, 5 --- maths/numerical_analysis/adams_bashforth.py | 172 ++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 maths/numerical_analysis/adams_bashforth.py diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py new file mode 100644 index 000000000000..a6454b113ed3 --- /dev/null +++ b/maths/numerical_analysis/adams_bashforth.py @@ -0,0 +1,172 @@ +""" +Use the Adams-Bashforth methods to solve Ordinary Differential Equations. + + +https://en.wikipedia.org/wiki/Linear_multistep_method +Author : Ravi Kumar +""" +from collections.abc import Callable + +import numpy as np + +class AdamsBashforth: + def __init__(self, func: Callable[[float, float], float], x_initials: list[float], y_initials: list[float], step_size: float, x_final: float): + + if x_initials[-1] >= x_final: + raise ValueError("The final value of x must be greater than the initial values of x.") + + if step_size <= 0: + raise ValueError("Step size must be positive.") + + if not all(x1 - x0 == step_size for x0, x1 in zip(x_initials, x_initials[1:])): + raise ValueError("x-values must be equally spaced according to step size.") + + self.func = func + self.x_initials = x_initials + self.y_initials = y_initials + self.step_size = step_size + self.x_final = x_final + + """ + args: + func: An ordinary differential equation (ODE) as function of x and y. + x_initials: List containing initial required values of x. + y_initials: List containing initial required values of y. + step_size: The increment value of x. + x_final: The final value of x. + + Returns: Solution of y at each nodal point + + >>> def f(x, y): + ... return x + >>> y = AdamsBashforth(f, [0, 0.2], [0, 0], 0.2, 1).step_2() + >>> y + array([0. 0. 0.06 0.178 0.3654 0.63722]) + + >>> def f(x,y): + ... return x + y + >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6], [0, 0, 0.04, 0.128], 0.2, 1).step_4() + >>> y[-1] + 0.57710833 + + >>> def f(x, y): + ... return x + y + >>> y = AdamsBashforth(f, [0, 0.2, 1], [0, 0, 0.04], 0.2, 1).step_3() + Traceback (most recent call last): + ... + ValueError: The final value of x must be greater than the all initial values of x. + + >>> def f(x, y): + ... return x + y + >>> y = AdamsBashforth(f, [0, 0.2, 0.3], [0, 0, 0.04], 0.2, 1).step_3() + Traceback (most recent call last): + ... + ValueError: x-values must be equally spaced according to step size. + + >>> def f(x, y): + ... return x + >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6, 0.8], [0, 0, 0.04, 0.128, 0.307], -0.2, 1).step_5() + Traceback (most recent call last): + ... + ValueError: Step size must be positive. + + >>> def f(x, y): + ... return (x -y)/2 + >>> y = AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_2() + Traceback (most recent call last): + ... + ValueError: Insufficient nodal points values information. + """ + + def step_2(self) -> np.ndarray: + if len(self.x_initials) != 2 or len(self.y_initials) != 2: + raise ValueError("Insufficient nodal points values information.") + + x_0, x_1 = self.x_initials[:2] + y_0, y_1 = self.y_initials[:2] + + n = int((self.x_final - x_1) / self.step_size) + y = np.zeros(n + 2) + y[0] = y_0 + y[1] = y_1 + + for i in range(n): + y[i+2] = y[i+1] + (self.step_size/2)*(3*self.func(x_1, y[i+1]) - self.func(x_0, y[i])) + x_0 = x_1 + x_1 = x_1 + self.step_size + + return y + + def step_3(self) -> np.ndarray: + if len(self.x_initials) != 3 or len(self.y_initials) != 3: + raise ValueError("Insufficient nodal points information.") + + x_0, x_1, x_2 = self.x_initials[:3] + y_0, y_1, y_2 = self.y_initials[:3] + + n = int((self.x_final - x_2) / self.step_size) + y = np.zeros(n + 4) + y[0] = y_0 + y[1] = y_1 + y[2] = y_2 + + for i in range(n+1): + y[i+3] = y[i+2] + (self.step_size/12)*(23*self.func(x_2 , y[i+2]) -16*self.func(x_1, y[i+1]) + 5*self.func(x_0, y[i])) + x_0 = x_1 + x_1 = x_2 + x_2 = x_2 + self.step_size + + return y + + def step_4(self) -> np.ndarray: + if len(self.x_initials) != 4 or len(self.y_initials) != 4: + raise ValueError("Insufficient nodal points information.") + + x_0, x_1, x_2, x_3 = self.x_initials[:4] + y_0, y_1, y_2, y_3 = self.y_initials[:4] + + n = int((self.x_final - x_3) / self.step_size) + y = np.zeros(n + 4) + y[0] = y_0 + y[1] = y_1 + y[2] = y_2 + y[3] = y_3 + + for i in range(n): + y[i+4] = y[i+3] + (self.step_size/24) * (55 * self.func(x_3, y[i+3]) - 59 * self.func(x_2 , y[i+2]) + 37*self.func(x_1, y[i+1]) - 9*self.func(x_0, y[i])) + x_0 = x_1 + x_1 = x_2 + x_2 = x_3 + x_3 = x_3 + self.step_size + + return y + + def step_5(self) -> np.ndarray: + if len(self.x_initials) != 5 or len(self.y_initials) != 5: + raise ValueError("Insufficient nodal points information.") + + x_0, x_1, x_2, x_3, x_4 = self.x_initials[:5] + y_0, y_1, y_2, y_3, y_4 = self.y_initials[:5] + + n = int((self.x_final - x_4) / self.step_size) + y = np.zeros(n + 6) + y[0] = y_0 + y[1] = y_1 + y[2] = y_2 + y[3] = y_3 + y[4] = y_4 + + for i in range(n+1): + y[i+5] = y[i+4] + (self.step_size/720) * (1901 * self.func(x_4, y[i+4]) - 2774 * self.func(x_3, y[i+3]) - 2616 * self.func(x_2 , y[i+2]) - 1274 *self.func(x_1, y[i+1]) + 251*self.func(x_0, y[i])) + x_0 = x_1 + x_1 = x_2 + x_2 = x_3 + x_3 = x_4 + x_4 = x_4 + self.step_size + + return y + +if __name__ == "__main__": + import doctest + + doctest.testmod() \ No newline at end of file From 548777cbbc77a9143297477274bc2afd3cbd6262 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 20:30:55 +0000 Subject: [PATCH 3/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/numerical_analysis/adams_bashforth.py | 49 ++++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py index a6454b113ed3..6475e5983d14 100644 --- a/maths/numerical_analysis/adams_bashforth.py +++ b/maths/numerical_analysis/adams_bashforth.py @@ -9,11 +9,20 @@ import numpy as np -class AdamsBashforth: - def __init__(self, func: Callable[[float, float], float], x_initials: list[float], y_initials: list[float], step_size: float, x_final: float): +class AdamsBashforth: + def __init__( + self, + func: Callable[[float, float], float], + x_initials: list[float], + y_initials: list[float], + step_size: float, + x_final: float, + ): if x_initials[-1] >= x_final: - raise ValueError("The final value of x must be greater than the initial values of x.") + raise ValueError( + "The final value of x must be greater than the initial values of x." + ) if step_size <= 0: raise ValueError("Step size must be positive.") @@ -69,7 +78,7 @@ def __init__(self, func: Callable[[float, float], float], x_initials: list[float Traceback (most recent call last): ... ValueError: Step size must be positive. - + >>> def f(x, y): ... return (x -y)/2 >>> y = AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_2() @@ -91,7 +100,9 @@ def step_2(self) -> np.ndarray: y[1] = y_1 for i in range(n): - y[i+2] = y[i+1] + (self.step_size/2)*(3*self.func(x_1, y[i+1]) - self.func(x_0, y[i])) + y[i + 2] = y[i + 1] + (self.step_size / 2) * ( + 3 * self.func(x_1, y[i + 1]) - self.func(x_0, y[i]) + ) x_0 = x_1 x_1 = x_1 + self.step_size @@ -110,8 +121,12 @@ def step_3(self) -> np.ndarray: y[1] = y_1 y[2] = y_2 - for i in range(n+1): - y[i+3] = y[i+2] + (self.step_size/12)*(23*self.func(x_2 , y[i+2]) -16*self.func(x_1, y[i+1]) + 5*self.func(x_0, y[i])) + for i in range(n + 1): + y[i + 3] = y[i + 2] + (self.step_size / 12) * ( + 23 * self.func(x_2, y[i + 2]) + - 16 * self.func(x_1, y[i + 1]) + + 5 * self.func(x_0, y[i]) + ) x_0 = x_1 x_1 = x_2 x_2 = x_2 + self.step_size @@ -133,7 +148,12 @@ def step_4(self) -> np.ndarray: y[3] = y_3 for i in range(n): - y[i+4] = y[i+3] + (self.step_size/24) * (55 * self.func(x_3, y[i+3]) - 59 * self.func(x_2 , y[i+2]) + 37*self.func(x_1, y[i+1]) - 9*self.func(x_0, y[i])) + y[i + 4] = y[i + 3] + (self.step_size / 24) * ( + 55 * self.func(x_3, y[i + 3]) + - 59 * self.func(x_2, y[i + 2]) + + 37 * self.func(x_1, y[i + 1]) + - 9 * self.func(x_0, y[i]) + ) x_0 = x_1 x_1 = x_2 x_2 = x_3 @@ -156,8 +176,14 @@ def step_5(self) -> np.ndarray: y[3] = y_3 y[4] = y_4 - for i in range(n+1): - y[i+5] = y[i+4] + (self.step_size/720) * (1901 * self.func(x_4, y[i+4]) - 2774 * self.func(x_3, y[i+3]) - 2616 * self.func(x_2 , y[i+2]) - 1274 *self.func(x_1, y[i+1]) + 251*self.func(x_0, y[i])) + for i in range(n + 1): + y[i + 5] = y[i + 4] + (self.step_size / 720) * ( + 1901 * self.func(x_4, y[i + 4]) + - 2774 * self.func(x_3, y[i + 3]) + - 2616 * self.func(x_2, y[i + 2]) + - 1274 * self.func(x_1, y[i + 1]) + + 251 * self.func(x_0, y[i]) + ) x_0 = x_1 x_1 = x_2 x_2 = x_3 @@ -166,7 +192,8 @@ def step_5(self) -> np.ndarray: return y + if __name__ == "__main__": import doctest - doctest.testmod() \ No newline at end of file + doctest.testmod() From dc07518f813d0043017d441163126395eef4d23c Mon Sep 17 00:00:00 2001 From: Ravi Kumar <119737193+ravi-ivar-7@users.noreply.github.com> Date: Thu, 26 Oct 2023 02:10:11 +0530 Subject: [PATCH 4/9] Update adams_bashforth.py --- maths/numerical_analysis/adams_bashforth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py index 6475e5983d14..811a7d277739 100644 --- a/maths/numerical_analysis/adams_bashforth.py +++ b/maths/numerical_analysis/adams_bashforth.py @@ -74,7 +74,7 @@ def __init__( >>> def f(x, y): ... return x - >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6, 0.8], [0, 0, 0.04, 0.128, 0.307], -0.2, 1).step_5() + >>> y = AdamsBashforth(f,[0,0.2,0.4,0.6,0.8],[0,0,0.04,0.128 0.307],-0.2,1).step_5() Traceback (most recent call last): ... ValueError: Step size must be positive. From 45cb8ecf7dca4d90d42794607d5a6fbf8ac41abf Mon Sep 17 00:00:00 2001 From: Ravi Kumar <119737193+ravi-ivar-7@users.noreply.github.com> Date: Thu, 26 Oct 2023 14:50:36 +0530 Subject: [PATCH 5/9] Deleted extraneous file, maths/numerical_analysis/runge_kutta_gills.py --- maths/numerical_analysis/runge_kutta_gills.py | 90 ------------------- 1 file changed, 90 deletions(-) delete mode 100644 maths/numerical_analysis/runge_kutta_gills.py diff --git a/maths/numerical_analysis/runge_kutta_gills.py b/maths/numerical_analysis/runge_kutta_gills.py deleted file mode 100644 index 0f4e585a1f72..000000000000 --- a/maths/numerical_analysis/runge_kutta_gills.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -Use the Runge-Kutta-Gill's method of order 4 to solve Ordinary Differential Equations. - - -https://www.geeksforgeeks.org/gills-4th-order-method-to-solve-differential-equations/ -Author : Ravi Kumar -""" -from collections.abc import Callable -from math import sqrt - -import numpy as np - - -def runge_kutta_gills( - func: Callable[[float, float], float], - x_initial: float, - y_initial: float, - step_size: float, - x_final: float, -) -> np.ndarray: - """ - Solve an Ordinary Differential Equations using Runge-Kutta-Gills Method of order 4. - - args: - func: An ordinary differential equation (ODE) as function of x and y. - x_initial: The initial value of x. - y_initial: The initial value of y. - step_size: The increment value of x. - x_final: The final value of x. - - Returns: - Solution of y at each nodal point - - >>> def f(x, y): - ... return (x-y)/2 - >>> y = runge_kutta_gills(f, 0, 3, 0.2, 5) - >>> y[-1] - 3.4104259225717537 - - >>> def f(x,y): - ... return x - >>> y = runge_kutta_gills(f, -1, 0, 0.2, 0) - >>> y - array([ 0. , -0.18, -0.32, -0.42, -0.48, -0.5 ]) - - >>> def f(x, y): - ... return x + y - >>> y = runge_kutta_gills(f, 0, 0, 0.2, -1) - Traceback (most recent call last): - ... - ValueError: The final value of x must be greater than initial value of x. - - >>> def f(x, y): - ... return x - >>> y = runge_kutta_gills(f, -1, 0, -0.2, 0) - Traceback (most recent call last): - ... - ValueError: Step size must be positive. - """ - if x_initial >= x_final: - raise ValueError( - "The final value of x must be greater than initial value of x." - ) - - if step_size <= 0: - raise ValueError("Step size must be positive.") - - n = int((x_final - x_initial) / step_size) - y = np.zeros(n + 1) - y[0] = y_initial - for i in range(n): - k1 = step_size * func(x_initial, y[i]) - k2 = step_size * func(x_initial + step_size / 2, y[i] + k1 / 2) - k3 = step_size * func( - x_initial + step_size / 2, - y[i] + (-0.5 + 1 / sqrt(2)) * k1 + (1 - 1 / sqrt(2)) * k2, - ) - k4 = step_size * func( - x_initial + step_size, y[i] - (1 / sqrt(2)) * k2 + (1 + 1 / sqrt(2)) * k3 - ) - - y[i + 1] = y[i] + (k1 + (2 - sqrt(2)) * k2 + (2 + sqrt(2)) * k3 + k4) / 6 - x_initial = step_size + x_initial - return y - - -if __name__ == "__main__": - import doctest - - doctest.testmod() From a7283bc02dbfd8b8231737cac48a24f0b6c9c6b4 Mon Sep 17 00:00:00 2001 From: Ravi Kumar <119737193+ravi-ivar-7@users.noreply.github.com> Date: Sat, 28 Oct 2023 13:04:06 +0530 Subject: [PATCH 6/9] Added doctests to each function adams_bashforth.py --- maths/numerical_analysis/adams_bashforth.py | 122 ++++++++++++++------ 1 file changed, 84 insertions(+), 38 deletions(-) diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py index 811a7d277739..86105e9f6a0d 100644 --- a/maths/numerical_analysis/adams_bashforth.py +++ b/maths/numerical_analysis/adams_bashforth.py @@ -18,7 +18,14 @@ def __init__( y_initials: list[float], step_size: float, x_final: float, - ): + ) -> None: + + self.func = func + self.x_initials = x_initials + self.y_initials = y_initials + self.step_size = step_size + self.x_final = x_final + if x_initials[-1] >= x_final: raise ValueError( "The final value of x must be greater than the initial values of x." @@ -27,15 +34,9 @@ def __init__( if step_size <= 0: raise ValueError("Step size must be positive.") - if not all(x1 - x0 == step_size for x0, x1 in zip(x_initials, x_initials[1:])): + if not all(round(x1 - x0,10) == step_size for x0, x1 in zip(x_initials, x_initials[1:])): raise ValueError("x-values must be equally spaced according to step size.") - self.func = func - self.x_initials = x_initials - self.y_initials = y_initials - self.step_size = step_size - self.x_final = x_final - """ args: func: An ordinary differential equation (ODE) as function of x and y. @@ -46,50 +47,46 @@ def __init__( Returns: Solution of y at each nodal point - >>> def f(x, y): - ... return x - >>> y = AdamsBashforth(f, [0, 0.2], [0, 0], 0.2, 1).step_2() - >>> y - array([0. 0. 0.06 0.178 0.3654 0.63722]) - - >>> def f(x,y): - ... return x + y - >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6], [0, 0, 0.04, 0.128], 0.2, 1).step_4() - >>> y[-1] - 0.57710833 - >>> def f(x, y): ... return x + y - >>> y = AdamsBashforth(f, [0, 0.2, 1], [0, 0, 0.04], 0.2, 1).step_3() + >>> AdamsBashforth(f, [0, 0.2, 1], [0, 0, 0.04], 0.2, 1).step_2() Traceback (most recent call last): ... ValueError: The final value of x must be greater than the all initial values of x. >>> def f(x, y): ... return x + y - >>> y = AdamsBashforth(f, [0, 0.2, 0.3], [0, 0, 0.04], 0.2, 1).step_3() + >>> AdamsBashforth(f, [0, 0.2, 0.3], [0, 0, 0.04], 0.2, 1).step_3() Traceback (most recent call last): ... ValueError: x-values must be equally spaced according to step size. >>> def f(x, y): ... return x - >>> y = AdamsBashforth(f,[0,0.2,0.4,0.6,0.8],[0,0,0.04,0.128 0.307],-0.2,1).step_5() + >>> AdamsBashforth(f,[0,0.2,0.4,0.6,0.8],[0,0,0.04,0.128 0.307],-0.2,1).step_5() Traceback (most recent call last): ... ValueError: Step size must be positive. - - >>> def f(x, y): - ... return (x -y)/2 - >>> y = AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_2() - Traceback (most recent call last): - ... - ValueError: Insufficient nodal points values information. """ def step_2(self) -> np.ndarray: + + """ + >>> def f(x, y): + ... return x + >>> AdamsBashforth(f, [0, 0.2], [0, 0], 0.2, 1).step_2() + array([0. , 0. , 0.06, 0.16, 0.3 , 0.48]) + + >>> def f(x, y): + ... return (x -y)/2 + >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_2() + Traceback (most recent call last): + ... + ValueError: Insufficient initial points information. + """ + if len(self.x_initials) != 2 or len(self.y_initials) != 2: - raise ValueError("Insufficient nodal points values information.") + raise ValueError("Insufficient initial points information.") x_0, x_1 = self.x_initials[:2] y_0, y_1 = self.y_initials[:2] @@ -104,13 +101,28 @@ def step_2(self) -> np.ndarray: 3 * self.func(x_1, y[i + 1]) - self.func(x_0, y[i]) ) x_0 = x_1 - x_1 = x_1 + self.step_size + x_1 += self.step_size return y def step_3(self) -> np.ndarray: + + """ + >>> def f(x, y): + ... return x + y + >>> y = AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_3() + >>> y[3] + 0.15533333333333332 + + >>> def f(x, y): + ... return (x -y)/2 + >>> AdamsBashforth(f, [0, 0.2], [0, 0], 0.2, 1).step_3() + Traceback (most recent call last): + ... + ValueError: Insufficient initial points information. + """ if len(self.x_initials) != 3 or len(self.y_initials) != 3: - raise ValueError("Insufficient nodal points information.") + raise ValueError("Insufficient initial points information.") x_0, x_1, x_2 = self.x_initials[:3] y_0, y_1, y_2 = self.y_initials[:3] @@ -129,13 +141,31 @@ def step_3(self) -> np.ndarray: ) x_0 = x_1 x_1 = x_2 - x_2 = x_2 + self.step_size + x_2 += self.step_size return y def step_4(self) -> np.ndarray: + + """ + >>> def f(x,y): + ... return x + y + >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6], [0, 0, 0.04, 0.128], 0.2, 1).step_4() + >>> y[4] + 0.30699999999999994 + >>> y[5] + 0.5771083333333333 + + >>> def f(x, y): + ... return (x -y)/2 + >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_4() + Traceback (most recent call last): + ... + ValueError: Insufficient initial points information. + """ + if len(self.x_initials) != 4 or len(self.y_initials) != 4: - raise ValueError("Insufficient nodal points information.") + raise ValueError("Insufficient initial points information.") x_0, x_1, x_2, x_3 = self.x_initials[:4] y_0, y_1, y_2, y_3 = self.y_initials[:4] @@ -157,13 +187,29 @@ def step_4(self) -> np.ndarray: x_0 = x_1 x_1 = x_2 x_2 = x_3 - x_3 = x_3 + self.step_size + x_3 += self.step_size return y def step_5(self) -> np.ndarray: + + """ + >>> def f(x,y): + ... return x + y + >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6, 0.8], [0, 0.02140, 0.02140, 0.22211, 0.42536], 0.2, 1).step_5() + >>> y[-1] + 0.05436839444444452 + + >>> def f(x, y): + ... return (x -y)/2 + >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_5() + Traceback (most recent call last): + ... + ValueError: Insufficient initial points information. + """ + if len(self.x_initials) != 5 or len(self.y_initials) != 5: - raise ValueError("Insufficient nodal points information.") + raise ValueError("Insufficient initial points information.") x_0, x_1, x_2, x_3, x_4 = self.x_initials[:5] y_0, y_1, y_2, y_3, y_4 = self.y_initials[:5] @@ -188,7 +234,7 @@ def step_5(self) -> np.ndarray: x_1 = x_2 x_2 = x_3 x_3 = x_4 - x_4 = x_4 + self.step_size + x_4 += self.step_size return y From c5a24b28df62a0f84b912ddc3de2dc1a0a3cc4a0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 28 Oct 2023 07:35:16 +0000 Subject: [PATCH 7/9] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/numerical_analysis/adams_bashforth.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py index 86105e9f6a0d..5b43f93e059f 100644 --- a/maths/numerical_analysis/adams_bashforth.py +++ b/maths/numerical_analysis/adams_bashforth.py @@ -19,7 +19,6 @@ def __init__( step_size: float, x_final: float, ) -> None: - self.func = func self.x_initials = x_initials self.y_initials = y_initials @@ -34,7 +33,10 @@ def __init__( if step_size <= 0: raise ValueError("Step size must be positive.") - if not all(round(x1 - x0,10) == step_size for x0, x1 in zip(x_initials, x_initials[1:])): + if not all( + round(x1 - x0, 10) == step_size + for x0, x1 in zip(x_initials, x_initials[1:]) + ): raise ValueError("x-values must be equally spaced according to step size.") """ @@ -70,7 +72,6 @@ def __init__( """ def step_2(self) -> np.ndarray: - """ >>> def f(x, y): ... return x @@ -106,7 +107,6 @@ def step_2(self) -> np.ndarray: return y def step_3(self) -> np.ndarray: - """ >>> def f(x, y): ... return x + y @@ -146,7 +146,6 @@ def step_3(self) -> np.ndarray: return y def step_4(self) -> np.ndarray: - """ >>> def f(x,y): ... return x + y @@ -155,7 +154,7 @@ def step_4(self) -> np.ndarray: 0.30699999999999994 >>> y[5] 0.5771083333333333 - + >>> def f(x, y): ... return (x -y)/2 >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_4() @@ -192,7 +191,6 @@ def step_4(self) -> np.ndarray: return y def step_5(self) -> np.ndarray: - """ >>> def f(x,y): ... return x + y From 729df6cf68bce011dbc8a9497d7c7a3f645aa2c1 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sat, 28 Oct 2023 23:52:28 +0200 Subject: [PATCH 8/9] Update adams_bashforth.py --- maths/numerical_analysis/adams_bashforth.py | 62 ++++++++++----------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py index 5b43f93e059f..aba52b977f37 100644 --- a/maths/numerical_analysis/adams_bashforth.py +++ b/maths/numerical_analysis/adams_bashforth.py @@ -6,39 +6,13 @@ Author : Ravi Kumar """ from collections.abc import Callable +from dataclasses import dataclass import numpy as np +@dataclass class AdamsBashforth: - def __init__( - self, - func: Callable[[float, float], float], - x_initials: list[float], - y_initials: list[float], - step_size: float, - x_final: float, - ) -> None: - self.func = func - self.x_initials = x_initials - self.y_initials = y_initials - self.step_size = step_size - self.x_final = x_final - - if x_initials[-1] >= x_final: - raise ValueError( - "The final value of x must be greater than the initial values of x." - ) - - if step_size <= 0: - raise ValueError("Step size must be positive.") - - if not all( - round(x1 - x0, 10) == step_size - for x0, x1 in zip(x_initials, x_initials[1:]) - ): - raise ValueError("x-values must be equally spaced according to step size.") - """ args: func: An ordinary differential equation (ODE) as function of x and y. @@ -54,7 +28,7 @@ def __init__( >>> AdamsBashforth(f, [0, 0.2, 1], [0, 0, 0.04], 0.2, 1).step_2() Traceback (most recent call last): ... - ValueError: The final value of x must be greater than the all initial values of x. + ValueError: The final value of x must be greater than the initial values of x. >>> def f(x, y): ... return x + y @@ -65,12 +39,33 @@ def __init__( >>> def f(x, y): ... return x - >>> AdamsBashforth(f,[0,0.2,0.4,0.6,0.8],[0,0,0.04,0.128 0.307],-0.2,1).step_5() + >>> AdamsBashforth(f,[0,0.2,0.4,0.6,0.8],[0,0,0.04,0.128,0.307],-0.2,1).step_5() Traceback (most recent call last): ... ValueError: Step size must be positive. """ + func: Callable[[float, float], float] + x_initials: list[float] + y_initials: list[float] + step_size: float + x_final: float + + def __post_init__(self) -> None: + if self.x_initials[-1] >= self.x_final: + raise ValueError( + "The final value of x must be greater than the initial values of x." + ) + + if self.step_size <= 0: + raise ValueError("Step size must be positive.") + + if not all( + round(x1 - x0, 10) == self.step_size + for x0, x1 in zip(self.x_initials, self.x_initials[1:]) + ): + raise ValueError("x-values must be equally spaced according to step size.") + def step_2(self) -> np.ndarray: """ >>> def f(x, y): @@ -149,7 +144,8 @@ def step_4(self) -> np.ndarray: """ >>> def f(x,y): ... return x + y - >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6], [0, 0, 0.04, 0.128], 0.2, 1).step_4() + >>> y = AdamsBashforth( + ... f, [0, 0.2, 0.4, 0.6], [0, 0, 0.04, 0.128], 0.2, 1).step_4() >>> y[4] 0.30699999999999994 >>> y[5] @@ -194,7 +190,9 @@ def step_5(self) -> np.ndarray: """ >>> def f(x,y): ... return x + y - >>> y = AdamsBashforth(f, [0, 0.2, 0.4, 0.6, 0.8], [0, 0.02140, 0.02140, 0.22211, 0.42536], 0.2, 1).step_5() + >>> y = AdamsBashforth( + ... f, [0, 0.2, 0.4, 0.6, 0.8], [0, 0.02140, 0.02140, 0.22211, 0.42536], + ... 0.2, 1).step_5() >>> y[-1] 0.05436839444444452 From 0703b9ca40c0254f289f59cca269473b062f03e3 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Sun, 29 Oct 2023 00:03:05 +0200 Subject: [PATCH 9/9] Update adams_bashforth.py --- maths/numerical_analysis/adams_bashforth.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/maths/numerical_analysis/adams_bashforth.py b/maths/numerical_analysis/adams_bashforth.py index aba52b977f37..d61f022a413d 100644 --- a/maths/numerical_analysis/adams_bashforth.py +++ b/maths/numerical_analysis/adams_bashforth.py @@ -1,7 +1,6 @@ """ Use the Adams-Bashforth methods to solve Ordinary Differential Equations. - https://en.wikipedia.org/wiki/Linear_multistep_method Author : Ravi Kumar """ @@ -25,20 +24,18 @@ class AdamsBashforth: >>> def f(x, y): ... return x + y + >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0.2, 1], 0.2, 1) # doctest: +ELLIPSIS + AdamsBashforth(func=..., x_initials=[0, 0.2, 0.4], y_initials=[0, 0.2, 1], step...) >>> AdamsBashforth(f, [0, 0.2, 1], [0, 0, 0.04], 0.2, 1).step_2() Traceback (most recent call last): ... ValueError: The final value of x must be greater than the initial values of x. - >>> def f(x, y): - ... return x + y >>> AdamsBashforth(f, [0, 0.2, 0.3], [0, 0, 0.04], 0.2, 1).step_3() Traceback (most recent call last): ... ValueError: x-values must be equally spaced according to step size. - >>> def f(x, y): - ... return x >>> AdamsBashforth(f,[0,0.2,0.4,0.6,0.8],[0,0,0.04,0.128,0.307],-0.2,1).step_5() Traceback (most recent call last): ... @@ -73,8 +70,6 @@ def step_2(self) -> np.ndarray: >>> AdamsBashforth(f, [0, 0.2], [0, 0], 0.2, 1).step_2() array([0. , 0. , 0.06, 0.16, 0.3 , 0.48]) - >>> def f(x, y): - ... return (x -y)/2 >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_2() Traceback (most recent call last): ... @@ -109,8 +104,6 @@ def step_3(self) -> np.ndarray: >>> y[3] 0.15533333333333332 - >>> def f(x, y): - ... return (x -y)/2 >>> AdamsBashforth(f, [0, 0.2], [0, 0], 0.2, 1).step_3() Traceback (most recent call last): ... @@ -151,8 +144,6 @@ def step_4(self) -> np.ndarray: >>> y[5] 0.5771083333333333 - >>> def f(x, y): - ... return (x -y)/2 >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_4() Traceback (most recent call last): ... @@ -196,8 +187,6 @@ def step_5(self) -> np.ndarray: >>> y[-1] 0.05436839444444452 - >>> def f(x, y): - ... return (x -y)/2 >>> AdamsBashforth(f, [0, 0.2, 0.4], [0, 0, 0.04], 0.2, 1).step_5() Traceback (most recent call last): ...