我有一个for循环创建一个三对角矩阵,如下所示:
m = 5;
Fo = 0.35;
A(1,1) = 1+2*Fo;
A(1,2) = 1+Fo;
for i = 2:m-1
A(i,i-1) = 1;
A(i,i) = 2;
A(i,i+1) = 3;
end
A(m,m-1) = 4;
A(m,m) = 5;
输出为:
A =
1.7000 1.3500 0 0 0
1.0000 2.0000 3.0000 0 0
0 1.0000 2.0000 3.0000 0
0 0 1.0000 2.0000 3.0000
0 0 0 4.0000 5.0000
我正在尝试使用以下内容来替换for循环来创建三对角矩阵:
i = 2:m-1;
A(i,i-1) = 1;
A(i,i) = 2;
A(i,i+1) = 3;
不幸的是输出不正确:
A =
1.7000 1.3500 0 0 0
1.0000 2.0000 3.0000 3.0000 3.0000
1.0000 2.0000 3.0000 3.0000 3.0000
1.0000 2.0000 3.0000 3.0000 3.0000
0 0 0 4.0000 5.0000
是否可以使用矢量化而不是for-loop创建这样的矩阵?我最终需要创建一个更大更复杂的三对角矩阵,因此希望使用矢量化来加速这个过程。
答案 0 :(得分:2)
正如路易斯指出的那样,sub2ind能够运作。我想你也可以使用诊断。例如,你可能会这样做:
m = 5;
Fo = 0.35;
d = [1+2*Fo; repmat(2,m - 2,1); 5];
ud = [1+Fo;repmat(3,m-2,1)];
sd = [ones(m-2,1);4];
A = diag(d) + diag(ud,1) + diag(sd,-1)
A =
1.7 1.35 0 0 0
1 2 3 0 0
0 1 2 3 0
0 0 1 2 3
0 0 0 4 5
问题是我们在这个组合中做了很多添加,并且大多数添加都是零。不喜欢这种解决方案的另一个原因是它产生了一个完整的矩阵。我不建议一般,但它是一个很好的,直观的直观解决方案。 (顺便说一句,我只是注意到diag的帮助显示了这个解决方案,以创建一个三对角矩阵。)
更好的选择是学习使用稀疏矩阵。三对角矩阵是SPARSE。使用该功能。为此,学习如何使用spdiags,或者至少学习稀疏。
让我们将A构建为稀疏的三对角矩阵。我将使用更大的m值,以便我们可以看到节省的费用。
m = 500;
Fo = 0.35;
d = [1+2*Fo; repmat(2,m - 2,1); 5];
ud = [1+Fo;repmat(3,m-2,1)];
sd = [ones(m-2,1);4];
A = diag(d) + diag(ud,1) + diag(sd,-1);
As = spdiags([[sd;0],d,[0;ud]],[-1 0 1],m,m);
whos A*
Name Size Bytes Class Attributes
A 500x500 2000000 double
As 500x500 27976 double sparse
因此,稀疏形式需要28k存储,而完整版需要2兆字节。
当您开始以稀疏形式使用这些数组时,真正的好处将会出现。例如,使用反斜杠:
y = rand(m,1);
tic,x = A\y;toc
Elapsed time is 0.002847 seconds.
tic,xs = As\y;toc
Elapsed time is 0.000290 seconds.
我想我还应该在MATLAB Central文件交换中找到我自己的代码blktridiag。它真的被设计用于生成块三对角数组,但它也可以解决这个问题,因为我们只有标量块。
Ab = blktridiag(reshape(d,1,1,m),reshape(sd,1,1,m-1),reshape(ud,1,1,m-1));
As - Ab
ans =
All zero sparse: 500-by-500
最后,正如natan指出的那样,如果你的目标是一个完整的矩阵,那么在给定稀疏矩阵输入的情况下,函数full将会这样做。但是,在许多情况下,稀疏形式将是一个很大的好处。学习使用稀疏矩阵。你会很高兴的。
答案 1 :(得分:1)
您可以使用sub2ind
:
for
循环进行矢量化
m = 5;
Fo = 0.35;
A = zeros(m); % initialize
A(sub2ind([m m],2:m, 1:m-1)) = 1;
A(sub2ind([m m],1:m, 1:m)) = 2;
A(sub2ind([m m],1:m-1, 2:m)) = 3;
A(1,1) = 1+2*Fo;
A(1,2) = 1+Fo;
A(m,m-1) = 4;
A(m,m) = 5;
替换循环的方法的问题是两个索引被认为是定义一个块(两个索引的所有组合),而不是对角线(第一个索引的每个值与第二个中的每个对应值)。