薛定宇教授大讲堂(卷Ⅲ):MATLAB线性代数运算
上QQ阅读APP看书,第一时间看更新

2.4 稀疏矩阵的输入

在很多应用中经常需要描述一些特殊的大型矩阵,而这类矩阵的大部分元素都是零,仅有少部分非零元素,这样的矩阵称为稀疏矩阵(sparse matrix)。若选择合适的求解算法,稀疏矩阵的计算比常规矩阵效率更高。MATLAB支持稀疏矩阵的输入,且很多矩阵分析函数支持稀疏矩阵的特别处理。

稀疏矩阵可以由sparse()函数读入MATLAB。A=sparse(p,q,w),其中,pq为非零元素的行号和列号构成的向量,w为相应位置的矩阵元素构成的向量。这三个向量的长度是一致的,否则将给出错误信息。

对双精度数据结构而言,存储一个矩阵元素需要8字节,所以要存储一个n×n的方阵需要8n2字节。稀疏矩阵要存储一个非零元素需要8字节存储该元素本身,还需要16字节存储其所在的行数与列数,所以总共需要24m字节存储非零元素,m为非零元素的个数。可见,m=n2/3时,存储双精度矩阵与稀疏矩阵所需的空间是一致的。换句话说,如果一个矩阵2/3以上的元素为零,则利用稀疏矩阵的方式存储矩阵比较经济,且矩阵的稀疏度越高存储越经济。

常规矩阵B与稀疏矩阵A是可以相互转换的,也可以检验一个矩阵A是不是按稀疏矩阵的形式存储的,这些转换与检测函数的调用格式为

B=full(A), A=sparse(B), key=issparse(A)

一个常规矩阵或稀疏矩阵的非零元素个数可以由n=nnz(A)直接得出。如果想提取出矩阵A中全部的非零元素,则可以使用v=nonzeros(A)命令,其提取顺序是按列提取。

稀疏矩阵A的非零元素所在的位置可以用spy(A)函数显示出来,如果A不是稀疏矩阵,仍然能用该函数显示矩阵的非零元素。在spy()调用语句中,A还可以是符号型矩阵。

例2-23 考虑例1-5中给出的简单梁结构,试分析矩阵的稀疏度。

这里只考虑双精度矩阵表示,不再采用符号型矩阵。可以用下面的语句重新输入原始矩阵,则可以得出该矩阵非零元素的个数为30。可以将该矩阵转换为稀疏矩阵,并绘制出稀疏矩阵的非零元素位置图。如图2-2所示,图中非零元素是用圆点表示的,没有圆点的位置元素都是零。

给出whos命令,还可以比较二者的存储空间使用情况。

从得出的结果看,该矩阵的稀疏度不是很高。不过可以看出,在复杂的梁结构中,例如有1000根梁,则建立起来的矩阵比较适合由稀疏矩阵表示,存储该矩阵会节省很多存储空间。

图2-2 稀疏矩阵非零元素的分布

MATLAB还提供了一些特殊稀疏矩阵的输入方法。例如,可以由speye()函数直接输入单位矩阵;还可以由sprandn()与sprandsym()函数生成随机的稀疏矩阵。这两个矩阵的元素都满足标准正态分布,不同的是,后者生成的是对称矩阵。这些函数的调用格式为

E=speye([n,m])

A=sprandn(n,m,稀疏度)

B=sprandn(n,稀疏度)

例2-24 试生成一个稀疏度为0.0002%的50000×50000随机矩阵,并观察随机元素的分布。试将该矩阵转换为常规矩阵。

可以由下面的语句直接生成所需的稀疏矩阵,并绘制出5000个非零元素的示意图,如图2-3所示。若想将矩阵转换成常规矩阵,则得出“Out of memory”错误信息,因为MATLAB不能存储这样大规模的常规矩阵。使用稀疏矩阵的方式,即使稀疏度增大为1%,仍能存储该矩阵。

则得出的结果显示如下

如何求解两个稀疏矩阵的乘法至今是一个具有挑战性的问题。如果不能很好地求解乘法问题,则需要将稀疏矩阵转换成普通矩阵再进行乘法运算,不能利用稀疏矩阵自身的性质减少运算量。

图2-3 稀疏矩阵非零元素的分布