对邻接矩阵的行和列进行排序以显示派系

时间:2015-05-29 16:01:13

标签: algorithm matlab adjacency-matrix clique-problem

我正在寻找一种重新排序技术,将邻接矩阵的连通分量组合在一起。

例如,我用蓝色和绿色两组进行了说明。最初,'1的条目分布在矩阵的行和列中。通过重新排序行和列,所有'1'可以位于矩阵的两个连续部分中,更清楚地显示蓝色和绿色分量。

Illustration

我不记得这种重新排序技术是什么。我搜索了邻接矩阵,集团,排序和重新排序的许多组合。

我发现的最接近的点击是

  1. symrcm将元素移近对角线,但不会创建组。

  2. Is there a way to reorder the rows and columns of matrix to create a dense corner, in R?专注于删除完全空的行和列

  3. 请提供此技术的通用名称,以便我可以更有效地谷歌,或指向我的Matlab功能的方向。

1 个答案:

答案 0 :(得分:2)

我不知道是否有更好的替代品可以直接给你结果,但这里有一种方法可以达到你的目的。

您的意见:

>> A

A =

 0     1     1     0     1
 1     0     0     1     0
 0     1     1     0     1
 1     0     0     1     0
 0     1     1     0     1

方法1

  

将第一行和第一列作为列掩码(maskCol)和      行掩码(maskRow)。

获取掩码,其中第一行和第一列中包含一些的值

maskRow = A(:,1)==1;
maskCol = A(1,:)~=1;

重新排列行(根据行掩码)

out = [A(maskRow,:);A(~maskRow,:)];

给出这样的东西:

out =

 1     0     0     1     0
 1     0     0     1     0
 0     1     1     0     1
 0     1     1     0     1
 0     1     1     0     1

重新排列列(根据列掩码)

out = [out(:,maskCol),out(:,~maskCol)]

给出了预期的结果:

out =

 1     1     0     0     0
 1     1     0     0     0
 0     0     1     1     1
 0     0     1     1     1
 0     0     1     1     1

只是检查指数是否应该是它们应该在哪里,或者你是否想要相应的重新安排指数;)

重新安排之前:

idx = reshape(1:25,5,[])

idx =

 1     6    11    16    21
 2     7    12    17    22
 3     8    13    18    23
 4     9    14    19    24
 5    10    15    20    25

重新安排后(我们之前做过的同样的过程)

outidx = [idx(maskRow,:);idx(~maskRow,:)];
outidx = [outidx(:,maskCol),outidx(:,~maskCol)]

<强>输出:

outidx =

 2    17     7    12    22
 4    19     9    14    24
 1    16     6    11    21
 3    18     8    13    23
 5    20    10    15    25

方法2

对于通用案例,如果您事先不知道矩阵,请按以下步骤查找maskRowmaskCol

  

使用的逻辑:

     
      
  1. 第一排。将其视为列掩码(maskCol)。

  2.   
  3. 对于第2行到最后一行,重复以下过程。

  4.   
  5. 将当前行与maskCol进行比较。

  6.   
  7. 如果任何一个值与maskCol匹配,则找到该元素       明智的逻辑OR并将其更新为新的maskCol

  8.   
  9. 重复此过程直至最后一行。

  10.   
  11. 在使用列时查找maskRow的相同过程       而是迭代。

  12.   

<强>代码:

%// If you have a square matrix, you can combine both these loops into a single loop.
maskCol = A(1,:);
for ii = 2:size(A,1)
    if sum(A(ii,:) & maskCol)>0 
        maskCol = maskCol | A(ii,:);
    end
end

maskCol = ~maskCol;

maskRow = A(:,1);
for ii = 2:size(A,2)
    if sum(A(:,ii) & maskRow)>0 
        maskRow = maskRow | A(:,ii);
    end
end

以下是尝试此操作的示例:

%// Here I removed some 'ones' from first, last rows and columns.
%// Compare it with the original example.
A = [0     0     1     0     1
     0     0     0     1     0
     0     1     1     0     0
     1     0     0     1     0
     0     1     0     0     1];

然后,重复之前遵循的程序:

out = [A(maskRow,:);A(~maskRow,:)];        %// same code used
out = [out(:,maskCol),out(:,~maskCol)];    %// same code used

结果如下:

>> out

out =

 0     1     0     0     0
 1     1     0     0     0
 0     0     0     1     1
 0     0     1     1     0
 0     0     1     0     1
  

注意:此方法可能适用于大多数情况,但在某些罕见情况下仍可能失败。

这是一个例子:

%// this works well.
A = [0     0     1     0     1    0
     1     0     0     1     0    0
     0     1     0     0     0    1
     1     0     0     1     0    0
     0     0     1     0     1    0
     0     1     0     0     1    1];

%// This may not
%// Second col, last row changed to zero from one
A = [0     0     1     0     1    0
     1     0     0     1     0    0
     0     1     0     0     0    1
     1     0     0     1     0    0
     0     0     1     0     1    0
     0     0     0     0     1    1];

为什么会失败?

  

当我们遍历每一行(以查找列掩码)时,例如,当我们移动到第3行时,没有cols与第一行匹配(当前maskCol)。因此,第3行(第2个元素)携带的唯一信息将丢失。

     

这可能是极少数情况,因为某些其他行可能仍包含相同的信息。见第一个例子。第三行中没有一个元素与第一行匹配,但由于最后一行具有相同的信息(第二个元素为1),因此它给出了正确的结果。只有在极少数情况下,可能会发生类似的情况。知道这个缺点仍然很好。

方法3

  

这是蛮力替代品。如果您认为前一种情况可能会失败,则可以应用。在这里,我们使用while loop运行前面的代码(查找行和col掩码),并使用更新的maskCol,以便找到正确的掩码。

<强>步骤:

 maskCol = A(1,:);
 count = 1;
 while(count<3)
     for ii = 2:size(A,1)
         if sum(A(ii,:) & maskCol)>0
             maskCol = maskCol | A(ii,:);
         end
     end
     count = count+1;
 end

采用上一个示例(前一个方法失败的地方)并使用和不使用while-loop

运行

没有蛮力:

>> out

out =

 1     0     1     0     0     0
 1     0     1     0     0     0
 0     0     0     1     1     0
 0     1     0     0     0     1
 0     0     0     1     1     0
 0     0     0     0     1     1

使用Brute-Forcing while循环:

>> out

out =

 1     1     0     0     0     0
 1     1     0     0     0     0
 0     0     0     1     1     0
 0     0     1     0     0     1
 0     0     0     1     1     0
 0     0     0     0     1     1

获得正确结果所需的迭代次数可能会有所不同。但是拥有一个好的数字是安全的。

祝你好运!