How to extract diagonal elements of multidimensional array ?

12 visualizaciones (últimos 30 días)
If I have a m-order n-dimensional tensor. How should I extract the diagonal elements ?
For example
% Generate a 3-order 4-dimensional tensor
rng('default')
A = rand(4,4,4)
A =
A(:,:,1) = 0.8147 0.6324 0.9575 0.9572 0.9058 0.0975 0.9649 0.4854 0.1270 0.2785 0.1576 0.8003 0.9134 0.5469 0.9706 0.1419 A(:,:,2) = 0.4218 0.6557 0.6787 0.6555 0.9157 0.0357 0.7577 0.1712 0.7922 0.8491 0.7431 0.7060 0.9595 0.9340 0.3922 0.0318 A(:,:,3) = 0.2769 0.6948 0.4387 0.1869 0.0462 0.3171 0.3816 0.4898 0.0971 0.9502 0.7655 0.4456 0.8235 0.0344 0.7952 0.6463 A(:,:,4) = 0.7094 0.6551 0.9597 0.7513 0.7547 0.1626 0.3404 0.2551 0.2760 0.1190 0.5853 0.5060 0.6797 0.4984 0.2238 0.6991
The diagonal elements are A(1,1,1) = 0.8147, A(2,2,2) = 0.0357, A(3,3,3) = 0.7655 and A(4,4,4) = 0.6991.
I was hoping to have a tensor_diag function that takes a tensor A as an input parameter and returns a vector consisting of its diagonal elements.
  3 comentarios
Stephen23
Stephen23 el 23 de Mzo. de 2023
Editada: Stephen23 el 23 de Mzo. de 2023
@Mattia Marsetti: your code throws an error on the example array:
rng('default')
A = rand(4,4,4)
A =
A(:,:,1) = 0.8147 0.6324 0.9575 0.9572 0.9058 0.0975 0.9649 0.4854 0.1270 0.2785 0.1576 0.8003 0.9134 0.5469 0.9706 0.1419 A(:,:,2) = 0.4218 0.6557 0.6787 0.6555 0.9157 0.0357 0.7577 0.1712 0.7922 0.8491 0.7431 0.7060 0.9595 0.9340 0.3922 0.0318 A(:,:,3) = 0.2769 0.6948 0.4387 0.1869 0.0462 0.3171 0.3816 0.4898 0.0971 0.9502 0.7655 0.4456 0.8235 0.0344 0.7952 0.6463 A(:,:,4) = 0.7094 0.6551 0.9597 0.7513 0.7547 0.1626 0.3404 0.2551 0.2760 0.1190 0.5853 0.5060 0.6797 0.4984 0.2238 0.6991
get_tensor(A)
Index in position 4 exceeds array bounds. Index must not exceed 1.

Error in solution>get_tensor (line 19)
out(i)=eval(str);
function out=get_tensor(v)
size_v=size(v);
if sum(size_v == size_v(1))<numel(size_v)
error('the input vector is not a sqare matrix');
end
N = size_v(1);
out=zeros(N,1);
for i=1:N
str='v(';
for s=1:N
str=[str 'i,'];
end
str(end:end+1)=');';
out(i)=eval(str);
end
end
Note that you could easily replace the evil EVAL with a cell array and a comma-separated list.
Mattia Marsetti
Mattia Marsetti el 24 de Mzo. de 2023
Thanks for the hint Stephen23, I'll try that
Regards

Iniciar sesión para comentar.

Respuesta aceptada

the cyclist
the cyclist el 23 de Mzo. de 2023
rng('default')
N = 4;
A = rand(N,N,N);
A(1:N^2+N+1:end)
ans = 1×4
0.8147 0.0357 0.7655 0.6991
  5 comentarios
the cyclist
the cyclist el 23 de Mzo. de 2023
Ah, I read your question too quickly, and didn't make my solution general enough. Glad you found it.
Stephen23
Stephen23 el 23 de Mzo. de 2023
@shuang Yang: you could generalize that:
A(1:sum(N.^(0:ndims(A)-1):end)

Iniciar sesión para comentar.

Más respuestas (1)

Bruno Luong
Bruno Luong el 23 de Mzo. de 2023
N = 7;
A = rand(N,N,N,N,N);
p=ndims(A);
N=length(A);
% Method 1: generalization of cyclist's answer
step = polyval(ones(1,p),N);
idx = 1:step:N^p;
A(idx)
ans = 1×7
0.4728 0.2804 0.8097 0.9442 0.5680 0.1666 0.9129
% Method 2
c = repmat({1:N}, [1,p]);
idx = sub2ind(size(A), c{:});
A(idx)
ans = 1×7
0.4728 0.2804 0.8097 0.9442 0.5680 0.1666 0.9129

Categorías

Más información sobre Operating on Diagonal Matrices en Help Center y File Exchange.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by