Wolfram mathematica Mathematica规则和GraphEdit返回的对象之间有什么区别?

Wolfram mathematica Mathematica规则和GraphEdit返回的对象之间有什么区别?,wolfram-mathematica,mathematical-expressions,Wolfram Mathematica,Mathematical Expressions,这实际上是一个双重问题。首先:作为一个有OO编程背景的人,我觉得Mathematica使用列表作为一切的基础有点令人讨厌。以下是mathematica程序员(据我所知)如何定义图形: graph={{1, 2, 3, 4, 5}, {1->2, 2->4, 4->4, 4->5}}; 然后程序员就必须记住这一点 graph[[1]] 指顶点和顶点的列表 graph[[2]] 指边列表(在本例中定义为一组规则) 所以,我在学习Mathematica中的规则,我看到了

这实际上是一个双重问题。首先:作为一个有OO编程背景的人,我觉得Mathematica使用列表作为一切的基础有点令人讨厌。以下是mathematica程序员(据我所知)如何定义图形:

graph={{1, 2, 3, 4, 5}, {1->2, 2->4, 4->4, 4->5}};
然后程序员就必须记住这一点

graph[[1]] 
指顶点和顶点的列表

graph[[2]]
指边列表(在本例中定义为一组规则)

所以,我在学习Mathematica中的规则,我看到了一个让我的数据结构更面向对象的感觉的机会。我选择定义一个类似以下内容的图形:

graph={Verts->{1,2,3,4,5}, Edges->{1->2, 2->4, 4->4, 4->5}};
然后通过引用顶点和边(分别)

但是,如果其他Mathematica文件在某个地方将顶点或边定义为全局变量,则这可能会产生奇怪的副作用,因为规则的左侧不是标识符,而是对象本身

所以问题1是这样的:对于创建Mathematica数据结构来说,这是一个好的实践,还是一个坏的实践?我这样做的原因之一是我可以附加任意属性,比如颜色:

AppendTo[graph, Colors->{Red, Red, Blue, Red, Red}]; (* Labels ea. vert with a color *)
我的函数不需要知道特定属性添加的确切顺序。例如,您可能有一个函数GetColor,其定义如下:

GetColor[graph_, vertIdx_]:=(Colors/.graph)[[vertIdx]];
这是更可取的,因为我可能并不总是想要有颜色信息的图形数据结构,所以不想在列表中为颜色信息保留一个点(如graph[[3]])

第二:我看到GraphEdit返回类似于我上面描述的规则的内容。例如,如果我执行(并绘制图形)

我得到如下输出:

Graph->{1->2,3->3,4->4,5->4}
这看起来像一条规则!所以我试着这样做:

Graph/.g[[2]]
期待

{1->2,3->3,4->4,5->4}
返回。但是,输出只是

Graph
但如果我改为执行

g[[2]][[1]] /. g[[2]]
我得到了预期的输出

