从最近邻搜索创建邻接矩阵。 (将邻接表转换为邻接矩阵)- Matlab
Create adjacency matrix from nearest neighbour search. (convert adjacency list to adjacency matrix) - Matlab
我有一个矩阵 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 列的每行非零元素的总数。执行此操作后,对于邻接矩阵的行,您将复制点号的次数与有多少次一样多每行的非零元素。函数 repelem
非常适合为您执行此操作。列索引只是第二到第五列 删除 所有零元素。你如何做到这一点是首先 转置 矩阵导致索引第二到第五列,然后使用 logical
索引矩阵删除零条目。这样做会以列优先方式展开您的向量,这就是为什么在执行此操作之前需要转置的原因。执行此操作后,您可以创建行和列访问索引,以便将它们输入到 sparse
中,就像您链接的 post 一样。
假设你的矩阵存储在 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 on a custom implementation of repelem
here: Repeat copies of array elements: Run-length decoding in MATLAB
的这个答案
一种快速简单的技巧:
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. 要强制无向-ness,您可以简单地在for循环体中添加另一条语句:
adjMat(nonzeros(A(ind,2:end)),ind) = 1;
这将确保邻接矩阵是对称的,这是无向图的一个特征。
我有一个矩阵 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 列的每行非零元素的总数。执行此操作后,对于邻接矩阵的行,您将复制点号的次数与有多少次一样多每行的非零元素。函数 repelem
非常适合为您执行此操作。列索引只是第二到第五列 删除 所有零元素。你如何做到这一点是首先 转置 矩阵导致索引第二到第五列,然后使用 logical
索引矩阵删除零条目。这样做会以列优先方式展开您的向量,这就是为什么在执行此操作之前需要转置的原因。执行此操作后,您可以创建行和列访问索引,以便将它们输入到 sparse
中,就像您链接的 post 一样。
假设你的矩阵存储在 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 on a custom implementation of repelem
here: Repeat copies of array elements: Run-length decoding in MATLAB
一种快速简单的技巧:
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. 要强制无向-ness,您可以简单地在for循环体中添加另一条语句:
adjMat(nonzeros(A(ind,2:end)),ind) = 1;
这将确保邻接矩阵是对称的,这是无向图的一个特征。