-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrref_gaussian_elimination.py
48 lines (47 loc) · 1.8 KB
/
rref_gaussian_elimination.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
# Converts an augmented matrix A to its RREF form
# The equal function handles floating precision issue
def rref(A):
def equal(a, b): return abs(a-b) < 1e-5
def leading_entry_col(A, r):
row = A[r]; i = 0
while i < len(A[0]) and equal(row[i], 0): i += 1
return i
def list_pivots(A):
res = []
for r in range(len(A)):
k = leading_entry_col(A, r)
if k != len(A[0]): res.append((r, k))
return sorted(res, reverse=True)
def col(A, i): return list(map(lambda x: x[i], A))
def ero1(A, i, c):
for j in range(len(A[0])): A[i][j] *= c
def ero2(A, i, j, c):
for k in range(len(A[0])): A[i][k] += c*A[j][k]
def ero3(A, i, j): A[i], A[j] = A[j], A[i]
curr_col = 0
curr_row = 0
while curr_col < len(A[0]) and curr_row < len(A):
if equal(A[curr_row][curr_col], 0):
check_col = col(A, curr_col)[curr_row+1:]
for i in range(len(check_col)):
if not equal(check_col[i], 0): break
elif i == len(check_col)-1: i += 1
if i < len(check_col): ero3(A, curr_row, curr_row+i+1)
else: curr_col += 1
else:
if not equal(A[curr_row][curr_col], 1): ero1(A, curr_row, 1/A[curr_row][curr_col])
for i in range(curr_row+1, len(A)):
if not equal(A[i][curr_col], 0): ero2(A, i, curr_row, -A[i][curr_col])
curr_col += 1
curr_row += 1
pivots = list_pivots(A)
for i in range(len(pivots)-1):
for j in range(pivots[i][0]-1, -1, -1): ero2(A, j, pivots[i][0], -A[j][pivots[i][1]])
return A
A = [
[16, 2, 3, 13],
[5, 11, 10, 8],
[9, 7, 6, 12],
[4, 14, 15, 1]
]
for row in rref(A): print([round(i, 9) for i in row])