numericalanalysisiiser 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.
@@ -0,0 +1,38 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+
5
+ def composite_simpson(f, a, b, n):
6
+ """Composite Simpson 1/3 rule with n (even) sub-intervals (a single number)."""
7
+ if n % 2 != 0:
8
+ raise ValueError("n must be even")
9
+ h = (b - a) / n
10
+ total = f(a) + f(b)
11
+ for k in range(1, n):
12
+ if k % 2 == 0:
13
+ total += 2 * f(a + k * h)
14
+ else:
15
+ total += 4 * f(a + k * h)
16
+ return (h / 3) * total
17
+
18
+
19
+ def simpson(f, a, b, n=2, exact=None):
20
+ """Simpson's 1/3 rule for the integral of f over [a, b].
21
+
22
+ n : number of sub-intervals (even), or a list of them (n = 2 is the basic rule)
23
+ exact : optional true value, adds error and order
24
+
25
+ Returns a DataFrame: n, h, value [, error, order]
26
+ """
27
+ n = np.atleast_1d(n)
28
+ h = (b - a) / n
29
+ table = pd.DataFrame({"n": n, "h": h, "value": [composite_simpson(f, a, b, int(k)) for k in n]})
30
+
31
+ if exact is not None:
32
+ error = np.abs(table["value"].to_numpy() - exact)
33
+ with np.errstate(divide="ignore", invalid="ignore"):
34
+ order = np.log(error[:-1] / error[1:]) / np.log(h[:-1] / h[1:])
35
+ table["error"] = error
36
+ table["order"] = np.append(order, np.nan)
37
+
38
+ return table
@@ -0,0 +1,42 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+
5
+ def sor(A, b, omega, x0=None, tol=1e-6, max_iter=1000):
6
+ """Successive over-relaxation for A x = b; stops when max|x_k - x_(k-1)| < tol.
7
+
8
+ omega : relaxation parameter (omega = 1 is Gauss-Seidel)
9
+ x0 : starting vector (zeros by default)
10
+
11
+ Returns a DataFrame, one row per iteration (k = 0 is the starting vector):
12
+ k, omega, step, residual, q, x1, x2, ...
13
+ step = max|x_k - x_(k-1)|, residual = max|b - A x_k|, q = residual_k / residual_(k-1).
14
+ The solution is the last row of x1, x2, ...
15
+ """
16
+ A = np.array(A, dtype=float)
17
+ b = np.array(b, dtype=float)
18
+ n = len(b)
19
+ x = np.zeros(n) if x0 is None else np.array(x0, dtype=float)
20
+
21
+ xs = [x]
22
+ step = [np.nan]
23
+ residual = [np.max(np.abs(b - A @ x))]
24
+
25
+ for k in range(1, max_iter + 1):
26
+ x_new = x.copy()
27
+ for i in range(n):
28
+ sum1 = np.dot(A[i, :i], x_new[:i])
29
+ sum2 = np.dot(A[i, i + 1:], x[i + 1:])
30
+ x_gs = (b[i] - sum1 - sum2) / A[i, i]
31
+ x_new[i] = (1 - omega) * x[i] + omega * x_gs
32
+
33
+ step.append(np.max(np.abs(x_new - x)))
34
+ x = x_new
35
+ xs.append(x)
36
+ residual.append(np.max(np.abs(b - A @ x)))
37
+ if step[-1] < tol:
38
+ break
39
+
40
+ table = pd.DataFrame({"k": range(len(xs)), "omega": omega, "step": step, "residual": residual})
41
+ table["q"] = table["residual"] / table["residual"].shift(1)
42
+ return pd.concat([table, pd.DataFrame(xs, columns=[f"x{i + 1}" for i in range(n)])], axis=1)
@@ -0,0 +1,33 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+
4
+
5
+ def composite_trapezoid(f, a, b, n):
6
+ """Composite trapezoidal rule with n sub-intervals (a single number)."""
7
+ h = (b - a) / n
8
+ total = f(a) + f(b)
9
+ for j in range(1, n):
10
+ total += 2 * f(a + j * h)
11
+ return (h / 2) * total
12
+
13
+
14
+ def trapezoid(f, a, b, n=1, exact=None):
15
+ """Trapezoidal rule for the integral of f over [a, b].
16
+
17
+ n : number of sub-intervals, or a list of them (n = 1 is the basic rule)
18
+ exact : optional true value, adds error and order
19
+
20
+ Returns a DataFrame: n, h, value [, error, order]
21
+ """
22
+ n = np.atleast_1d(n)
23
+ h = (b - a) / n
24
+ table = pd.DataFrame({"n": n, "h": h, "value": [composite_trapezoid(f, a, b, int(k)) for k in n]})
25
+
26
+ if exact is not None:
27
+ error = np.abs(table["value"].to_numpy() - exact)
28
+ with np.errstate(divide="ignore", invalid="ignore"):
29
+ order = np.log(error[:-1] / error[1:]) / np.log(h[:-1] / h[1:])
30
+ table["error"] = error
31
+ table["order"] = np.append(order, np.nan)
32
+
33
+ return table
@@ -0,0 +1,13 @@
1
+ import numpy as np
2
+
3
+
4
+ def tridiagonal_matrix(n, diag=4.0, off=-1.0):
5
+ """n x n matrix with diag on the main diagonal and off on the two neighbouring diagonals."""
6
+ A = np.zeros((n, n))
7
+ for i in range(n):
8
+ A[i, i] = diag
9
+ if i > 0:
10
+ A[i, i - 1] = off
11
+ if i < n - 1:
12
+ A[i, i + 1] = off
13
+ return A