11"""
2- Numerical methods for solving Ordinary Differential Equations (ODEs) of the form y' = f(x, y).
2+ Numerical methods for solving Ordinary Differential Equations (ODEs)
3+ of the form y' = f(x, y).
34This module implements the Euler method and Heun's method.
45
56References:
67- Euler Method: https://en.wikipedia.org/wiki/Euler_method
78- Heun's Method: https://en.wikipedia.org/wiki/Heun%27s_method
8-
99"""
1010
11- from typing import Callable , List , Tuple
11+ from collections . abc import Callable
1212
1313
1414def euler_method (
15- f : Callable [[float , float ], float ], x0 : float , y0 : float , h : float , steps : int
16- ) -> Tuple [List [float ], List [float ]]:
15+ differential_function : Callable [[float , float ], float ],
16+ x_initial : float ,
17+ y_initial : float ,
18+ step_size : float ,
19+ total_steps : int ,
20+ ) -> tuple [list [float ], list [float ]]:
1721 """
1822 Approximates the solution of a first-order ODE y' = f(x, y) using Euler's method.
1923
20- :param f : The differential equation function f(x, y).
21- :param x0 : Initial value of x.
22- :param y0 : Initial value of y (y(x0 ) = y0 ).
23- :param h : Step size.
24- :param steps : Number of iterations to perform.
24+ :param differential_function : The differential equation function f(x, y).
25+ :param x_initial : Initial value of x.
26+ :param y_initial : Initial value of y (y(x_initial ) = y_initial ).
27+ :param step_size : Step size.
28+ :param total_steps : Number of iterations to perform.
2529 :return: A tuple containing lists of x and y coordinates.
2630
2731 >>> def f_ode(x: float, y: float) -> float: return y - x**2 + 1
@@ -31,56 +35,69 @@ def euler_method(
3135 >>> [round(i, 4) for i in y_vals]
3236 [0.5, 0.875, 1.3281]
3337 """
34- x = [0.0 ] * (steps + 1 )
35- y = [0.0 ] * (steps + 1 )
36- x [0 ], y [0 ] = x0 , y0
38+ x_estimates = [0.0 ] * (total_steps + 1 )
39+ y_estimates = [0.0 ] * (total_steps + 1 )
40+ x_estimates [0 ], y_estimates [0 ] = x_initial , y_initial
3741
38- for i in range (steps ):
39- y [i + 1 ] = y [i ] + f (x [i ], y [i ]) * h
40- x [i + 1 ] = x [i ] + h
42+ for i in range (total_steps ):
43+ y_estimates [i + 1 ] = (
44+ y_estimates [i ]
45+ + differential_function (x_estimates [i ], y_estimates [i ]) * step_size
46+ )
47+ x_estimates [i + 1 ] = x_estimates [i ] + step_size
4148
42- return x , y
49+ return x_estimates , y_estimates
4350
4451
4552def heuns_method (
46- f : Callable [[float , float ], float ], x0 : float , y0 : float , h : float , steps : int
47- ) -> Tuple [List [float ], List [float ]]:
53+ differential_function : Callable [[float , float ], float ],
54+ x_initial : float ,
55+ y_initial : float ,
56+ step_size : float ,
57+ total_steps : int ,
58+ ) -> tuple [list [float ], list [float ]]:
4859 """
49- Approximates the solution of a firs -order ODE y' = f(x, y) using Heun's method
60+ Approximates the solution of a first -order ODE y' = f(x, y) using Heun's method
5061 (also known as the improved Euler method).
5162
52- :param f : The differential equation function f(x, y).
53- :param x0 : Initial value of x.
54- :param y0 : Initial value of y.
55- :param h : Step size.
56- :param steps : Number of iterations to perform.
63+ :param differential_function : The differential equation function f(x, y).
64+ :param x_initial : Initial value of x.
65+ :param y_initial : Initial value of y.
66+ :param step_size : Step size.
67+ :param total_steps : Number of iterations to perform.
5768 :return: A tuple containing lists of x and y coordinates.
5869
5970 >>> def f_ode(x: float, y: float) -> float: return y - x**2 + 1
6071 >>> x_vals, y_vals = heuns_method(f_ode, 0.0, 0.5, 0.25, 2)
6172 >>> [round(i, 4) for i in y_vals]
6273 [0.5, 0.9141, 1.4114]
6374 """
64- x = [0.0 ] * (steps + 1 )
65- y = [0.0 ] * (steps + 1 )
66- x [0 ], y [0 ] = x0 , y0
67-
68- for i in range (steps ):
69- y_predictor = y [i ] + f (x [i ], y [i ]) * h
70- x [i + 1 ] = x [i ] + h
71- y [i + 1 ] = y [i ] + ((f (x [i ], y [i ]) + f (x [i + 1 ], y_predictor )) / 2.0 ) * h
72-
73- return x , y
75+ x_estimates = [0.0 ] * (total_steps + 1 )
76+ y_estimates = [0.0 ] * (total_steps + 1 )
77+ x_estimates [0 ], y_estimates [0 ] = x_initial , y_initial
78+
79+ for i in range (total_steps ):
80+ y_predictor = (
81+ y_estimates [i ]
82+ + differential_function (x_estimates [i ], y_estimates [i ]) * step_size
83+ )
84+ x_estimates [i + 1 ] = x_estimates [i ] + step_size
85+ y_estimates [i + 1 ] = (
86+ y_estimates [i ]
87+ + (
88+ (
89+ differential_function (x_estimates [i ], y_estimates [i ])
90+ + differential_function (x_estimates [i + 1 ], y_predictor )
91+ )
92+ / 2.0
93+ )
94+ * step_size
95+ )
96+
97+ return x_estimates , y_estimates
7498
7599
76100if __name__ == "__main__" :
77101 import doctest
78102
79- doctest .testmod ()
80-
81- # example
82- def example_ode (x : float , y : float ) -> float :
83- return y - x ** 2 + 1
84-
85- x_res , y_res = heuns_method (example_ode , 0.0 , 0.5 , 0.25 , 4 )
86- print (f"Final heuns methot y value at x={ x_res [- 1 ]} : { round (y_res [- 1 ], 4 )} " )
103+ doctest .testmod ()
0 commit comments