要求完成课堂上讲的关于矩阵分解的LU、QR(Gram-Schmidt)、Orthogonal Reduction (Householder reduction 和Givens reduction)和 URV程序实现,要求如下:
1、一个综合程序,根据选择参数的不同,实现不同的矩阵分解;在此基础上,实现Ax=b方程组的求解,以及计算A的行列式;
2、可以用matlab、Python等编写程序,需附上简单的程序说明,比如参数代表什么意思,输入什么,输出什么等等,附上相应的例子;
3、一定是可执行文件,例如 .m文件等,不能是word或者txt文档。附上源代码,不能为直接调用matlab等函数库;
import numpy as np import scipy import copy def det_P(P: np.ndarray): """ 计算LU分解中的P矩阵的行列式 :param P: LU分解中的P矩阵 :return: P矩阵的行列式 """ h, w = P.shape t = 0 for i in range(h): if P[i][i] != 1: t = t + 1 for j in range(h): if P[i][j] == 1: s = j for j in range(i + 1, h): if P[j][i] == 1: P[i][i] = 1 P[i][j] = 0 P[j][i] = 0 P[j]▼显示 = 1 if t % 2 == 0: return 1 else: return -1 def det_triangle(matrix: np.ndarray): """ 计算三角矩阵的行列式 :param matrix: 上三角矩阵或下三角矩阵 :return: 上三角矩阵或下三角矩阵的行列式 """ h, w = matrix.shape sum = 1 for i in range(h): sum = sum * matrix[i][i] return sum def det(matrix: np.ndarray): """ 利用LU分解计算行列式 :param matrix: :return: 行列式 """ P, L, U = matrix_decompose(matrix, "LU") print("*" * 30 + "计算行列式" + "*" * 30) det_p = det_P(P) det_l = det_triangle(L) det_u = det_triangle(U) return np.rint(det_p * det_u * det_l) def matrix_decompose(matrix: np.ndarray, mode): """ 实现矩阵的LU、QR(Gram-Schmidt)、Orthogonal Reduction (Householder reduction 和Givens reduction)和 URV :param matrix: 需要分解的矩阵 :param mode: 1、LU 实现矩阵的LU分解 2、Gram-Schmidt 采用Gram-Schmidt的方式实现矩阵的QR分解 3、Householder reduction 采用Householder reduction的方式实现矩阵的QR分解 4、Givens reduction 采用Givens reduction的方式实现矩阵的QR分解 5、URV 实现矩阵的URV分解 :return: 若为LU分解,则一次返回P、L、U矩阵,使得PA=LU 若为QR分解,则返回Q、R矩阵,使得A=QR 若为URV分解,则返回R,R,U矩阵,使得A=URV^T """ h, w = matrix.shape if h < w: print("*" * 30 + mode + "(h<w 类型)" + "*" * 30) elif h == w: print("*" * 30 + mode + "(h=w 类型)" + "*" * 30) else: print("*" * 30 + mode + "(h>w 类型)" + "*" * 30) if mode == 'LU': h, w = matrix.shape A = copy.deepcopy(matrix) P = np.identity(h) L = np.zeros((h, w)) U = np.zeros((w, w)) min_len = min(A.shape) # 高斯消元法 for i in range(min_len): index = i for j in range(i + 1, h): if np.abs(A[j, i]) > np.abs(A[index, i]): index = j temp = copy.deepcopy(P[i, :]) P[i, :] = P[index, :] P[index, :] = temp temp = copy.deepcopy(A[i, :]) A[i, :] = A[index, :] A[index, :] = temp print("行交换({},{}): ".format(i, index), A) for j in range(i + 1, h): c = A[j][i] / A[i][i] for k in range(i, w): A[j][k] = A[j][k] - c * A[i][k] A[j][i] = c print("行消去({},{}以下): {}".format(i, i, A)) print("*A* ", A) for i in range(0, h): if i < w: L[i, i] = 1 for j in range(0, min(i, w)): L[i, j] = A[i, j] for i in range(0, h): for j in range(i, w): U[i, j] = A[i, j] print("*" * 30 + "分解计算完成" + "*" * 30) print("P: ", P) print("L: ", L) print("U: ", U) print("*" * 30 + "验证PA=LU" + "*" * 30) restored_A = L @ U print("P@A: ", P @ matrix) print("restored_A: ", np.rint(restored_A)) return P, L, U elif mode == 'Gram-Schmidt': u = [] h, w = matrix.shape A = copy.deepcopy(matrix) R = np.zeros((w, w)) Q = np.zeros((h, w)) q = [] # 施密特正交化 for i in range(w): u.append(A[:, i].reshape((-1, 1))) for i in range(0, w): sum = np.zeros((h, 1)) for j in range(0, i): rji = (q[j].T @ u[i])[0][0] R[j][i] = rji sum += rji * q[j] qi = u[i] - sum rii = np.linalg.norm(qi) R[i][i] = rii qi = qi / rii q.append(qi) print("h:{},w:{}".format(h, w)) print(Q.shape) for i in range(w): Q[:, i] = q[i].reshape(h) print("*" * 30 + "分解计算完成" + "*" * 30) print("Q: ", Q) print("R: ", R) print("*" * 30 + "验证A=QR" + "*" * 30) A_restored = Q @ R A_restored[(A_restored < 1e-12) & (A_restored > -1e-12)] = 0 print("A_restored: ", np.rint(A_restored)) print("matrix: ", matrix) return Q, R elif mode == 'Householder reduction': # 计算PA=R 其中R为上三角矩阵 A_h, A_w = matrix.shape Plist = [] R = np.zeros((A_h, A_w)) l = min(A_h, A_w) A = copy.deepcopy(matrix) if A_h > A_w: l = l + 1 for i in range(l - 1): print("epoch:{}".format(i + 1)) min_len = min(A.shape) print("A的大小为{},A的最短边大小为{}".format(A.shape, min_len)) A_1 = A[:, 0].reshape(-1, 1) # A的第一列 A_1_len = A_1.shape[0] print("A1的长度: ", A_1_len) print("A的第一列: ", A_1) A_1_norm = np.linalg.norm(A_1) # A的第一列的模 print("A的第一列的模: ", A_1_norm) e1 = np.identity(A_1_len)[:, 0].reshape((-1, 1)) print("e1: ", e1) u = A_1 - A_1_norm * e1 # u=A1-||A1||e1 print("u=A1-||A1||e1: ", u) P_1 = np.identity(A_1_len) - 2 * (u @ u.T / (u.T @ u)) # P1=I-2*(UUT/UTU) print("P1=I-2*(UUT/UTU): ", P_1) P_ = np.identity(A_h) P_[i:, i:] = P_1 # 扩充大小 print("P_为P左上角添加1: ", P_) Plist.append(P_) A = P_1 @ A # 将A的第一列主元下方的元素消去 A[(A < 1e-12) & (A > -1e-12)] = 0 print("A: ", A) # 计算R矩阵 R[i, i:] = A[0, :] R[i:, i] = A[:, 0] print("R: ", R) A_ = A[1:, 1:] print("A_: ", A_) A = A_ if A_.shape[0] == 1: R[i + 1][i + 1:] = A[0][0:] R[(R < 1e-12) & (R > -1e-12)] = 0 print("上三角矩阵R: ", R) P = np.identity(A_h) for p in Plist: P = p @ P print("P: ", P) Q = np.linalg.inv(P) Q[(Q < 1e-12) & (Q > -1e-12)] = 0 print("*" * 30 + "分解计算完成" + "*" * 30) print("Q: ", Q) print("R: ", R) print("*" * 30 + "验证A=QR" + "*" * 30) A_restored = Q @ R A_restored[(A_restored < 1e-12) & (A_restored > -1e-12)] = 0 print("A_restored: ", np.rint(A_restored)) print("matrix: ", matrix) return Q, R elif mode == 'Givens reduction': h, w = matrix.shape Plist = [] A = copy.deepcopy(matrix) # 构造旋转矩阵 for i in range(0, h): for j in range(0, min(i, w)): P_ = np.identity(h) a = A[j][j] b = A[i][j] print("a:{},b:{}".format(a, b)) if a != 0 or b != 0: d = np.sqrt(a ** 2 + b ** 2) c = a / d s = b / d print("c:{},s:{}".format(c, s)) P_[i][i] = c P_[j][j] = c P_[i][j] = -s P_[j][i] = s Plist.append(P_) print("消去({},{})".format(i, j)) print("旋转矩阵P_: ", P_) A = P_ @ A A[(A < 1e-12) & (A > -1e-12)] = 0 print("A: ", A) P = np.identity(h) for p in Plist: P = p @ P print("P: ", P) Q = np.linalg.inv(P) R = A Q[(Q < 1e-12) & (Q > -1e-12)] = 0 print("*" * 30 + "分解计算完成" + "*" * 30) print("Q: ", Q) print("R: ", R) print("*" * 30 + "验证A=QR" + "*" * 30) A_restored = Q @ R A_restored[(A_restored < 1e-12) & (A_restored > -1e-12)] = 0 print("A_restored: ", np.rint(A_restored)) print("matrix: ", matrix) return Q, R elif mode == 'URV': A = matrix m, n = A.shape r = np.linalg.matrix_rank(A) # 奇异值分解 U, sigma, VT = np.linalg.svd(A, full_matrices=True) # 构造C和零矩阵 C = np.diag(sigma[:r]) R = np.zeros((m, n)) R[:r, :r] = C # 截断U和V以获得正确的大小 U = U[:, :m] V = VT.T[:, :n] print("*" * 30 + "验证A=URV^T" + "*" * 30) print((U @ R @ VT)) return U, R, V.T else: raise ValueError("mode error") if mode in ['Givens reduction', 'Householder reduction', 'Gram-Schmidt']: print("*" * 30 + "验证QR分解" + "*" * 30) Q_, R_ = np.linalg.qr(matrix) print("Q_: ", Q_) print("R_: ", R_) elif mode == 'LU': print("*" * 30 + "验证LU分解" + "*" * 30) P_, L_, U_ = scipy.linalg.lu(matrix) print("P_: ", P_) print("L_: ", L_) print("U_: ", U_) def AXb(A: np.ndarray, b: np.ndarray): """ 解方程AX=b :param A: 系数矩阵A :param b: b :return: 待求未知量X """ n = A.shape[0] Ab = np.hstack((A, b)) Rank_A = np.linalg.matrix_rank(A) Rank_Ab = np.linalg.matrix_rank(Ab) if Rank_A == Rank_Ab and Rank_A == n: P, L, U = matrix_decompose(A, "LU") print("*" * 30 + "解方程AX=b" + "*" * 30) # LUX=Pb Pb = P @ b print("P@b ", Pb) # LY=Pb 计算Y y_list = [] for i in range(n): sum = 0 for j in range(0, i): sum += L[i][j] * y_list[j] y_list.append(Pb[i][0] - sum) print("y_list: ", y_list) # UX=Y 计算X x_list = [] for i in range(n - 1, -1, -1): sum = 0 for j in range(n - 1, i, -1): sum += U[i][j] * x_list[n - j - 1] x_list.append((y_list[i] - sum) / U[i][i]) x_list.reverse() X = np.array(x_list).reshape((-1, 1)) print("X: ", X) print("*" * 30 + "验证AX=b" + "*" * 30) print(np.linalg.solve(A, b)) else: print("不存在唯一解") if __name__ == '__main__': mode = "Householder reduction" # # h<w 类型 # matrix1 = np.array( # [[0, -20, 23, 34, 11, 20, 2], [3, 27, 124, 52, 1, 49, 123], [4, 11, 8, 23, 9, 64, 76], # [12, 45, 12, 86, 95, 19, 99]], # dtype=np.float32) # print("matrix1: {} matrix1.shape: {}".format(matrix1, matrix1.shape)) # matrix_decompose(matrix1, mode) # # h=w 类型 # matrix2 = np.array([[0, -20, 23], [3, 27, -4], [4, 11, -2]], dtype=np.float32) # print("matrix2: {} matrix2.shape: {}".format(matrix2, matrix2.shape)) # matrix_decompose(matrix2, mode) # # h>w 类型 # matrix3 = np.array( # [[0, -20, 23], [3, 27, 124], [4, 11, 8], [12, 45, 12], [123, 1, 80], [12, 99, 662]], # dtype=np.float32) # b = np.array([[0], [0], [0], [5], [5], [5]]) # print("matrix3: {} matrix3.shape: {}".format(matrix3, matrix3.shape)) # matrix_decompose(matrix3, b, mode) # LU分解 matrix4 = np.array( [[0, -20, 23, 319, -89], [3, 27, -4, 987, 34], [4, 11, -2, -237, 10], [12, 67, 234, 66, -1099], [32, 562, 64, 88, 24]], dtype=np.float32) P, L, U = matrix_decompose(matrix4, "LU") print(det(matrix4)) print(np.linalg.det(matrix4)) # matrix6 = np.array([[1, 2, -3, 4], [4, 8, 12, -8], [2, 3, 2, 1], [-3, -1, 1, -4]], dtype=np.float32) # b = np.array(([1], [2], [3], [4]), dtype=np.float32) # AXb(matrix6, b)