问题
I am trying to do an elementwise insertion of a small matrix (2x2) along the diagonal of a large matrix (10x10 say). Overlapping values are added, and the small matrix is only inserted where it can fit fully inside the large matrix.
I have achieved this using a for loop, but am curious whether the process can be vectorised.
function M = TestDiagonal()
N = 10;
miniM = [1, -1; -1, 1];
M = zeros(N);
for i = 1:N-1
M(i:i+1,i:i+1) = M(i:i+1,i:i+1) + miniM;
end
end
Giving the desired matrix
1 -1 0 0 0 0 0 0 0 0
-1 2 -1 0 0 0 0 0 0 0
0 -1 2 -1 0 0 0 0 0 0
0 0 -1 2 -1 0 0 0 0 0
0 0 0 -1 2 -1 0 0 0 0
0 0 0 0 -1 2 -1 0 0 0
0 0 0 0 0 -1 2 -1 0 0
0 0 0 0 0 0 -1 2 -1 0
0 0 0 0 0 0 0 -1 2 -1
0 0 0 0 0 0 0 0 -1 1
In the general case, the input will always be square, but can take any size. The step dimension will always be equal to 1.
回答1:
Just use 2D convolution (see conv2).
2×2 case, step 1 along each dimension
M = conv2(eye(N-1), miniM);
m
×m
case, step 1 along each dimension
M = conv2(eye(N-size(miniM-1)+1), miniM);
m
×n
case, arbitrary steps along each dimension
In this case the steps need to be defined:
step = [2 1]; % desired step along each dimension
and it makes more sense to define a desired number of repetitions R
, rather than the final size (N
), because the latter may not be achievable with full repetitions of miniM
:
R = 4; % desired number of repetitions
Then:
M = conv2(full(sparse(1:step(1):step(1)*R, 1:step(2):step(2)*R, 1)), miniM);
Example:
>> miniM = [10 20 30; 40 50 60];
>> R = 4;
>> step = [1 2];
>> M = conv2(full(sparse(1:step(1):step(1)*R, 1:step(2):step(2)*R, 1)), miniM)
M =
10 20 30 0 0 0 0 0 0
40 50 70 20 30 0 0 0 0
0 0 40 50 70 20 30 0 0
0 0 0 0 40 50 70 20 30
0 0 0 0 0 0 40 50 60
来源:https://stackoverflow.com/questions/58484566/vectorisation-of-code-for-insertion-of-2x2-matrix-along-the-diagonal-of-a-large