前言
有人可能好奇,为啥有那么多工具还要自己写一个。emmm…
比如我求 Ax=b, 增广矩阵, 比如说我想要 [ A , I ] [A, I] [A,I] -> [ I , A − 1 ] [I, A^{-1}] [I,A−1], 工具就用不了了
代码
"""
支持分数,主要用来计算阶梯型和最简阶梯型
Ax = b
Alter time: 2022.9.13 23:24
"""
from fractions import Fraction
cnt = 0 # 步骤计数器
# frac.numerator 整数/ frac.denominator分数
# 创造一个支持分数运算的矩阵
def make_matrix(list_matrix):
global cnt
cnt = 0
fra_matrix = []
for i in range(len(list_matrix)):
row = []
for j in list_matrix[i]:
if not isinstance(j, Fraction):
row.append(Fraction(j))
else:
row.append(j)
fra_matrix.append(row)
return fra_matrix
# 展示矩阵
def show(matrix, information_str='no tips'):
global cnt
print(information_str)
print('-' * len(matrix[0]) * 10)
for row in matrix:
for item in row:
print('{:>10}'.format(str(item)), end='')
print()
print()
cnt += 1
# 交换两行 (行数下标从1开始, 即 m * n的矩阵, 行数下标从1 ~ m)
def change_row(matrix, row1_num, row2_num):
global cnt
matrix[row1_num - 1], matrix[row2_num - 1] = matrix[row2_num - 1], matrix[row1_num - 1]
show(matrix, 'process {}. change row {} and row {}'.format(cnt, row1_num, row2_num))
# 化简某一行 (行数下标从1开始, 即 m * n的矩阵, 行数下标从1 ~ m)
def simplify(matrix, row_num, pivot_col, reduce_echelon_form=False):
global cnt
# row_num -= 1
pivot = matrix[row_num][pivot_col]
for j in range(len(matrix[0])):
matrix[row_num][j] /= pivot
# 化简为 最简行列式
if reduce_echelon_form:
for i in range(len(matrix)):
if i != row_num:
times = matrix[i][pivot_col]
for j in range(len(matrix[0])):
matrix[i][j] -= matrix[row_num][j] * times
else: # 只是化为行列式
for i in range(row_num + 1, len(matrix)):
times = matrix[i][pivot_col]
for j in range(len(matrix[0])):
matrix[i][j] -= matrix[row_num][j] * times
show(matrix, 'process {}. simplify row {}'.format(cnt, 1))
# 化为阶梯型
def echelon_form(a, cc_num=None, reduce_echelon_form=False):
m, n = len(a), len(a[0])
# print('s001: ', m, n, cofficient_cols_num)
if cc_num is None:
cc_num = n
prc_row, prc_col = 0, 0
while prc_row < m and prc_col < cc_num:
if a[prc_row][prc_col] == 0:
zero_flag = True
for f_row in range(prc_row + 1, m):
if a[f_row][prc_col] != 0:
change_row(prc_row, f_row)
zero_flag = False
break
if zero_flag:
prc_col += 1
continue
print('prc_row, prc_col:', prc_row, prc_col)
simplify(a, prc_row, prc_col, reduce_echelon_form=reduce_echelon_form)
prc_row += 1
prc_col += 1
tips_op = '(reduced)' if reduce_echelon_form else ''
if prc_row == m:
print('The matrix has been changed to {} echelon form'.format(tips_op))
else:
print('The matrix is singular')
if __name__ == '__main__':
a = [[1, 2, 1, 3], [2, 5, -1, -4], [3, -2, -1, 5]]
a = make_matrix(a)
cnt = 0 # 步骤计数器
cofficient_cols_num = 3
echelon_form(a, cofficient_cols_num, reduce_echelon_form=True)
例子输出:
prc_row, prc_col: 0 0
process 0. simplify row 1
----------------------------------------
1 2 1 3
0 1 -3 -10
0 -8 -4 -4
prc_row, prc_col: 1 1
process 1. simplify row 1
----------------------------------------
1 0 7 23
0 1 -3 -10
0 0 -28 -84
prc_row, prc_col: 2 2
process 2. simplify row 1
----------------------------------------
1 0 0 2
0 1 0 -1
0 0 1 3
The matrix has been changed to (reduced) echelon form
如果最后一行代码改一下, 即reduce_echelon_form为False, 我们只想得到阶梯型
echelon_form(a, cofficient_cols_num, reduce_echelon_form=False)
输出:
prc_row, prc_col: 0 0
process 0. simplify row 1
----------------------------------------
1 2 1 3
0 1 -3 -10
0 -8 -4 -4
prc_row, prc_col: 1 1
process 1. simplify row 1
----------------------------------------
1 2 1 3
0 1 -3 -10
0 0 -28 -84
prc_row, prc_col: 2 2
process 2. simplify row 1
----------------------------------------
1 2 1 3
0 1 -3 -10
0 0 1 3