Diagonal sums with non-zero elements

3 Ansichten (letzte 30 Tage)
Ingrid Wilson
Ingrid Wilson am 2 Mai 2022
Hello,
I have a matrix A, and have computed all possible (n factorial) permutations of this matrix. Next, I want to compute the sum of the diagonals of the permuted matrices containing non-zero elements. I've written a nested for loop to check for non-zero elements, and then, if there are no zero-elements, I want to save the diagonal sum in "diag". But it saves diagonal sums that still contain zero-elements.
All permutations of matrix A, with non-zeros on the diagonal, have constant diagonal sum 1.6. This means that if the code works, it should only find diagonals with sum 1.6
%define A
A = [0 0.4 0.3 0.3; 0 0 0.5 0.5; 0.5 0.3 0 0.2; 0.5 0.3 0.2 0];
[n,n] = size(A);
%find all permutations of A
B = reshape(A(:,flipud(perms(1:4)).'),n,n,factorial(n));
%compute diagonal sums with non-zero elements
diag = zeros(1, factorial(n));
for i = 1:factorial(n)
for j=1:n
if B(j,j,i) == 0
break
end
diag(1,i) = trace(B(:,:,i));
end
end
diag

Akzeptierte Antwort

Riccardo Scorretti
Riccardo Scorretti am 2 Mai 2022
Bearbeitet: Riccardo Scorretti am 2 Mai 2022
Hi Ingrid,
I guess you mean you want to compute te sum of the diagonals of the permuted matrices containing all non-zero elements. In this case I would program like that:
%define A
A = [0 0.4 0.3 0.3; 0 0 0.5 0.5; 0.5 0.3 0 0.2; 0.5 0.3 0.2 0];
You wrote: [n,n] = size(A). This is weird (for me), I would rather program like that:
[n, m] = size(A); % ***
assert(n == m, 'The matrix A must be square!') % ***
%find all permutations of A
B = reshape(A(:,flipud(perms(1:4)).'),n,n,factorial(n));
I need to use the built-in function diag, so I had to rename diag to diag_
%compute diagonal sums with non-zero elements
diag_ = zeros(1, factorial(n)); % diag "shades" a function with the same name
for i = 1:factorial(n)
if any(diag(B(:,:,i)) == 0) , continue ; end
diag_(1,i) = trace(B(:,:,i));
end
diag_'
ans = 24×1
0 0 0 0 0 0 0 0 0 1.6000
The error in your program was here:
%define A
A = [0 0.4 0.3 0.3; 0 0 0.5 0.5; 0.5 0.3 0 0.2; 0.5 0.3 0.2 0];
[n,n] = size(A);
%find all permutations of A
B = reshape(A(:,flipud(perms(1:4)).'),n,n,factorial(n));
%compute diagonal sums with non-zero elements
diag = zeros(1, factorial(n));
for i = 1:factorial(n)
for j=1:n
if B(j,j,i) == 0
Consider the case: B(:,:,j) = [1 0 0 0 ; 0 2 0 0 ; 0 0 0 0 ; 0 0 0 0]. In the first two iterations B(j,j,i) ~= 0, so you assign to diag(1,i) the trace of B(:,:,i). But at the third iteration, B(3,3,i) = 0: if you break the loop, it is mandatory to reset the value of diag(1,j) to 0 otherwise it will store the wrong result.
By the way, in this algorithm the computation of the trace is uselessly repeated many times.
diag(1,i) = 0; % THIS WAS MISSING
break
end
diag(1,i) = trace(B(:,:,i));
end
end
diag
diag = 1×24
0 0 0 0 0 0 0 0 0 1.6000 1.6000 0 0 0 0 0 1.6000 1.6000 0 0 0 0 1.6000 1.6000
Of course, both versions give exactly the same result.

Weitere Antworten (1)

Davide Masiello
Davide Masiello am 2 Mai 2022
Bearbeitet: Davide Masiello am 2 Mai 2022
%define A
A = [0 0.4 0.3 0.3; 0 0 0.5 0.5; 0.5 0.3 0 0.2; 0.5 0.3 0.2 0];
[n,n] = size(A);
%find all permutations of A
B = reshape(A(:,flipud(perms(1:4)).'),n,n,factorial(n));
%compute diagonal sums with non-zero elements
dgnl = [];
for i = 1:factorial(n)
if all(diag(B(:,:,i))~=0)
dgnl = [dgnl,sum(diag(B(:,:,i)))];
end
end
dgnl
dgnl = 1×6
1.6000 1.6000 1.6000 1.6000 1.6000 1.6000
Better not use diag as variable name, since it's already a MatLab in-built function.

Kategorien

Mehr zu Operating on Diagonal Matrices finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by