numerical-method-lab 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- numerical_method_lab/__inti__.py +1 -0
- numerical_method_lab/integration.py +59 -0
- numerical_method_lab/linear_algebra.py +100 -0
- numerical_method_lab/root_finding.py +170 -0
- numerical_method_lab/visualization.py +0 -0
- numerical_method_lab-0.1.0.dist-info/METADATA +35 -0
- numerical_method_lab-0.1.0.dist-info/RECORD +10 -0
- numerical_method_lab-0.1.0.dist-info/WHEEL +5 -0
- numerical_method_lab-0.1.0.dist-info/licenses/LICENSE +21 -0
- numerical_method_lab-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# src/__init__.py
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
def trapezoidal(f,a,b,n=10000):
|
|
3
|
+
"""
|
|
4
|
+
This function implements the trapezoidal rule for numerical integration.
|
|
5
|
+
:param f: The function to integrate
|
|
6
|
+
:param a: The lower limit of integration
|
|
7
|
+
:param b: The upper limit of integration
|
|
8
|
+
:param n: The number of trapezoids (default is 10000)
|
|
9
|
+
:return: The approximate value of the integral
|
|
10
|
+
"""
|
|
11
|
+
x = np.linspace(a, b, n+1) # x values for the trapezoids
|
|
12
|
+
dx = x[1]-x[0] # width of each trapezoid
|
|
13
|
+
total = np.sum(f(x[:-1])*dx) + np.sum(f(x[1:])*dx) # sum of areas of trapezoids
|
|
14
|
+
return total/2 # return the average of the two sums
|
|
15
|
+
|
|
16
|
+
def rectanglel(f,a,b,n=10000):
|
|
17
|
+
"""
|
|
18
|
+
This function implements the left rectangle rule for numerical integration.
|
|
19
|
+
:param f: The function to integrate
|
|
20
|
+
:param a: The lower limit of integration
|
|
21
|
+
:param b: The upper limit of integration
|
|
22
|
+
:param n: The number of rectangles (default is 10000)
|
|
23
|
+
:return: The approximate value of the integral
|
|
24
|
+
"""
|
|
25
|
+
x = np.linspace(a, b, n+1) # x values for the rectangles
|
|
26
|
+
dx = x[1]-x[0] # width of each rectangle
|
|
27
|
+
total = np.sum(f(x[:-1])*dx) # sum of areas of rectangles
|
|
28
|
+
return total # return the total area
|
|
29
|
+
|
|
30
|
+
def rectangler(f,a,b,n=10000):
|
|
31
|
+
"""
|
|
32
|
+
This function implements the right rectangle rule for numerical integration.
|
|
33
|
+
:param f: The function to integrate
|
|
34
|
+
:param a: The lower limit of integration
|
|
35
|
+
:param b: The upper limit of integration
|
|
36
|
+
:param n: The number of rectangles (default is 10000)
|
|
37
|
+
:return: The approximate value of the integral
|
|
38
|
+
"""
|
|
39
|
+
x = np.linspace(a, b, n+1) # x values for the rectangles
|
|
40
|
+
dx = x[1]-x[0] # width of each rectangle
|
|
41
|
+
total = np.sum(f(x[1:])*dx) # sum of areas of rectangles
|
|
42
|
+
return total # return the total area
|
|
43
|
+
|
|
44
|
+
def simpson(f,a,b,n=10000):
|
|
45
|
+
"""
|
|
46
|
+
This function implements Simpson's rule for numerical integration.
|
|
47
|
+
:param f: The function to integrate
|
|
48
|
+
:param a: The lower limit of integration
|
|
49
|
+
:param b: The upper limit of integration
|
|
50
|
+
:param n: The number of intervals (default is 10000, must be even)
|
|
51
|
+
:return: The approximate value of the integral
|
|
52
|
+
"""
|
|
53
|
+
if n % 2 == 1:
|
|
54
|
+
n += 1 # make n even if it is odd
|
|
55
|
+
x = np.linspace(a, b, n+1) # x values for the intervals
|
|
56
|
+
dx = x[1]-x[0] # width of each interval
|
|
57
|
+
total = f(x[0]) + f(x[-1]) + 4*np.sum(f(x[1:-1:2])) + 2*np.sum(f(x[2:-1:2])) # Simpson's rule formula
|
|
58
|
+
return total * dx / 3 # return the approximate integral value
|
|
59
|
+
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def back_substitution(A, b):
|
|
5
|
+
"""
|
|
6
|
+
Solve an upper-triangular system Ax = b
|
|
7
|
+
using back substitution.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
n = len(b)
|
|
11
|
+
|
|
12
|
+
# Create an array to store the solution
|
|
13
|
+
x = np.zeros(n)
|
|
14
|
+
|
|
15
|
+
# Start from the last equation
|
|
16
|
+
for i in range(n - 1, -1, -1):
|
|
17
|
+
|
|
18
|
+
# Start with the right-hand side
|
|
19
|
+
total = b[i]
|
|
20
|
+
|
|
21
|
+
# Subtract the terms we already know
|
|
22
|
+
for j in range(i + 1, n):
|
|
23
|
+
total -= A[i, j] * x[j]
|
|
24
|
+
|
|
25
|
+
# Check for zero diagonal element
|
|
26
|
+
if abs(A[i, i]) < 1e-12:
|
|
27
|
+
raise ValueError("Zero pivot encountered during back substitution.")
|
|
28
|
+
|
|
29
|
+
# Solve for x[i]
|
|
30
|
+
x[i] = total / A[i, i]
|
|
31
|
+
|
|
32
|
+
return x
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def gaussian_elimination(A, b):
|
|
36
|
+
"""
|
|
37
|
+
Solve Ax = b using Gaussian elimination
|
|
38
|
+
with partial pivoting and back substitution.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# Convert inputs to NumPy arrays
|
|
42
|
+
A = np.array(A, dtype=float)
|
|
43
|
+
b = np.array(b, dtype=float)
|
|
44
|
+
|
|
45
|
+
# Make sure A is a square matrix
|
|
46
|
+
if A.ndim != 2 or A.shape[0] != A.shape[1]:
|
|
47
|
+
raise ValueError("A must be a square matrix.")
|
|
48
|
+
|
|
49
|
+
# Make sure b has the correct size
|
|
50
|
+
if len(b) != A.shape[0]:
|
|
51
|
+
raise ValueError("The dimensions of A and b do not match.")
|
|
52
|
+
|
|
53
|
+
n = len(b)
|
|
54
|
+
|
|
55
|
+
# -----------------------------------------
|
|
56
|
+
# Gaussian Elimination
|
|
57
|
+
# -----------------------------------------
|
|
58
|
+
|
|
59
|
+
for i in range(n):
|
|
60
|
+
|
|
61
|
+
# -------------------------------------
|
|
62
|
+
# PARTIAL PIVOTING
|
|
63
|
+
# -------------------------------------
|
|
64
|
+
|
|
65
|
+
# Look at the current column from row i downward
|
|
66
|
+
pivot_row = i + np.argmax(np.abs(A[i:, i]))
|
|
67
|
+
|
|
68
|
+
# Check whether the largest value is effectively zero
|
|
69
|
+
if abs(A[pivot_row, i]) < 1e-12:
|
|
70
|
+
raise ValueError("Matrix is singular or nearly singular.")
|
|
71
|
+
|
|
72
|
+
# Swap the current row with the pivot row
|
|
73
|
+
if pivot_row != i:
|
|
74
|
+
A[[i, pivot_row]] = A[[pivot_row, i]]
|
|
75
|
+
b[[i, pivot_row]] = b[[pivot_row, i]]
|
|
76
|
+
|
|
77
|
+
# -------------------------------------
|
|
78
|
+
# ELIMINATION
|
|
79
|
+
# -------------------------------------
|
|
80
|
+
|
|
81
|
+
# Eliminate values below the pivot
|
|
82
|
+
for j in range(i + 1, n):
|
|
83
|
+
|
|
84
|
+
# Calculate elimination factor
|
|
85
|
+
factor = A[j, i] / A[i, i]
|
|
86
|
+
|
|
87
|
+
# Eliminate the value
|
|
88
|
+
for k in range(i, n):
|
|
89
|
+
A[j, k] -= factor * A[i, k]
|
|
90
|
+
|
|
91
|
+
# Apply the same operation to b
|
|
92
|
+
b[j] -= factor * b[i]
|
|
93
|
+
|
|
94
|
+
# -----------------------------------------
|
|
95
|
+
# BACK SUBSTITUTION
|
|
96
|
+
# -----------------------------------------
|
|
97
|
+
|
|
98
|
+
solution = back_substitution(A, b)
|
|
99
|
+
|
|
100
|
+
return solution
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def bisection_method(f, a, b, tol=1e-5, max_iter=100):
|
|
5
|
+
"""
|
|
6
|
+
Bisection method for finding roots of a function.
|
|
7
|
+
|
|
8
|
+
Parameters:
|
|
9
|
+
f : function
|
|
10
|
+
The function for which we are trying to find a root.
|
|
11
|
+
a : float
|
|
12
|
+
The start of the interval.
|
|
13
|
+
b : float
|
|
14
|
+
The end of the interval.
|
|
15
|
+
tol : float
|
|
16
|
+
The tolerance for stopping the algorithm.
|
|
17
|
+
max_iter : int
|
|
18
|
+
The maximum number of iterations.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
float
|
|
22
|
+
The approximate root of the function.
|
|
23
|
+
"""
|
|
24
|
+
fa = f(a)
|
|
25
|
+
fb = f(b)
|
|
26
|
+
|
|
27
|
+
if fa * fb >= 0:
|
|
28
|
+
raise ValueError(
|
|
29
|
+
"The function must have different signs at the endpoints."
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
for i in range(max_iter):
|
|
33
|
+
|
|
34
|
+
c = (a + b) / 2
|
|
35
|
+
fc = f(c)
|
|
36
|
+
|
|
37
|
+
if abs(fc) < tol or (b - a) / 2 < tol:
|
|
38
|
+
return c
|
|
39
|
+
|
|
40
|
+
if fa * fc < 0:
|
|
41
|
+
b = c
|
|
42
|
+
fb = fc
|
|
43
|
+
else:
|
|
44
|
+
a = c
|
|
45
|
+
fa = fc
|
|
46
|
+
|
|
47
|
+
return (a + b) / 2
|
|
48
|
+
|
|
49
|
+
def derivative(f, x, h=1e-5):
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
Numerical derivative of a function using central difference.
|
|
54
|
+
|
|
55
|
+
Parameters:
|
|
56
|
+
|
|
57
|
+
f : function
|
|
58
|
+
|
|
59
|
+
The function for which we are calculating the derivative.
|
|
60
|
+
|
|
61
|
+
x : float
|
|
62
|
+
|
|
63
|
+
The point at which to evaluate the derivative.
|
|
64
|
+
|
|
65
|
+
h : float
|
|
66
|
+
|
|
67
|
+
The step size for the finite difference.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
|
|
71
|
+
float
|
|
72
|
+
|
|
73
|
+
The approximate derivative of the function at point x.
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
return (f(x + h) - f(x - h)) / (2 * h)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def Newton_raphson_method(f, x0, df=derivative, tol=1e-5, max_iter=100):
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
Newton-Raphson Method
|
|
85
|
+
|
|
86
|
+
=====================
|
|
87
|
+
|
|
88
|
+
What it is:
|
|
89
|
+
|
|
90
|
+
The Newton-Raphson method is an iterative numerical technique used to find
|
|
91
|
+
|
|
92
|
+
roots of a real-valued function f(x) = 0.
|
|
93
|
+
|
|
94
|
+
If x_n is the current estimate, then the next estimate is:
|
|
95
|
+
|
|
96
|
+
x_{n+1} = x_n - f(x_n) / f'(x_n)
|
|
97
|
+
|
|
98
|
+
where f'(x) is the derivative of f(x).
|
|
99
|
+
|
|
100
|
+
How it works:
|
|
101
|
+
|
|
102
|
+
- Start with an initial guess x0.
|
|
103
|
+
|
|
104
|
+
- Compute the tangent line to the curve at x0.
|
|
105
|
+
|
|
106
|
+
- Find where that tangent line crosses the x-axis.
|
|
107
|
+
|
|
108
|
+
- Repeat until the change is very small or the function value is close to zero.
|
|
109
|
+
|
|
110
|
+
Why use it:
|
|
111
|
+
|
|
112
|
+
- Very fast when the initial guess is close to the actual root.
|
|
113
|
+
|
|
114
|
+
- It usually converges quadratically near simple roots.
|
|
115
|
+
|
|
116
|
+
- Works well for smooth functions with known derivatives.
|
|
117
|
+
|
|
118
|
+
Using NumPy:
|
|
119
|
+
|
|
120
|
+
NumPy helps with array operations, mathematical calculations, and plotting
|
|
121
|
+
|
|
122
|
+
when needed. This example uses only standard NumPy math functions.
|
|
123
|
+
|
|
124
|
+
Parameters:
|
|
125
|
+
|
|
126
|
+
f : function
|
|
127
|
+
|
|
128
|
+
The function for which we are trying to find a root.
|
|
129
|
+
|
|
130
|
+
x0 : float
|
|
131
|
+
|
|
132
|
+
The initial guess for the root.
|
|
133
|
+
|
|
134
|
+
df : function, optional
|
|
135
|
+
|
|
136
|
+
The derivative of the function f. If not provided, it will be calculated numerically.
|
|
137
|
+
|
|
138
|
+
tol : float, optional
|
|
139
|
+
|
|
140
|
+
The tolerance for stopping the algorithm.
|
|
141
|
+
|
|
142
|
+
max_iter : int, optional
|
|
143
|
+
|
|
144
|
+
The maximum number of iterations.
|
|
145
|
+
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
x_n = x0
|
|
149
|
+
|
|
150
|
+
for i in range(max_iter):
|
|
151
|
+
|
|
152
|
+
f_xn = f(x_n)
|
|
153
|
+
|
|
154
|
+
df_xn = df(f, x_n)
|
|
155
|
+
|
|
156
|
+
if abs(df_xn) < 1e-12:
|
|
157
|
+
|
|
158
|
+
raise ValueError("Derivative is too small; no convergence.")
|
|
159
|
+
|
|
160
|
+
x_n1 = x_n - f_xn / df_xn
|
|
161
|
+
|
|
162
|
+
if abs(x_n1 - x_n) < tol:
|
|
163
|
+
return x_n1
|
|
164
|
+
|
|
165
|
+
if abs(f(x_n1)) < tol:
|
|
166
|
+
return x_n1
|
|
167
|
+
|
|
168
|
+
x_n = x_n1
|
|
169
|
+
|
|
170
|
+
raise ValueError("Maximum iterations reached without convergence.")
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: numerical-method-lab
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A collection of numerical methods for root finding, integration, and linear algebra
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 Abhishek thakur
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
|
|
27
|
+
Requires-Python: >=3.8
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: numpy
|
|
31
|
+
Requires-Dist: matplotlib
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# Numerical_Method_Lab
|
|
35
|
+
A from-scratch numerical analysis laboratory implementing classical numerical methods for root finding, numerical integration, and linear algebra, with automated tests, visualization, and experimental notebooks to study accuracy, convergence, and numerical stability.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
numerical_method_lab/__inti__.py,sha256=GAtuudnJ7YjHG-XK35xFEuWgo7mJTw_qFo86c_gXRmE,17
|
|
2
|
+
numerical_method_lab/integration.py,sha256=pVW-Cr5N6fFGHx9sA0c4tj3tanySF539OrkgAvboJe8,2503
|
|
3
|
+
numerical_method_lab/linear_algebra.py,sha256=IYxHRWffLmlkxEtGkq2MDvrs2WKhdOSydXVJUmZFan0,2627
|
|
4
|
+
numerical_method_lab/root_finding.py,sha256=YhhFJVeo0j_K5_yY2nzRB1jB3vXDcnM_v7MaHhm72tU,3442
|
|
5
|
+
numerical_method_lab/visualization.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
numerical_method_lab-0.1.0.dist-info/licenses/LICENSE,sha256=BTBqf01TJ7ZLWhuaWgiYEKXNmxigkWwpkXAdcXM98b8,1072
|
|
7
|
+
numerical_method_lab-0.1.0.dist-info/METADATA,sha256=27S9H6VVCuPhCh-1Pfdj_os2MbNC8ZQbOxC263HX4eI,1853
|
|
8
|
+
numerical_method_lab-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
9
|
+
numerical_method_lab-0.1.0.dist-info/top_level.txt,sha256=XdQ4cWNraOuwHcIT_tGpELd2pwYnAg9OuEI0qAjYPBQ,21
|
|
10
|
+
numerical_method_lab-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Abhishek thakur
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
numerical_method_lab
|