import numpy as np
def eliminateCol(A, k=0):
# guarantee that A is float type
if A.dtype.kind != 'f' and A.dtype.kind != 'c': return None
# load dimensions
dim0,dim1 = np.shape(A)
# initialize outputs
swap = np.identity(dim0,dtype=float)
oper = np.identity(dim0,dtype=float)
# k < dim1
k = k%dim1
# if the column k is zero column, return
if A[:,k].any() == False: return swap,oper
i0 = 0
if k != 0:
# find a row i0 whose leftmost k-1 entries are all zero
while i0 < dim0:
if not A[i0, 0:k].any():
break
i0 += 1
# find a nonzero element A[i, k] to use as a pivot
i = i0
while i < dim0:
if A[i, k] != 0:
break
i += 1
if i == dim0:
return swap, oper
# Partial Pivoting: ensures that the largest element of the column is placed on the diagonal
max_index = np.argmax(np.abs(A[i0:, k])) + i0
A[[i0, max_index], ] = A[[max_index, i0], ]; swap[[i0, max_index], ] = swap[[max_index, i0], ]
# row i0 is the pivot row and A[j, k] is zero for i0 < j <= i
for i in range(i0 + 1, dim0):
if A[i, k] != 0:
quot = A[i, k] / A[i0, k]
A[i, :] -= quot * A[i0, :]
oper[i, i0] = -quot
return swap, oper
def eliminateRow(A, k=-1):
# guarantee that A is float type
if A.dtype.kind != 'f' and A.dtype.kind != 'c': return None
# load dimensions
dim0,dim1 = np.shape(A)
# initialize outputs
oper = np.identity(dim0,dtype=float)
# k < dim0
k = k%dim0
# if the row k is zero column, return
if k == 0 or A[k,:].any() == False: return oper
# find a nonzero element A[k,j] to use as a pivot
for j in range(dim1):
if A[k, j] != 0: break
for i in range(k - 1, -1, -1):
if A[i, j] != 0:
quot = A[i, j] / A[k, j]
A[i, :] -= quot * A[k, :]
oper[i, k] = -quot
return oper
def eliminateScale(A):
# guarantee that A is float type
if A.dtype.kind != 'f' and A.dtype.kind != 'c': return None
# load dimensions
dim0,dim1 = np.shape(A)
# initialize outputs
oper = np.identity(dim0,dtype=float)
# find pivots
i = 0
while i < dim0:
j = 0
while j < dim1:
if A[i,j] == 0: j+= 1; continue
else:
oper[i,i] = 1/A[i,j]
A[i,j:] = A[i,j:]/A[i,j]
break
j+= 1
i+= 1
return oper
def get_reduced_echelon_form (A):
for k in range(A.shape[1]):
eliminateCol(A, k)
eliminateRow(A, k)
# Finally, scale the matrix
eliminateScale(A)
return A
def get_echelon_form(A):
dim0, dim1 = np.shape(A)
for k in range(min(dim0, dim1)):
# Eliminate below diagonal in column k
swap, oper = eliminateCol(A, k)
return A
# Example Usage:
B = np.array([[0.02, 0.01, 0.0, 0.0, 0.02],
[1.0, 2.0, 1.0, 0.0, 1.0],
[0.0, 1.0, 2.0, 1.0, 4.0],
[0.0, 0.0, 100.0, 200.0, 800.0]], dtype=float)
A = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]], dtype=float)
echelon = get_echelon_form(A.copy())
reduced = get_reduced_echelon_form(A.copy())
print(B)
print(echelon)
print(reduced)
This is my code to find echelon and reduced echelon form of a matrix using partial pivoting. Please help me to any bugs or shortcomings.(please ignore using for loop instead of while loop)
At the result of execution, correct reduced row echelon form is found for zero column matrix, zero row matrix, and a example usage matrix for partial pivoting. I am looking for a bug or shortcoming