-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgauss.py
86 lines (65 loc) · 2.41 KB
/
gauss.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import numpy as np
from scipy.linalg.lapack import dtrtri
# This will be needed in all routines...
def unpack(A: np.ndarray)->tuple[np.ndarray, np.ndarray]:
m, n = A.shape
assert m >= n
# Extract L and U.
L = np.tril(A).copy()
L[range(n), range(n)] = 1.0
U = np.triu(A)[:n, :n].copy()
return L, U
def basic_gaussian_elimination(A: np.ndarray)->tuple[np.ndarray, np.ndarray]:
m, n = A.shape[0], A.shape[1]
for k in range(min(m - 1, n)):
# L bearbeiten.
for j in range(k+1, m):
A[j, k] /= A[k, k]
# U bearbeiten. Beim letzten Schritt nicht arbeiten.
if k < n - 1:
for j in range(k+1, m):
for i in range(k+1, n):
A[j, i] -= A[j, k] * A[k, i]
return unpack(A)
def blas_2_inplace_gaussian_elimination(A: np.ndarray):
m, n = A.shape[0], A.shape[1]
for k in range(min(m - 1, n)):
# L bearbeiten.
A[k+1:, k] /= A[k, k]
# U bearbeiten.
if k < n:
A[k+1:, k+1:] -= np.outer(A[k+1:, k], A[k, k+1:])
def blas_2_gaussian_elimination(A: np.ndarray)->tuple[np.ndarray, np.ndarray]:
blas_2_inplace_gaussian_elimination(A)
return unpack(A)
def old_block_gaussian_elimination(b: int, A: np.ndarray)->tuple[np.ndarray, np.ndarray]:
m = A.shape[0]
assert m == A.shape[1]
assert m % b == 0
for k in range(0, m - 1, b):
# Faktorisiere Teilmatrix A hut.
L, _ = blas_2_gaussian_elimination(A[k:, k:k+b])
L_1, L_2 = L[:b, :], L[b:, :]
# Erstelle U_23 in A.
A[k:k+b,k+b:] = np.linalg.inv(L_1) @ A[k:k+b,k+b:]
# Erstelle A hut in A.
A[k+b:, k+b:] = A[k+b:, k+b:] - L_2 @ A[k:k+b,k+b:]
return unpack(A)
def block_gaussian_elimination(b: int, A: np.ndarray)->tuple[np.ndarray, np.ndarray]:
m = A.shape[0]
assert m == A.shape[1]
assert m % b == 0
for k in range(0, m - 1, b):
# Faktorisiere Teilmatrix A hut.
X = A[k:, k:k+b]
# Kopiere nur L und nicht U und spare somit etwas Zeit.
blas_2_inplace_gaussian_elimination(X)
L = np.tril(X).copy()
np.fill_diagonal(L, 1.0)
L_1, L_2 = L[:b, :], L[b:, :]
# Erstelle U_23 in A.
L_1_inv, _ = dtrtri(L_1, lower=1)
A[k:k+b,k+b:] = L_1_inv @ A[k:k+b,k+b:]
# Erstelle A hut in A.
A[k+b:, k+b:] = A[k+b:, k+b:] - L_2 @ A[k:k+b,k+b:]
return unpack(A)