MATLAB - 稀疏到密集矩阵
MATLAB - sparse to dense matrix
我在代码生成的数据文件中有一个稀疏矩阵(不是 MATLAB
)。数据文件由四列组成。前两列是矩阵项的实部和虚部,第三列和第四列分别是对应的行和列索引。
我使用以下脚本将其转换为 Matlab
中的密集矩阵。
tic
dataA = load('sparse_LHS.dat');
toc
% Initialise matrix
tic
Nr = 15; Nz = 15; Neq = 5;
A (Nr*Nz*Neq,Nr*Nz*Neq) = 0;
toc
tic
lA = length(dataA)
rowA = dataA(:,3); colA = dataA(:,4);
toc
tic
for i = 1:lA
A(rowA(i), colA(i)) = complex(dataA(i,1), dataA(i,2));
end
toc
然而,这个脚本非常慢(for
循环是罪魁祸首)。
Elapsed time is 0.599023 seconds.
Elapsed time is 0.001978 seconds.
Elapsed time is 0.000406 seconds.
Elapsed time is 275.462138 seconds.
matlab
有什么快速的方法吗?
这是我到目前为止尝试过的方法:
parfor
- 这给了我
valid indices are restricted in parfor loops
我厌倦了将 for
循环改写成这样:
A(rowA(:),colA(:)) = complex(dataA(:,1), dataA(:,2));
然后出现错误
Subscripted assignment dimension mismatch.
您最后一次尝试失败的原因是 Matlab 无法获取列和行的下标列表,并匹配它们以按顺序分配元素。相反,它从列表中生成所有行和列的组合 - 这就是它的样子:
dataA = magic(4)
dataA =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
dataA([1,2],[1,4]) =
16 13
5 8
所以我们得到了 4 个元素([1,1]
、[1,4]
、[2,1]
、[2,4]
)而不是 2 个([1,1]
和 [2,4]
).
为了在列表中使用下标,您需要将它们转换为 linear indexing, and one simple way to do this is using the function sub2ind。
使用此功能,您可以编写以下代码一次完成所有操作:
% Initialise matrix
Nr = 15; Nz = 15; Neq = 5;
A(Nr*Nz*Neq,Nr*Nz*Neq) = 0;
% Place all complex values from dataA(:,1:2) in to A by the subscripts in dataA(:,3:4):
A(sub2ind(size(A),dataA(:,3),dataA(:,4))) = complex(dataA(:,1), dataA(:,2));
sub2ind 不是一个快速的函数(但它会比你的循环快得多),所以如果你有很多数据,你可能想自己计算线性索引:
rowA = dataA(:,3);
colA = dataA(:,4);
% compute the linear index:
ind = (colA-1)*size(A,1)+rowA;
% Place all complex values from dataA(:,1:2) in to A by the the index 'ind':
A(ind) = complex(dataA(:,1), dataA(:,2));
P.S.:
如果您使用的是 Matlab R2015b 或更高版本:
A = zeros(Nr*Nz*Neq,Nr*Nz*Neq);
比
quicker
A(Nr*Nz*Neq,Nr*Nz*Neq) = 0;
我在代码生成的数据文件中有一个稀疏矩阵(不是 MATLAB
)。数据文件由四列组成。前两列是矩阵项的实部和虚部,第三列和第四列分别是对应的行和列索引。
我使用以下脚本将其转换为 Matlab
中的密集矩阵。
tic
dataA = load('sparse_LHS.dat');
toc
% Initialise matrix
tic
Nr = 15; Nz = 15; Neq = 5;
A (Nr*Nz*Neq,Nr*Nz*Neq) = 0;
toc
tic
lA = length(dataA)
rowA = dataA(:,3); colA = dataA(:,4);
toc
tic
for i = 1:lA
A(rowA(i), colA(i)) = complex(dataA(i,1), dataA(i,2));
end
toc
然而,这个脚本非常慢(for
循环是罪魁祸首)。
Elapsed time is 0.599023 seconds.
Elapsed time is 0.001978 seconds.
Elapsed time is 0.000406 seconds.
Elapsed time is 275.462138 seconds.
matlab
有什么快速的方法吗?
这是我到目前为止尝试过的方法:
parfor
- 这给了我
valid indices are restricted in parfor loops
我厌倦了将 for
循环改写成这样:
A(rowA(:),colA(:)) = complex(dataA(:,1), dataA(:,2));
然后出现错误
Subscripted assignment dimension mismatch.
您最后一次尝试失败的原因是 Matlab 无法获取列和行的下标列表,并匹配它们以按顺序分配元素。相反,它从列表中生成所有行和列的组合 - 这就是它的样子:
dataA = magic(4)
dataA =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
dataA([1,2],[1,4]) =
16 13
5 8
所以我们得到了 4 个元素([1,1]
、[1,4]
、[2,1]
、[2,4]
)而不是 2 个([1,1]
和 [2,4]
).
为了在列表中使用下标,您需要将它们转换为 linear indexing, and one simple way to do this is using the function sub2ind。
使用此功能,您可以编写以下代码一次完成所有操作:
% Initialise matrix
Nr = 15; Nz = 15; Neq = 5;
A(Nr*Nz*Neq,Nr*Nz*Neq) = 0;
% Place all complex values from dataA(:,1:2) in to A by the subscripts in dataA(:,3:4):
A(sub2ind(size(A),dataA(:,3),dataA(:,4))) = complex(dataA(:,1), dataA(:,2));
sub2ind 不是一个快速的函数(但它会比你的循环快得多),所以如果你有很多数据,你可能想自己计算线性索引:
rowA = dataA(:,3);
colA = dataA(:,4);
% compute the linear index:
ind = (colA-1)*size(A,1)+rowA;
% Place all complex values from dataA(:,1:2) in to A by the the index 'ind':
A(ind) = complex(dataA(:,1), dataA(:,2));
P.S.:
如果您使用的是 Matlab R2015b 或更高版本:
A = zeros(Nr*Nz*Neq,Nr*Nz*Neq);
比
quickerA(Nr*Nz*Neq,Nr*Nz*Neq) = 0;