Wolfram mathematica GraphPlot图形中的顶点坐标规则和顶点列表

Wolfram mathematica GraphPlot图形中的顶点坐标规则和顶点列表,wolfram-mathematica,Wolfram Mathematica,是否有任何方法可以从GraphPlot生成的图形(完整形式或输入形式)中提取GraphPlot应用于顶点坐标规则的顶点顺序?我不想使用GraphUtilities函数VertexList。我也知道GraphCoordination,但这两个函数都与GraphPlot的图形输出一起工作,而不是与GraphPlot的图形输出一起工作 比如说, gr1 = {1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 1}; gp1 =

是否有任何方法可以从GraphPlot生成的图形(完整形式或输入形式)中提取GraphPlot应用于顶点坐标规则的顶点顺序?我不想使用GraphUtilities函数VertexList。我也知道GraphCoordination,但这两个函数都与GraphPlot的图形输出一起工作,而不是与GraphPlot的图形输出一起工作

比如说,

gr1 = {1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 1};
gp1 = GraphPlot[gr1, Method -> "CircularEmbedding", 
   VertexLabeling -> True];

Last@(gp1 /. Graphics[Annotation[x___], ___] :>  {x})
给出以下六个坐标对的列表:

顶点坐标->{2,0.866025},{1.5,1.73205},{0.5, 1.73205},{0,0.866025},{0.5,1.3469*10^-10},{1.5,0}

我如何知道哪条规则适用于哪一个顶点,我能确定这是正确的吗 与VertexList[gr1]给出的相同

比如说

 Needs["GraphUtilities`"];
gr2 = SparseArray@ 
      Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]];

    VertexList[gr2]
