如何将边缘列表转换为邻接矩阵

时间:2016-02-20 13:57:39

标签: matlab adjacency-matrix

我有这段代码

function adj=edgeL2adjj(e)
    Av = [e; fliplr(e)];
    nodes = unique(Av(:, 1:2)); % get all nodes, sorted
    adj = zeros(numel(nodes));   % initialize adjacency matrix
    % across all edges
    for i=1:size(Av,1)
        adj(nodes==Av(i,1),(nodes==Av(i,2))) = 1;
    end
end

将边缘列表转换为邻接矩阵但是如果我输入u=[8 5;1 4;3 5;6 7] 然后我将u分成两组[8 5;1 4][3 5,6 7]并在[3 5;6 7]上应用以前的代码我会得到一个7 x 7矩阵。
但我希望任何输入都有一个8 x 8矩阵。

2 个答案:

答案 0 :(得分:0)

你有一个7x7矩阵,因为numel(nodes)=7。实际上,u中不存在节点#2。我建议你给这个函数第二个输入,即你网络中的最大节点数(在这种情况下,8),并使用这样的输入参数而不是numel(nodes)预先分配邻接矩阵。或者,您也可以通过输入输入zeros()来预先分配numel(nodes)方阵,但输入u中的最大值。第一个选项将使您的代码更加健壮,只要第8个节点在输入u中,第二个选项将使您的代码更健壮。

此外,不需要fliplr():如果你的图是无向的(即,邻接矩阵是对称的),你可以依赖于for循环中的这种结构,而不需要{{1中的连接}}

这样的功能确实可以简化如下:

Av

如果输入function adj=edgeL2adjj(e) adj=zeros(max(max(e))); % initialize adjacency matrix % across all edges for i=1:size(e,1) adj(e(i,1),e(i,2))=1; adj(e(i,2),e(i,1))=1; end end 是您的矩阵:

e

此类代码返回

e= [8 5;1 4;3 5;6 7];

如您所见,您只是利用输入adj = 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 。最大值为8,因此您可以构建一个8x8方形矩阵。同样在for循环内部通过交换e中的列索引1和2,您将自动处理邻接矩阵的对称结构。最后,如果缺少节点,此代码会自动对您进行排序:实际上,如您所见,e中的第二行和第二列是全零,因为边缘列表中不存在节点#2 { {1}}。

注意:我不建议拆分输入边缘列表。通过这种方式,您将丢失有关您的网络的所有全局信息。实际上,你将拥有(让我们说)两个“子网络”,你后来必须连接这两个“子网络”(就邻接矩阵而言)。也就是说,如果将adj拆分为两个子矩阵,则会有两个邻接矩阵。通过在我的答案中考虑现在的代码,第一个矩阵将是8x8而第二个矩阵将是7x7,因为e

答案 1 :(得分:0)

如果可以,我想为您的问题提供一个完全不同的解决方案,这样可以避免遍历所有边缘(总是一个好主意,以避免MATLAB中的循环!)。

由于您拥有所有行索引和列索引,因此基本上已经的边列表指定了一个(尽管是稀疏的)矩阵。您可以像这样简单地分配矩阵:

function adj = edgeL2adjj(e)

    r = e(:,1);
    c = e(:,2);
    vals = ones(size(r));

    % maximum node index determines matrix dimensions
    n_nodes = max(e(:));

    % create sparse matrix
    adj = sparse(r, c, vals, n_nodes, n_nodes);

    % if really necessary, you can just convert it to a full matrix
    adj = full(adj);

end

如果你知道你总是希望图形具有相同的尺寸,即使你只使用部分边作为函数的输入,你也可以将n_nodes作为输入而不是从e

function adj = edgeL2adjj(e, n_nodes)