There is an example just like this in the IGraph/M documentation for IGExpressionTree
. I'll summarize the technique:
It is not sufficient to use VertexShape
because we have no control over the vertex size and we cannot make the size adapt to the size of the expression that is being displayed
Instead, VertexShapeFunction
must be used. We can set a shape function that explicitly ignores VertexSize
and renders each expression at the appropriate size instead.
Use PerformanceGoal -> "Quality"
to allow auto-adjusting the end and starting point of edges
Example:
asc = <|a -> aShape, b -> bShape, c -> cShape|>
Graph[nodeList, edgeList,
VertexShapeFunction -> (Inset[Framed@StandardForm@asc[#2], #1] &),
PerformanceGoal -> "Quality",
VertexStyle -> Black
]

The purpose of Framed
is just to add a margin, not to add a frame. If you prefer, use FrameStyle -> None
to remove the frame. You can also adjust FrameMargins
.
Additional notes
Avoid symbols as vertex names
I do not recommend using symbols as vertex names. Things will break in strange ways as soon as you assign a value to a
. You could have used "a"
(a string), and "assigned" a value to it using an association, as I did above.
Avoid using TeX to write math in Mathematica
You really really should not use TeX to input math in Mathematica. Mathematica's TeX parser is not very good and you will not have precise control over what to display. Best is to enter the formulas directly in a string using 2D notation (no HoldForm needed). Next-best thing is to enter Mathematica expressions within HoldForm.
In your example, cShape is not even parsed correctly. It is parsed as a product, not as a string. Therefore it does not render with correctly sized spaces between "words" (actually product terms) no matter what you do. I also needed to use StandardForm to prevent the default TraditionalForm from reordering terms in the product. HoldForm
's purpose is to prevent evaluation, not to prevent formatting. The reordering done by TraditionalForm is due to formatting, not evaluation (compare e.g. with TraditionalForm[1 + x + x^2]
which is reordered highest-order term first, which does not correspond with the representation order).
You can also use Panel for a nice vertex appearance
You can consider using Panel
instead of Framed
. This is my preferred method when displaying mathematical expressions as graph vertices. Here's the example from the IGraph/M docs, copied verbatim:
<<IGraphM`
IGExpressionTree[First@Roots[x^2 + a x + 1 == 0, x],
VertexLabels -> "Subexpression",
PerformanceGoal -> "Quality",
ImageSize -> 280
] //
IGVertexMap[
Function[e, Inset[Panel[e], #1] &],
VertexShapeFunction -> IGVertexProp[VertexLabels]
] // RemoveProperty[#, VertexLabels] &

If you need $\TeX$ input, use MaTeX to render
Finally, if for some reason you strongly insist on using TeX code as input, I suggest you render using my MaTeX package. It will use an actual TeX system to render the formulas, and will look exactly the same as if you were using LaTeX.
a = "c=\\sqrt{a^2+b^2}";
b = "c=\\sqrt{b^2+a^2}";
c = "\\text{Area equals A}";
<< MaTeX`
Graph[{a <-> b, b <-> c, c <-> a},
VertexShapeFunction ->
Function[{position, vertex, size}, Inset[Framed[MaTeX[vertex, FontSize -> 16], FrameStyle -> None], position]],
PerformanceGoal -> "Quality"
]

aShape = ToString[#, StandardForm] &@ToExpression["$c=\\sqrt{a^2+b^2}$", TeXForm, HoldForm];
? Similarly, forbShape
andcShape
. $\endgroup$