【问题标题】:Create adjacency matrix from nearest neighbour search. (convert adjacency list to adjacency matrix) - Matlab从最近邻搜索创建邻接矩阵。 (将邻接表转换为邻接矩阵) - Matlab
【发布时间】:2016-06-10 13:51:58
【问题描述】:

我有一个矩阵2000x5,第一列是点号,第 2-5 列是 4 个邻居(如果没有邻居,则为 0)。有没有一种有效的方法来创建一个邻接矩阵?

1   129 0   65  0
2   130 0   66  85
3   131 169 67  0
4   132 170 68  87
5   133 0   69  81
6   134 0   70  82
7   135 173 71  83
8   136 174 72  84
9   137 161 73  0
10  138 162 74  93
11  139 163 75  0
12  140 164 76  95
13  141 165 77  89
14  142 166 78  90
15  143 167 79  91
16  144 168 80  92
17  145 0   81  65
18  146 0   82  66
....

我找到了以下线程,其中仅对一个邻居进行了解释,但我不确定如何将其用于多个邻居。 matlab adjacency list to adjacency matrix

我将非常感谢任何帮助。

【问题讨论】:

  • 所以要遵循矩阵的格式,给定第一列中描绘的点编号,第 2 - 5 列会告诉您与所述点相邻的点?
  • 好的,你需要停止一遍又一遍地重复同一个问题。您目前有 5 个关于同一个问题的问题。如果您需要澄清您的问题,请编辑它而不是打开一个新问题。
  • 我同意这些问题是相似的(因为我仍在研究这个问题),但它们绝不是相互重复的。但我以后会尽量避免的

标签: matlab matrix adjacency-matrix


【解决方案1】:

快速简单的技巧:

adjMat = zeros(size(A,1));
for ind = 1:size(A,1)
    % Flag 1 on each row 'ind' at the indices mentioned in col 2-5
    adjMat(ind, nonzeros(A(ind,2:end))) = 1;
end

由于您提到使用最近邻搜索,很可能应该完全填充邻接表以产生无向图,即如果第 1 行有 20 作为邻居,则第 20 行很可能有 1作为邻居。

但是从技术上讲,这将产生一个与邻接列表完全等效的邻接矩阵,假设它本身没有任何内容。

示例:

对于邻接列表

A = [1 2 3; 2 0 1; 3 1 4; 4 5 3; 5 4 0]

A =

 1     2     3
 2     0     1
 3     1     4
 4     5     3
 5     4     0

结果是:

adjMat =

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

P.S.要强制无向性,您可以简单地在for循环体中添加另一个语句:

adjMat(nonzeros(A(ind,2:end)),ind) = 1;

这将确保邻接矩阵是对称的,这是无向图的一个特征。

【讨论】:

  • 良好的规范方法。使用2:end 进行索引时,可以删除方括号。这里是多余的。此外,请在 zeros 调用的末尾添加一个分号,这样您就不会将该分配回显到命令窗口。
  • @rayryeng:是的,不知道我是怎么错过的。我已经做出了改变。谢谢你的建议:)
  • 感谢您的回答。我仍在同一领域工作,只是再次阅读该帖子-您的 P.S. 到底是什么意思。笔记 ?以哪种方式对称?如果你能用一句话解释我会很高兴!
  • @KiW,我已经更新了 P.S.笔记。对误导性陈述感到抱歉。简而言之,如果您的图是有向的,那么(比如说)节点 A 可能连接到节点 B,但 B 没有连接到 A。如果您的邻接列表属于这种类型,但您想强制使你的图是无向的(如果 A 连接 B,B 也应该连接 A),你需要使邻接矩阵对称。想想邻接矩阵描述了什么,你就应该明白了。
【解决方案2】:

首先,我将假设邻接列表是无向的。无论如何,去多个邻居那里并不是那么遥不可及。您首先需要做的是检测每行从第 2 列到第 5 列的非零元素总数。完成此操作后,对于邻接矩阵的行,您将复制点数尽可能多的次数每行的非零元素。 repelem 函数非常适合为您执行此操作。列索引将只是第二到第五列删除所有零元素。如何做到这一点是首先 转置 矩阵导致索引第二到第五列,然后使用logical 索引矩阵删除零条目。这样做将以列为主的方式展开您的向量,这就是为什么在执行此操作之前需要转置。完成此操作后,您可以创建行和列访问索引,以便可以将这些索引输入到sparse,就像您链接的帖子一样。

假设你的矩阵存储在A,你会做这样的事情。这也假设连接节点的每个权重都是1:

% Find total number of non-zero elements per row, skipping first column
non_zero = sum(A(:,2:end) ~= 0, 2);

% Create row indices
rows = repelem(A(:,1), non_zero);

% Create column indices
cols = A(:,2:end).';    
cols = cols(cols ~= 0);

% Create adjacency matrix
adj = sparse([rows; cols],[cols; rows], 1);

以上表示在sparse。如果您想要完整的数字版本,请使用 full 转换输出:

adj = full(adj);

如果你的图表是有向的

如果您有一个有向图而不是无向图,则上述对sparse 的调用会复制边,以便您创建与每个邻居之间的链接。如果您的图表实际上是定向的,那么您只需使用一次行和列索引,而不是上面代码中看到的两次:

% Create adjacency matrix
adj = sparse(rows, cols , 1);

测试用例

这是一个小测试用例,向您展示这是可行的。假设我的邻接列表如下所示:

>> A = [1 0 2 3; 2 4 0 0; 3 0 0 4]

A =

     1     0     2     3
     2     4     0     0
     3     0     0     4

邻接矩阵现在是:

>> full(adj)

ans =

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

看看上面的列表以及矩阵是如何填充的,我们可以验证这是正确的。


注意repelem

repelem 假设您拥有 MATLAB R2015a 或更高版本。如果你没有这个,你可以通过用户Divakar 来咨询这个答案,这里是repelem 的自定义实现:Repeat copies of array elements: Run-length decoding in MATLAB

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多