VertexList@
 SparseArray[
  Map[# -> 1 &, EdgeList[{2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6}]], {6, 6}]
给出{1,2,3,4,5}

但是

    gp2 = GraphPlot[gr2, VertexLabeling -> True, 
      VertexCoordinateRules -> 
       Thread[VertexList[gr1] -> 
         Last@(gp1 /. Graphics[Annotation[x___], ___] :>  {x})[[2]]]];
Last@(gp2 /. Graphics[Annotation[x___], ___] :>  {x})
给出六个坐标集:

顶点坐标->{2,0.866025},{1.5,1.73205},{0.5, 1.73205},{0,0.866025},{0.5,1.3469*10^-10},{1.5,0}

例如,如何为gr2的顶点坐标表提取正确的顶点列表

(例如,我知道在生成gr2后,我可以通过使用VertexList进行纠正,如下所示)

{1,2,3,4,5,6}

但我需要的信息似乎出现在GraphPlot图形中:我如何才能获得它

(我将图形转换为邻接矩阵的原因是,正如Wolfram的Carl Woll所指出的,它允许我包括一个“孤立”节点,如gp2中所示)


如果执行
FullForm[gp1]
您将获得一系列输出,我不会在这里发布。在输出的开始处,您会发现一个
图形复合体[]
。本质上,这是一个点列表,然后是这些点的使用列表。因此,对于图形
gp1
,图形复合体的开头是:

GraphicsComplex[
 List[List[2., 0.866025], List[1.5, 1.73205], List[0.5, 1.73205], 
  List[0., 0.866025], List[0.5, 1.3469*10^-10], List[1.5, 0.]], 
 List[List[RGBColor[0.5, 0., 0.], 
   Line[List[List[1, 2], List[2, 3], List[3, 4], List[4, 5], 
     List[5, 6], List[6, 1]]]],
第一个最外层列表定义了6个点的位置。第二个最外面的列表使用第一个列表中的点数定义了这些点之间的一组线。如果你玩这个,可能更容易理解

编辑:针对OP的评论,如果我执行:

FullForm[GraphPlot[{3 -> 4, 4 -> 5, 5 -> 6, 6 -> 3}]]
我明白了


顶点位置列表是GraphicsComplex中的第一个列表。稍后在完整表单中,您可以看到Mathematica添加工具提示的列表,以使用原始边列表中提供的标识符标记顶点。由于您现在看到的是描述图形的代码,因此顶点和将要绘制的内容之间只有间接关系;这些信息都在那里,但并不完全可以直接打开包装。

使用顶点标签,一种方法是获取标签的坐标。请注意,GraphPlot的输出在GraphicsComplex中,其中坐标别名的坐标作为第一个标签,您可以将其作为

points = Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // First
查看
FullForm
您将看到标签位于文本对象中,将它们提取为

labels = Cases[gp1, Text[___], Infinity]
实际的标签似乎有两层深,因此

actualLabels = labels[[All, 1, 1]];
坐标别名是第二个参数,因此可以将其作为

 coordAliases = labels[[All, 2]]
 actualCoords = points[[coordAliases]]
实际坐标是在GraphicsComplex中指定的,因此我们将它们作为

 coordAliases = labels[[All, 2]]
 actualCoords = points[[coordAliases]]
坐标列表和标签列表之间有1-1对应关系,所以可以使用线程将它们作为“标签”->坐标对列表返回

这是一个函数,所有这些都在一起

getLabelCoordinateMap[gp1_] := 
 Module[{points, labels, actualLabels, coordAliases, actualCoords},
  points = 
   Cases[gp1, GraphicsComplex[points_, __] :> points, Infinity] // 
    First;
  labels = Cases[gp1, Text[___], Infinity];
  actualLabels = labels[[All, 1, 1]];
  coordAliases = labels[[All, 2]];
  actualCoords = points[[coordAliases]];
  Thread[actualLabels -> actualCoords]
  ];
getLabelCoordinateMap[gp1]
并不是说这只适用于带标签的GraphPlot。对于没有标签的图形对象,您可以尝试从其他图形对象中提取,但根据从中提取贴图的对象,您可能会得到不同的结果,因为似乎存在错误,有时会将线端点和顶点标签指定给不同的顶点。我已经报告了。解决此问题的方法是,始终为VertexCoordinateList使用显式顶点->坐标规范,或者始终使用“邻接矩阵”表示。这里有一个不一致的例子

graphName = {"Grid", {3, 3}};
gp1 = GraphPlot[Rule @@@ GraphData[graphName, "EdgeIndices"], 
  VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"], 
  VertexLabeling -> True]
gp2 = GraphPlot[GraphData[graphName, "AdjacencyMatrix"], 
  VertexCoordinateRules -> GraphData[graphName, "VertexCoordinates"], 
  VertexLabeling -> True]
顺便说一句,这里是我用来在邻接矩阵和边规则表示之间转换的实用函数

edges2mat[edges_] := Module[{a, nodes, mat, n},
   (* custom flatten to allow edges be lists *)

   nodes = Sequence @@@ edges // Union // Sort;
   nodeMap = (# -> (Position[nodes, #] // Flatten // First)) & /@ 
     nodes;
   n = Length[nodes];
   mat = (({#1, #2} -> 1) & @@@ (edges /. nodeMap)) // 
     SparseArray[#, {n, n}] &
   ];
mat2edges[mat_List] := Rule @@@ Position[mat, 1];
mat2edges[mat_SparseArray] := 
 Rule @@@ (ArrayRules[mat][[All, 1]] // Most)


V12.0.0

尝试
转置{First/}[[1,1,2,1,2,1]],#[[1,1,1]}&[gp1]
这只在标签对应于GraphicsComplex对象中的坐标别名位置时起作用,对于graph{2->1}则不起作用。好的,我明白你的观点。但是如果我尝试完整形式的[GraphPlot[{3->4,4->5,5->6,6->3}],我会看到列表[1,2]、列表[2,3]、列表[3,4]、列表[4,1],而不是顶点列表。顺便说一句,用边列表表示断开连接的图的另一种方法是每个节点都有I->I边。在绘图过程中可能需要SelfLoopStyle->None是的,没错!在我了解卡尔·沃尔的方法之前,我曾经用过它。我有时需要显示自循环,并且(目前)更喜欢邻接矩阵方法。我认为这两种方法都很有用——如果您正在检查图形或进行不改变顶点数量的修改,邻接矩阵更方便,而edgelist在您需要将图形拆分为两个顶点时更好谢谢!我感谢你的帮助。我从你的回答中学到了很多。你的edges2mat也是个好东西。