How to move larger values close to matrix diagonal in a correlation matrix

后端 未结 2 1279
广开言路
广开言路 2021-01-06 09:29

I have a correlation matrix X of five elements(C1,C2,C3,C4,C5)

      C1    C2    C3     C4   C5  

 C1    *     1     0     1     0
 C2    1     *     0              


        
相关标签:
2条回答
  • 2021-01-06 10:00

    What you're looking for is probably the reverse Cuthill-McKee algorithm (RCM), which pretty much does what you want: for a given matrix it finds a permutation that tends to have its non-zero elements closer to the diagonal. There's a built-in function symrcm in MATLAB that does just that.

    So assuming that X is your matrix, you can do the following:

    p = symrcm(X);
    Xnew = X(p, p);
    

    Xnew is the new reordered matrix, and p is the new row/column order.

    Example

    Let's create a matrix first:

    X = [10 0 0 7 0; 3 20 0 0 11; 0 0 30 0 29; 12 7 0 40 0; 0 33 0 0 50]
    

    Now let's reorder it:

    p = symrcm(X);
    Xnew = X(p, p)
    

    The result is:

    Xnew =    
        40    12     7     0     0
         7    10     0     0     0
         0     3    20    11     0
         0     0    33    50     0
         0     0     0    29    30
    

    Seems right.

    0 讨论(0)
  • 2021-01-06 10:00
    A = [1 0  0 1 0;
         0 1  0 0 1;
         0 0  1 0 1;
         1 1  0 1 0;
         0 1  0 0 1]; 
    N = length(A);
    switched = false;
    
    %%
    % Calculate initial Global Energy
    disp(A);
    global_energy = 0;
    for l = 1:N
        for m = 1:N
            if(A(l,m))
                global_energy = global_energy + (l-m)^2/2;
            end
        end
    end
    disp(global_energy); 
    
    counter = 0;
    counter_cutoff = 10000000000;
    while(true)
        switched = false;
        counter = counter + 1;
        for i = 1:N
            for j = i+1:N        
                current_metric = 0; % Calculate metric of row i and j with columns i and j
                permuted_metric = 0; % Calculate metric if they were permuted        
                % Row i
                for k = 1:N
                    if(k ~= i && k ~= j && A(i,k))
                        current_metric = current_metric + (i-k)^2/2;
                        permuted_metric = permuted_metric + (j-k)^2/2;
                    end
                end
                % Row j
                for k = 1:N
                    if(k ~= i && k ~= j && A(j,k))
                        current_metric = current_metric + (j-k)^2/2;
                        permuted_metric = permuted_metric + (i-k)^2/2;
                    end
                end
                % Col i
                for k = 1:N
                    if(k ~= i && k ~= j && A(k,i))
                        current_metric = current_metric + (i-k)^2/2;
                        permuted_metric = permuted_metric + (j-k)^2/2;
                    end
                end
                % Col j 
                for k = 1:N
                    if(k ~= i && k ~= j && A(k,j))
                        current_metric = current_metric + (j-k)^2/2;
                        permuted_metric = permuted_metric + (i-k)^2/2;
                    end
                end
    
                % If permuted metric is less, swap columns and rows - set switched to true 
                if(permuted_metric < current_metric)
                    switched = true; % there was at least one switch
                    % Now switch rows and columns
                    % Switch columns first
                    A(:,[i j]) = A(:,[j i]);
                    % Now switch rows
                    A([i j],:) = A([j i],:);
                end
            end
        end
        if(~switched || counter > counter_cutoff)
            % All permutations did not lead to a switching of rows and columns
            break;
        end
    end
    
    % Calculate final Global Energy
    disp(A);
    global_energy = 0;
    for l = 1:N
        for m = 1:N
            if(A(l,m))
                global_energy = global_energy + (l-m)^2/2;
            end
        end
    end
    disp(global_energy); 
    

    Terminal:

     1     0     0     1     0
     0     1     0     0     1
     0     0     1     0     1
     1     1     0     1     0
     0     1     0     0     1
    
    22
    
     1     1     0     0     0
     1     1     1     0     0
     0     0     1     1     0
     0     0     1     1     0
     0     0     0     1     1
    
     3
    
    0 讨论(0)
提交回复
热议问题