{1->2,3->3,4->4,5->4}
这意味着g[[2]]实际上是一条规则,但出于某种原因,g[[2][[1]](如果执行,则打印图形)与键入图形不同。那么g[[2][[1]]到底是什么

它似乎是一个真正的标识符,如果是这样,我想用它来解决上面问题1的问题。有人知道其中的区别,或者如何在Mathematica中输入一个和另一个


我在文档中找不到任何与此相关的内容(或在线)。谢谢。

我使用InputForm[]找到了问题2的答案(今天之前不知道该函数)

返回

"Graph"
因此,似乎可以避免问题1中的问题,而他们如何定义GraphEdit的答案是使用规则中的字符串作为“标识符”


问题1可以修改为:这是一个好的实践吗?

我使用InputForm[]找到了问题2的答案(今天之前不知道该函数)

返回

"Graph"
因此,似乎可以避免问题1中的问题,而他们如何定义GraphEdit的答案是使用规则中的字符串作为“标识符”


问题1可以修改为:这是一个好的实践吗?

我想知道你使用的是什么版本的Mathematica

图论更紧密地集成到V8的核心中,这在很大程度上是一种改进。您可以以面向对象程序员可能喜欢的方式与图形交互。在V8中,我将这样执行您的示例:

g = Graph[Range[5], {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5}];
g = SetProperty[{g, 3}, VertexStyle -> Red]
然后,我可以这样查询属性:

PropertyValue[{g, 3}, VertexStyle]
不幸的是,大多数旧的图论功能在V8中不能很好地发挥作用。尽管如此,如果仔细使用上下文规范,您可以使用它。在V7中,我可以访问
GraphEdit
的输出,如下所示:

Needs["GraphUtilities`"];
g = GraphEdit[];
然后呢,

{vertices, edges} = {"VertexLabels", "Graph"} /. Rest[g]
获取值得传递给其他函数的内容,如
GraphPlot


这部分回答了您的问题,即这是否是一个合理的表述。这种类型的表示使通过替换规则访问信息变得容易。XML导入的工作方式就是一个很好的例子。

我想知道您使用的是什么版本的Mathematica

图论更紧密地集成到V8的核心中,这在很大程度上是一种改进。您可以以面向对象程序员可能喜欢的方式与图形交互。在V8中,我将这样执行您的示例:

g = Graph[Range[5], {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5}];
g = SetProperty[{g, 3}, VertexStyle -> Red]
然后,我可以这样查询属性:

PropertyValue[{g, 3}, VertexStyle]
不幸的是,大多数旧的图论功能在V8中不能很好地发挥作用。尽管如此,如果仔细使用上下文规范,您可以使用它。在V7中,我可以访问
GraphEdit
的输出,如下所示:

Needs["GraphUtilities`"];
g = GraphEdit[];
然后呢,

{vertices, edges} = {"VertexLabels", "Graph"} /. Rest[g]
获取值得传递给其他函数的内容,如
GraphPlot


这部分回答了您的问题,即这是否是一个合理的表述。这种类型的表示使通过替换规则访问信息变得容易。XML导入的工作方式就是一个很好的例子。

图形编辑规则

graphiedit
返回一个列表,其第一个元素是
Graphics
对象,其余元素是描述图形的规则。每条规则的左侧是一个字符串,而不是一个符号。您可以使用
g//FullForm
来确定这一点。要提取图形规则,必须忽略列表的第一个元素,例如

"Graph" /. Drop[g, 1]
模拟记录类型

按照您的建议,实现类似记录的数据类型是一种合理的方法:

graph={Verts->{1,2,3,4,5}, Edges->{1->2, 2->4, 4->4, 4->5}};
确实,如果
Verts
Edges
被赋值,那么“奇怪的副作用”就会发生。然而,有几种方法可以缓解这个问题

首先,Mathematica内部有一个非常广泛的惯例,即避免将值(特别是
OwnValues
)分配给大写字母的符号。Wolfram在所有顶级变量前面加上
$
,例如
$Context
。如果你坚持这些原则
ClearAll[makeGraph, graphVertices, graphEdges]
makeGraph[vertices_, edges_] := graphRecord[Verts -> vertices, Edges -> edges]
graphVertices[graphRecord[rules___]] := Verts /. {rules}
graphEdges[graphRecord[rules___]] := Edges /. {rules}
graph = makeGraph[{1,2,3,4,5}, {1->2,2->4,4->4,4->5}]
(* graphRecord[Verts -> {1, 2, 3, 4, 5}, Edges -> {1->2, 2->4, 4->4, 4->5}] *)

graphVertices[graph]
(* {1, 2, 3, 4, 5} *)

graphEdges[graph]
(* {1 -> 2, 2 -> 4, 4 -> 4, 4 -> 5} *)
graphEdgeCount[r_graphRecord] := graphEdges[r] // Length
graphEdgeCount[x_] := (Message[graphEdgeCount::invArg, x]; Abort[])
graphEdgeCount::invArg = "Invalid argument to graphEdgeCount: ``";
graphEdgeCount[graph]
(* 4 *)

graphEdgeCount["hi"]