Wolfram mathematica 在Mathematica中绘制分解树的最简单方法是什么?

Wolfram mathematica 在Mathematica中绘制分解树的最简单方法是什么?,wolfram-mathematica,Wolfram Mathematica,我想在Mathematica中绘制一个“分解树” 我有一个函数f,它接受一个对象并以列表的形式返回该对象的所有组件。对于这个问题,让我们将Mathematica表达式分解如下(我的实际f依赖于外部数据库来分解不同类型的对象,因此我无法轻松发布): 我想创建一个树形图,显示当我们递归地应用f时对象是如何分解的。对于上面的特定示例f,我们应该得到与TreeForm的输出非常相似的结果,只是每个节点都应该显示一个完整的表达式(而不仅仅是一个头部)。节点的子节点将成为其组件,由f返回 请注意,元素可以像

我想在Mathematica中绘制一个“分解树”

我有一个函数
f
,它接受一个对象并以列表的形式返回该对象的所有组件。对于这个问题,让我们将Mathematica表达式分解如下(我的实际
f
依赖于外部数据库来分解不同类型的对象,因此我无法轻松发布):

我想创建一个树形图,显示当我们递归地应用
f
时对象是如何分解的。对于上面的特定示例
f
,我们应该得到与
TreeForm
的输出非常相似的结果,只是每个节点都应该显示一个完整的表达式(而不仅仅是一个头部)。节点的子节点将成为其组件,由
f
返回


请注意,元素可以像这样在分解树中重复,但在
TreePlot
的输出中不会重复元素,因为它与图形一起工作。一个想法是为每个节点生成一个唯一的“内部名称”,构造一个图,并使用树形图,将其设置为显示节点的实际形式,而不是其“内部名称”

我不确定它是否回答了您的问题,但以下是我将如何实现基本树形图:

decompose[expr_?AtomQ] := expr
decompose[expr_] := Block[{lev = Level[expr, {1}]},
  Sow[Thread[expr -> lev]]; decompose /@ lev;]

treeForm[expr_] := Reap[decompose[expr]][[-1, 1]] // Flatten
然后:

编辑 是的,你是对的,这不是一棵树。要使它成为一棵树,每个表达式都应该有自己的位置。有点像这样:

ClearAll[treePlot, node, decompose2];
SetAttributes[{treePlot, node, decompose2}, HoldAll];
decompose2[expr_] /; AtomQ[Unevaluated[expr]] := node[expr];
decompose2[expr_] := Module[{pos, list},
  pos = SortBy[
    Position[Unevaluated[expr], _, {0, Infinity}, Heads -> False], 
    Length];
  list = Extract[Unevaluated[expr], pos, node];
  list = MapThread[Append, {list, pos}];
  ReplaceList[
   list, {___, node[e1_, p1_], ___, node[e2_, p2_], ___} /; 
     Length[p2] == Length[p1] + 1 && 
      Most[p2] == p1 :> (node[e1, p1] -> node[e2, p2])]
  ]
然后

这个怎么样

tf[x_] := f[x] /. {{} :> x, r_ :> x @@ tf /@ r}


如果任何一个术语不是惰性的,这种“简单的”(?)方法将不起作用。

您的绘图实际上不是一棵树,因为
a^2
b_2
都有一条边指向标记为2的相同节点。这正是挑战所在(也是我提到可能有必要为节点使用“内部名称”的原因):我需要在每一步进行分支,并且允许元素在树中重复。这里应该有两个标记为
2
的节点,一个从
a^2
分支,另一个从
b_2
分支。这是一个出色的编码,但有一个小错误。treeplot2函数应该是:模块[{data=decompose2[expr],gr,vlbls},gr=Graph[data];vlbls=Table[vl->(HoldForm@@@vl[[1]}),{vl,VertexList[gr]};Graph[data,VertexLabels->vlbls,ImagePadding->50]],从某种程度上说,这是我所希望的简单解决方案。我分解的对象存储为字符串,因此非常适合(没有意外的计算)。您能建议一种与此解决方案兼容的方法来更改节点的字体吗?(需要显示默认字体中不存在的图示符。)@Szabolcs您可以使用
TreeForm
VertexRenderingFunction
选项来完全控制节点外观,例如
VertexRenderingFunction->(插入[Framed[Style[#2,FontFamily->“Webdings]”,Background->LightYellow],#1]&
。啊,太明显了!我一直在错误的轨道上,试图直接操纵节点。。。
treePlot2[expr_] := 
 Module[{data = decompose2[a^2 + Subscript[b, 2] + 3 c], gr, vlbls},
  gr = Graph[data];
  vlbls = Table[vl -> (HoldForm @@ {vl[[1]]}), {vl, VertexList[gr]}];
  Graph[data, VertexLabels -> vlbls, ImagePadding -> 50]
  ]
tf[x_] := f[x] /. {{} :> x, r_ :> x @@ tf /@ r}