在 Matlab 中,我在 2x249 矩阵中有两个单行 (1x249) 向量,我必须通过多次复制它们来创建一个矩阵 A
,每次将 2 个位置的向量移动到正确的。我想用零填充左侧的条目。有一个聪明的方法来做到这一点吗?目前,我正在使用 for 循环和 circshift,并且在每次迭代时添加新行到 A
,但这可能效率非常低。
代码(myMat
是我想要移动的矩阵):
A = [];
myMat = [1 0 -1 zeros(1,246); 0 2 0 -2 zeros(1,245)];
N = 20;
for i=1:N-1
aux = circshift(myMat,[0,2*(i-1)]);
aux(:,1:2*(i-1)) = 0;
A =[A; aux];
end
最佳答案
正如您可能知道的那样,Matlab 中的循环效率不高。 我知道 Mathworks 一直说 JIT 不再是这样 编译,但我还没有体验过快速循环。
我将你构建矩阵 A 的方法放入函数中:
function A = replvector1(myMat,shift_right,width,N)
pre_alloc = true; % make implementation faster using pre-allocation yes/no
% Pad myMat with zeros to make it wide enough
myMat(1,width)=0;
% initialize A
if pre_alloc
A = zeros(size(myMat,1)*(N-1),width);
else
A = [];
end
% Fill A
for i=1:N-1
aux = circshift(myMat,[0,shift_right*(i-1)]);
aux(:,1:min(width,shift_right*(i-1))) = 0;
A(size(myMat,1)*(i-1)+1:size(myMat,1)*i,:) =aux;
end
你的矩阵运算看起来很像克罗内克乘积,但是 block 矩阵具有重叠的列范围,因此是直接克罗内克积 不管用。相反,我构造了以下函数:
function A = replvector2(myMat,shift_right,width,N)
[i,j,a] = find(myMat);
i = kron(ones(N-1,1),i) + kron([0:N-2]',ones(size(i))) * size(myMat,1);
j = kron(ones(N-1,1),j) + kron([0:N-2]',ones(size(j))) * shift_right;
a = kron(ones(N-1,1),a);
ok = j<=width;
A = full(sparse(i(ok),j(ok),a(ok),(N-1)*size(myMat,1),width));
您可以通过删除分号并查看中间值来遵循该算法 结果。
以下主程序运行您的示例,并且可以轻松修改为 运行类似的示例:
% inputs (you may vary them to see that it always works)
shift_right = 2;
width = 249;
myMat1 = [ 1 0 -1 0 ;
0 2 0 -2 ];
N = 20;
% Run your implementation
tic;
A = replvector1(myMat,shift_right,width,N);
disp(sprintf('\n original implementation took %e sec',toc))
% Run the new implementation
tic;
B = replvector2(myMat,shift_right,width,N);
disp(sprintf(' new implementation took %e sec',toc))
disp(sprintf('\n norm(B-A)=%e\n',norm(B-A)))
关于matlab - 复制向量将它们向右移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50131507/