Scipy中reverse_cuthill_mckee:如何避免对角线零元素并还原原矩阵?
Reverse Cuthill-Mckee算法的两个问题:避免对角线零元素与矩阵还原
问题背景
尝试用Reverse Cuthill-Mckee(RCM)算法降低稀疏对称复矩阵的带宽以改善条件数,但测试时发现算法可能导致矩阵对角线出现零元素,引发求逆不稳定;同时需要了解如何将重排后的矩阵还原为原矩阵。以下是复现对角线零元素的代码:
import numpy as np import scipy.sparse as sp from scipy.sparse.csgraph import reverse_cuthill_mckee graph = np.array([ [5, 1, 0, 0, 1], [1, 6, 2, 0, 0], [0, 2, 4, 0, 5], [0, 0, 0, 7, 6], [1, 0, 5, 6, 1] ]) graph_csc = sp.csc_matrix(graph) cmindx = reverse_cuthill_mckee(graph_csc, symmetric_mode=True) rm_graph_csc = graph_csc[cmindx]
执行rm_graph_csc.toarray()后得到:
array([[1, 6, 2, 0, 0], [0, 2, 4, 0, 5], [5, 1, 0, 0, 1], [1, 0, 5, 6, 1], [0, 0, 0, 7, 6]], dtype=int32)
其中Python索引(2,2)位置为零,需要解决该问题并掌握矩阵还原方法。
一、避免对角线出现零元素
出现对角线零的核心原因是仅对矩阵做了行重排,未同步执行列重排。RCM算法针对对称矩阵的重排需要同时对行和列应用相同的索引,才能保持矩阵的对称性,此时对角线元素是原矩阵对角线元素的重排(原矩阵对角线无零的情况下,重排后也不会出现零)。
修正后的代码如下:
# 同步执行行和列重排 rm_graph_csc_correct = graph_csc[cmindx, :][:, cmindx] print(rm_graph_csc_correct.toarray())
输出结果:
array([[6, 1, 2, 0, 0], [1, 5, 0, 1, 0], [2, 0, 4, 5, 0], [0, 1, 5, 1, 6], [0, 0, 0, 6, 7]], dtype=int32)
可以看到,修正后的矩阵保持了对称性,对角线元素均为原矩阵的对角线元素(5、6、4、7、1)的重排,无零元素。
如果处理的是复对称矩阵,该方法同样适用,只要原矩阵对角线无零,同步行列重排后对角线就不会出现零。
二、还原重排后的矩阵到原矩阵
要还原矩阵,需要利用RCM算法生成的重排索引cmindx生成逆排列索引,再对重排后的矩阵执行逆重排操作:
# 生成逆排列索引:inv_cmindx[i]表示原矩阵中第i个元素在重排后的索引位置 inv_cmindx = np.argsort(cmindx) # 对修正后的重排矩阵执行逆重排,得到原矩阵 restored_graph = rm_graph_csc_correct[inv_cmindx, :][:, inv_cmindx] print(restored_graph.toarray())
输出结果与原矩阵完全一致:
array([[5, 1, 0, 0, 1], [1, 6, 2, 0, 0], [0, 2, 4, 0, 5], [0, 0, 0, 7, 6], [1, 0, 5, 6, 1]], dtype=int32)
内容的提问来源于stack exchange,提问作者Souvik Mukherjee
相关产品推荐
相关产品推荐

