Diagonal sums with non-zero elements

2 views (last 30 days)
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

Accepted Answer

Riccardo Scorretti
Riccardo Scorretti on 2 May 2022
Edited: Riccardo Scorretti on 2 May 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.

More Answers (1)

Davide Masiello
Davide Masiello on 2 May 2022
Edited: Davide Masiello on 2 May 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.

Community Treasure Hunt

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

Start Hunting!