How to extract diagonal elements of multidimensional array ?

조회 수: 12 (최근 30일)
shuang Yang
shuang Yang 2023년 3월 23일
댓글: Mattia Marsetti 2023년 3월 24일
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
Stephen23
Stephen23 2023년 3월 23일
편집: Stephen23 2023년 3월 23일
@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 2023년 3월 24일
Thanks for the hint Stephen23, I'll try that
Regards

댓글을 달려면 로그인하십시오.

채택된 답변

the cyclist
the cyclist 2023년 3월 23일
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
the cyclist
the cyclist 2023년 3월 23일
Ah, I read your question too quickly, and didn't make my solution general enough. Glad you found it.
Stephen23
Stephen23 2023년 3월 23일
@shuang Yang: you could generalize that:
A(1:sum(N.^(0:ndims(A)-1):end)

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Bruno Luong
Bruno Luong 2023년 3월 23일
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

카테고리

Help CenterFile Exchange에서 Operating on Diagonal Matrices에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by