Most efficient way to put vector on the off-diagonal of the blocks of a block matrix
18 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
David Gillcrist
le 23 Mai 2023
Modifié(e) : David Goodmanson
le 24 Mai 2023
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
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1391774/image.png)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1391779/image.png)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1391784/image.png)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1391789/image.png)
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/1391794/image.png)
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 commentaires
Réponse acceptée
Stephen23
le 23 Mai 2023
Modifié(e) : Stephen23
le 23 Mai 2023
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 commentaires
Plus de réponses (2)
David Goodmanson
le 24 Mai 2023
Modifié(e) : David Goodmanson
le 24 Mai 2023
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 commentaire
Dyuman Joshi
le 24 Mai 2023
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
le 23 Mai 2023
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.
Voir également
Catégories
En savoir plus sur Creating and Concatenating Matrices dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!