from numpy import *
def rref(mat,precision=0,GJ=False):
m,n = mat.shape
p,t = precision, 1e-1**precision
A = around(mat.astype(float).copy(),decimals=p )
if GJ:
A = hstack((A,identity(n)))
pcol = -1 #pivot colum
for i in range(m):
pcol += 1
if pcol >= n : break
#pivot index
pid = argmax( abs(A[i:,pcol]) )
#Row exchange
A[i,:],A[pid+i,:] = A[pid+i,:].copy(),A[i,:].copy()
#pivot with given precision
while pcol < n and abs(A[i,pcol]) < t:
pcol += 1
if pcol >= n : break
#pivot index
pid = argmax( abs(A[i:,pcol]) )
#Row exchange
A[i,:],A[pid+i,:] = A[pid+i,:].copy(),A[i,:].copy()
if pcol >= n : break
pivot = float(A[i,pcol])
for j in range(m):
if j == i: continue
mul = float(A[j,pcol])/pivot
A[j,:] = around(A[j,:] - A[i,:]*mul,decimals=p)
A[i,:] /= pivot
A[i,:] = around(A[i,:],decimals=p)
if GJ:
return A[:,:n].copy(),A[:,n:].copy()
else:
return A
def rref(matrix):
A = np.array(matrix, dtype=np.float64)
i = 0 # row
j = 0 # column
while True:
# find next nonzero column
while all(A.T[j] == 0.0):
j += 1
# if reached the end, break
if j == len(A[0]) - 1 : break
# if a_ij == 0 find first row i_>=i with a
# nonzero entry in column j and swap rows i and i_
if A[i][j] == 0:
i_ = i
while A[i_][j] == 0:
i_ += 1
# if reached the end, break
if i_ == len(A) - 1 : break
A[[i, i_]] = A[[i_, i]]
# divide ith row a_ij to make it a_ij == 1
A[i] = A[i] / A[i][j]
# eliminate all other entries in the jth column by subtracting
# multiples of of the ith row from the others
for i_ in range(len(A)):
if i_ != i:
A[i_] = A[i_] - A[i] * A[i_][j] / A[i][j]
# if reached the end, break
if (i == len(A) - 1) or (j == len(A[0]) - 1): break
# otherwise, we continue
i += 1
j += 1
return A
def rref(A, tol=1.0e-12):
m, n = A.shape
i, j = 0, 0
jb = []
while i < m and j < n:
# Find value and index of largest element in the remainder of column j
k = np.argmax(np.abs(A[i:m, j])) + i
p = np.abs(A[k, j])
if p <= tol:
# The column is negligible, zero it out
A[i:m, j] = 0.0
j += 1
else:
# Remember the column index
jb.append(j)
if i != k:
# Swap the i-th and k-th rows
A[[i, k], j:n] = A[[k, i], j:n]
# Divide the pivot row i by the pivot element A[i, j]
A[i, j:n] = A[i, j:n] / A[i, j]
# Subtract multiples of the pivot row from all the other rows
for k in range(m):
if k != i:
A[k, j:n] -= A[k, j] * A[i, j:n]
i += 1
j += 1
# Finished
return A, jb
6条答案
按热度按时间gmol16391#
如果可以使用
sympy
,Matrix.rref()
也可以做到:z6psavjg2#
我同意@Mile评论to @WinstonEwert answer没有理由计算机不能以给定的精度执行RREF。
RREF的实现应该不是很复杂,matlab不知怎么就有了这个功能,numpy也应该有。
我做了一个非常简单明了的实现,虽然效率很低,但对于简单的矩阵来说,效果很好:
更新日期:
看起来,@JustMe在
rref
实现中发现了一个bug,如果输入矩阵的第一列为零,这个bug就会出现。下面是一些简单的测试
x一个一个一个一个x一个一个二个x
yyyllmsg3#
参见http://mail.scipy.org/pipermail/numpy-discussion/2008-November/038705.html
基本上就是:不做。
rref算法在计算机上实现时会产生太多的不准确性,所以你要么想用另一种方法解决这个问题,要么使用@aix建议的符号。
am46iovg4#
是的,在
scipy.linalg
中,lu
进行LU分解,这基本上会得到行-梯队形式。如果您感兴趣,还有其他的因式分解,如
qr
、rq
、svd
等等。Documentation.
4zcjmb1e5#
您可以自行定义:
h7appiyu6#
下面是一个工作版本,它几乎就是MATLAB的rref函数的一个麻木版本:
示例: