Most efficient way to put vector on the off-diagonal of the blocks of a block matrix
18 次查看(过去 30 天)
显示 更早的评论
I have two vectors each of the same length, and I want to put these vectors on the diagonal parts of each block of a matrix. Let's say my two vectors are and , both are of length , I am trying to construct an matrix that looks like
For example if my vectors were v = [1 2 3 4 5 6 7 8 9 8 7 6] and u = [9 8 7 6 5 4 3 2 1 2 3 4] then I would mant a matrix that looks like
[0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
9 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 8 0 3 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 6 0 5 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 5 0 6 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 7 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 3 0 8 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 2 0 9 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 2 0 7 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 6;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0;
]
I would like to know what an efficient way of doing this, particularly with sparse arrays I could create this matrix.
0 个评论
采纳的回答
Stephen23
2023-5-23
编辑:Stephen23
2023-5-23
v = [1,2,3,4,5,6,7,8,9,8,7,6];
u = [9,8,7,6,5,4,3,2,1,2,3,4];
L = sqrt(numel(v));
vM = reshape(v,fix(L),[]);
uM = reshape(u,fix(L),[]);
vM(end+1,:) = 0;
uM(end+1,:) = 0;
vM([2:end,1],:) = vM;
N = ceil(L).^2;
M = spdiags([uM(:),vM(:)],[-1,1],N,N);
Checking:
full(M)
0 个评论
更多回答(2 个)
David Goodmanson
2023-5-24
编辑:David Goodmanson
2023-5-24
Hi David,
MODIFIED
see Dyuman's comment to sensibly shorten this original code.
n = 4;
v = [1 2 3 4 5 6 7 8 9 8 7 6]; % length n*(n-1)
u = [9 8 7 6 5 4 3 2 1 2 3 4];
vv = [reshape(v,n-1,n); zeros(1,n)];
vv = vv(:);
vv(end) = [];
uu = [reshape(u,n-1,n); zeros(1,n)];
uu = uu(:);
uu(end) = [];
M = diag(vv,1) + diag(uu,-1)
you can cut even more lines using the code below but at the cost of transparancy, so I think Dyuman's version is the best one.
n = 4;
v = [1 2 3 4 5 6 7 8 9 8 7 6];
u = [9 8 7 6 5 4 3 2 1 2 3 4];
uv = [reshape([v u],n-1,2*n);zeros(1,2*n)];
M = diag(uv(1:n^2-1),1) + diag(uv(n^2+1:2*n^2-1),-1)
1 个评论
Dyuman Joshi
2023-5-24
You can use indexing to shorten the code by 2 lines -
n = 4;
v = [1 2 3 4 5 6 7 8 9 8 7 6]; % length n*(n-1)
u = [9 8 7 6 5 4 3 2 1 2 3 4];
vv = [reshape(v,n-1,n); zeros(1,n)];
vv = vv(1:end-1);
uu = [reshape(u,n-1,n); zeros(1,n)];
uu = uu(1:end-1);
M = diag(vv,1) + diag(uu,-1)
John D'Errico
2023-5-23
The most efficient way? SPDIAGS.
help spdiags
For example, to create a 6x6 sparse matrix, with an upper and lower diagonal elements as vectors of length 5, we do this:
V1 = randi(10,[5,1]); % Just some random numbers.
V2 = randi(10,[5,1]);
A = spdiags([[V1;nan],[nan;V2]],[-1,1],6,6)
full(A)
spy(A)
Note that I padded an extra element, a NaN in this case, at the beginning of V2 and the end of V1.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!