[英]How to graph adjacency matrix using MATLAB
我想创建一个图表,显示来自邻接矩阵的节点之间的连接,如下所示。
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自动为我找出一组坐标看起来没问题使用某种算法,所以我可以绘制看起来像顶部图片的东西。
提前致谢。
一种方法是使用某种静电排斥来编写自己的算法,就像你链接的文章一样。 可能可以在少于40行的Matlab中完成(似乎其他人已经尝试过 )。 但有时,使用外部工具比在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;
}
最后是一个image test.png (注意你的邻接矩阵列出了第一个项目与自身的连接,它显示为节点A的循环):
作为一个更复杂的例子,你可以在gplot
的文档中绘制一个gplot
球:
[A, XY] = bucky;
nodes = arrayfun(@(i) num2str(i), 1:size(A,1), 'uni', 0);
结果(注意布局是由neato完成的,它不使用XY
):
如果你的图是连通的,那么构造数组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找到
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.