【问题标题】:How to graph adjacency matrix using MATLAB如何使用 MATLAB 绘制邻接矩阵图
【发布时间】:2014-12-07 05:26:54
【问题描述】:

我想创建一个图,显示来自如下邻接矩阵的节点之间的连接。

gplot 似乎是最好的工具。但是,为了使用它,我需要传递每个节点的坐标。问题是我不知道坐标应该在哪里,我希望该函数能够为我找出一个好的布局。

例如,这是我使用以下任意坐标的输出:

 A = [1 1 0 0 1 0;
      1 0 1 0 1 0;
      0 1 0 1 0 0;
      0 0 1 0 1 1;
      1 1 0 1 0 0;
      0 0 0 1 0 0];

 crd = [0 1;
        1 1;
        2 1;
        0 2;
        1 2;
        2 2];

 gplot (A, crd, "o-");

这很难阅读,但是如果我稍微调整一下坐标并将它们更改为以下内容,它就会变得更具可读性。

   crd = [0.5 0;
         0 1;
         0 2;
         1 2;
         1 1;
         1.5 2.5];

我不期望完美优化的坐标或任何东西,但是我如何告诉 MATLAB 自动为我找出一组使用某种 algorithm 看起来不错的坐标,这样我就可以绘制看起来像顶部的东西图片。

提前致谢。

【问题讨论】:

    标签: matlab matrix octave graph-theory adjacency-matrix


    【解决方案1】:

    从 R2015b 开始,MATLAB 现在拥有一套图形和网络算法。对于这个例子,你可以create an undirected graph object 然后使用overloaded plot function 绘制它:

    % Create symmetric adjacency matrix
    A = [1 1 0 0 1 0;
         1 0 1 0 1 0;
         0 1 0 1 0 0;
         0 0 1 0 1 1;
         1 1 0 1 0 0;
         0 0 0 1 0 0];
    % Create undirected graph object
    G = graph(A);
    % Plot
    plot(G);
    

    【讨论】:

    • 谢谢!我在 R2016b 上对此进行了测试,当我发布这个问题时,它就像我想要的那样工作。很高兴看到它在不需要第三方解决方案的情况下得到解决。
    【解决方案2】:

    一种方法是使用您链接的论文中的某种静电排斥来编写您自己的算法。可能可以在不到 40 行的 Matlab 中完成(似乎others have tried)。但有时,使用外部工具比在 Matlab 中做所有事情要好。绘制图表的最佳工具可能是Graphviz,它附带了一套用于绘制不同样式图表的工具。对于无向图,使用的是neato。我不知道它使用哪种算法来分配节点,但我想它与您论文中的算法相似(其中一个参考文献甚至提到了 Graphviz!)。

    这些工具的输入是一种非常简单的文本格式,使用 Matlab 很容易生成。示例(这适用于 linux,您可能需要在 windows 上进行一些更改):

    % adjacency matrix
    A = [1 1 0 0 1 0;
         1 0 1 0 1 0;
         0 1 0 1 0 0;
         0 0 1 0 1 1;
         1 1 0 1 0 0;
         0 0 0 1 0 0];
    
    % node labels, these must be unique
    nodes = {'A', 'B', 'C', 'D', 'E', 'F'};
    
    n = length(nodes);
    assert(all(size(A) == n))
    
    % generate dot file for neato
    fid = fopen('test.dot', 'w');
    fprintf(fid, 'graph G {\n');
    for i = 1:n
        for j = i:n
            if A(i, j)
                fprintf(fid, '    %s -- %s;\n', nodes{i}, nodes{j});
            end
        end
    end
    fprintf(fid, '}\n');
    fclose(fid);
    
    % render dot file
    system('neato -Tpng test.dot -o test.png')
    

    生成文件 test.dot

    graph G {
        A -- A;
        A -- B;
        A -- E;
        B -- C;
        B -- E;
        C -- D;
        D -- E;
        D -- F;
    }
    

    最后是一张图片 test.png(请注意,您的邻接矩阵列出了第一项与其自身的连接,在节点 A 处显示为循环):

    作为一个更复杂的示例,您可以像gplot 的文档中那样绘制一个巴基球:

    [A, XY] = bucky;
    nodes = arrayfun(@(i) num2str(i), 1:size(A,1), 'uni', 0);
    

    with result(注意布局是neato做的,没有使用XY):

    【讨论】:

      【解决方案3】:

      如果您的图形是连接的,则构造数组 xy 以传递给 gplot 的一种方法是 v(:,[2 3]) 其中 v 是拉普拉斯矩阵的特征向量矩阵,从最小特征值到最大排序。所以我们可以这样做:

      L=diag(sum(A))-A;
      [v,~]=eig(L);
      xy=v(:,[2 3])
      gplot(A,xy)
      

      或者这样:

      L=diag(sum(A))-A;
      [v,~]=eigs(L,3,'SM')
      xy=v(:,[2 1])
      gplot(A,xy)
      

      第二个应该更有效,特别是如果 A 很大。

      这将在正常情况下创建一个不错的情节。这不能保证有效;特别是,不能保证为不同的节点分配不同的坐标。但通常它工作得很好。

      这背后的一些理论可以在https://arxiv.org/pdf/1311.2492.pdf找到

      【讨论】:

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