Solve / Convert Upper Triangular Matrix to MATLAB

I have an upper triangular matrix (without a diagonal) defined by the formula:

M = [0 3 2 2 0 0; 0 0 8 6 3 2; 0 0 0 3 2 1; 0 0 0 0 2 1; 0 0 0 0 0 0] 

The resulting matrix should look like this:

 R = [0 0 0 0 0 0; 0 2 0 0 0 0; 2 3 1 0 0 0; 2 6 2 1 0 0; 3 8 3 2 0 0] 

Since I could not find a simple explanation that describes my purpose, I tried to visualize it with an image:

enter image description here

I already tried many different combinations of rot90 , transpose , flipud , etc., but I could not find the correct transformation that gives me the matrix R

EDIT:

The rows of the matrix M not always sorted, as in the above example. For another matrix M_2 :

 M_2 = [0 2 3 1 0 0; 0 0 3 6 3 9; 0 0 0 1 2 4; 0 0 0 0 2 6; 0 0 0 0 0 0] 

the resulting matrix R_2 should be as follows:

 R_2 = [0 0 0 0 0 0; 0 9 0 0 0 0; 1 3 4 0 0 0; 3 6 2 6 0 0; 2 3 1 2 0 0] 

Again visualization below:

enter image description here

+4
source share
3 answers

EDIT: Inspired by the hint from @Dan's comment, it can be simplified further to

 R = reshape(rot90(M), size(M)); 

Original answer:

It should be an easy way to do it.

 F = rot90(M); R = F(reshape(1:numel(M), size(M))) 

which returns

 R = 0 0 0 0 0 0 0 2 0 0 0 0 2 3 1 0 0 0 2 6 2 1 0 0 3 8 3 2 0 0 

The idea is that when you rotate the matrix, you get

 >> F = rot90(M) F = 0 2 1 1 0 0 3 2 2 0 2 6 3 0 0 2 8 0 0 0 3 0 0 0 0 0 0 0 0 0 

which is a 6 by 5 matrix. If you are considering linear indexing over F, then the corresponding indices

 >> reshape(1:30, size(F)) 1 7 13 19 25 2 8 14 20 26 3 9 15 21 27 4 10 16 22 28 5 11 17 23 29 6 12 18 24 30 

where the elements 6, 11, 12, 16, 17, 18 and ... are now null if you change this to a 5 by 6 matrix, which you get

 >> reshape(1:30, size(M)) 1 6 11 16 21 26 2 7 12 17 22 27 3 8 13 18 23 28 4 9 14 19 24 29 5 10 15 20 25 30 

Now those elements that correspond to zero values ​​are on top, exactly what we wanted. Therefore, passing this index array to F , we get the desired R

+5
source

Without relying on order (just by turning the colored bars and pushing them to the bottom).

First solution: note that it does not work if there are zeros between the "data" values ​​(for example, if M(1,3) is 0 in the above example). If there may be zeros, see the second solution below:

 [nRows nCols]= size(M); R = [flipud(M(:,2:nCols).') zeros(nRows,1)]; [~, rowSubIndex] = sort(~~R); index = sub2ind([nRows nCols],rowSubIndex,repmat(1:nCols,nRows,1)); R = R(index); 

Second solution: works even if the data has zeros:

 [nRows nCols]= size(M); S = [flipud(M(:,2:nCols).') zeros(nRows,1)]; mask = 1 + fliplr(tril(NaN*ones(nRows, nCols))); S = S .* mask; [~, rowSubIndex] = sort(~isnan(S)); index = sub2ind([nRows nCols],rowSubIndex,repmat(1:nCols,nRows,1)); R = S(index); R(isnan(R)) = 0; 
+4
source

Alternative using loops:

 [nRows nCols]= size(M); R = zeros(nRows,nCols); for n = 1:nRows R((n+1):nCols,n)=fliplr(M(n,(n+1):nCols)); end 
+1
source

Source: https://habr.com/ru/post/1497967/


All Articles