use*_*011 5 matlab matrix correlation
我有一个由五个元素组成的相关矩阵 X(C1,C2,C3,C4,C5)
C1 C2 C3 C4 C5
C1 * 1 0 1 0
C2 1 * 0 0 1
C3 0 0 * 1 1
C4 1 0 1 * 0
C5 0 1 1 0 *
Run Code Online (Sandbox Code Playgroud)
我想使用 MatLab 将尽可能多的非零单元移动到对角线附近,同时保持对角线单元为“*”。
例如,您可能会注意到以下矩阵中的列和行正在移动,而对角单元格为“*”。
C1 C4 C2 C5 C3
C1 * 1 1 0 0
C4 1 * 0 0 1
C2 1 0 * 1 0
C5 0 0 1 * 1
C3 0 1 0 1 *
Run Code Online (Sandbox Code Playgroud)
因为我想做聚类,所以我希望尽可能多的非零单元在移位后接近对角线。这是一个NP难题。
有谁知道MatLab中有什么函数可以实现这个功能吗?
您正在寻找的可能是反向 Cuthill-McKee 算法 (RCM),它几乎可以满足您的需求:对于给定的矩阵,它会找到一个排列,该排列往往使其非零元素更接近对角线。有一个内置函数symrcm
可以完成此任务。
因此,假设这X
是您的矩阵,您可以执行以下操作:
p = symrcm(X);
Xnew = X(p, p);
Run Code Online (Sandbox Code Playgroud)
Xnew
是新的重新排序的矩阵,并且p
是新的行/列顺序。
我们先创建一个矩阵:
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]
Run Code Online (Sandbox Code Playgroud)
现在让我们重新排序:
p = symrcm(X);
Xnew = X(p, p)
Run Code Online (Sandbox Code Playgroud)
结果是:
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
Run Code Online (Sandbox Code Playgroud)
看来是对的。
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);
Run Code Online (Sandbox Code Playgroud)
终端:
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
Run Code Online (Sandbox Code Playgroud)