2011-04-13 52 views
6

我想在Mathematica中繪製一個「分解樹」。在Mathematica中繪製分解樹的最簡單方法是什麼?

我有一個函數f需要一個對象,並返回該對象的所有組件作爲列表。對於這個問題的目的,我們只是分解數學表達式如下(我的實際f依賴外部數據庫分解不同種類的對象,所以我不能輕易地張貼):

f[e_?AtomQ] := {} 
f[e_] := List @@ e 

我想創建一個樹狀圖,顯示一個對象如何遞歸分解,繼續應用f。對於上面的特定示例f,我們應該得到與TreeForm的輸出非常相似的內容,不同之處在於應在每個節點處顯示完整表達式(而不是僅顯示一個頭)。節點的子節點將成爲f返回的組件。

請注意,元素可以像這樣在分解樹中重複,但不會在TreePlot的輸出中重複元素,因爲它與圖形一起工作。一個想法是產生了獨特的「內部名稱」爲每個節點,構建一個圖形,並用TreePlot,將其設置爲顯示節點的實際形式,而不是他們的「內部名稱」

回答

9

這個怎麼樣?

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

example usage

如果任何條款都不是惰性的,這種 「簡單」(?)的做法是行不通的。

+0

的hackish的方式,但它是那種簡單的解決方案,我希望的。我分解的對象被存儲爲字符串,所以非常適合(無意外評估)。 – Szabolcs 2011-04-13 23:37:01

+0

你能否建議一種與此解決方案兼容的方式來更改節點的字體? (需要顯示默認字體中不存在的字形) – Szabolcs 2011-05-05 10:36:36

+1

@Szabolcs您可以使用'TreeForm'的'VertexRenderingFunction'選項來完全控制節點的外觀, 'VertexRenderingFunction - >(Inset [Framed [Style [#2,FontFamily - >「Webdings」],Background-> LightYellow],#1]&)'。 – WReach 2011-05-05 14:32:57

4

我不知道它回答你的問題,但這裏是我將如何實現基本的TreeForm:

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 

然後:

enter image description here

編輯 ÿ如果你是對的,這不是一棵樹。爲了使它成爲一棵樹,每個表達都應該帶着它的位置。有點像這樣:

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])] 
    ] 

然後

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] 
    ] 

enter image description here

+0

你的情節是不是一個真正的樹,作爲_both_'a^2'和'b_2'具有指向標2.同一節點上的邊緣而這也正是挑戰(爲什麼我提到,也許是爲了使用它的必要節點的「內部名稱」):我需要在每一步都進行分支,並且允許元素在樹中重複。我們應該在這裏有兩個標記爲'2'的節點,一個從'a^2'分支,另一個從'b_2'分支。 – Szabolcs 2011-04-13 13:09:57

+0

@Szabolcs請參閱編輯我的迴應 – Sasha 2011-04-13 17:44:48

+0

這是輝煌的代碼,但有一個小錯誤。 treeplot2函數應爲:Module [{data = decompose2 [expr],gr,vlbls}, gr = Graph [data]; vlbls =表[vl - >(HoldForm @@ {vl [[1]]}),{v1,VertexList [gr]}]; 圖[數據,VertexLabels - > vlbls,ImagePadding - > 50] ], – mathlawguy 2013-01-20 15:52:25

相關問題