This question is similar to this: Nested list to graph. How to "flatten" an arbitrary expression, eg
expr = a[b[c, d[e][f], g], h]
to a list of key-value pairs representing Graph edges of the expression tree:
These can be extracted by applying WReach's exception-based method --> Can TreeForm be displayed “sideways”?:
Block[{TreePlot},
t_TreePlot := Throw@Hold@t;
Catch@MakeBoxes@TreeForm[expr]
][[1, 1]]
Giving:
{{"a", "0", "a[b[c, d[e][f], g], h]"} -> {"b", "1",
"b[c, d[e][f], g]"}, {"b", "1", "b[c, d[e][f], g]"} -> {"c", "2",
"c"}, {"b", "1", "b[c, d[e][f], g]"} -> {"d[e]", "3",
"d[e][f]"}, {"d[e]", "3", "d[e][f]"} -> {"f", "4", "f"}, {"b", "1",
"b[c, d[e][f], g]"} -> {"g", "5", "g"}, {"a", "0",
"a[b[c, d[e][f], g], h]"} -> {"h", "6", "h"}}
(Why are they cast to String?) Note non-atomic sub-expressions replaced with their Head. Based on the above, and the rule: ({h_, _, _} -> {a_, _, _}) :> ToExpression@h -> ToExpression@ a
gives:
{a -> b, b -> c, b -> d[e], d[e] -> f, b -> g, a -> h}
TreeForm is a wrapper around TreePlot
. TreePlot[%, VertexLabeling -> True]
gives:
Since the layout is different, TreePlot
must be making use of the other components of the output of the Block above.
EDIT:
How do TreeForm and SparseAray`ExpressionToTree (see below) extract these pairs of vertices? "Proof of work" is to extract the position (in the expression) of each vertex along with the edges.
Previously, I asked how to extract these "edges" based on a more restricted example Alternatives ordering affects pattern matching in Cases?. Also tried ReplaceList
but don't know how to map it consistently across all levels.