4
$\begingroup$

I have a set of equations written in TeX that I want to use as vertices of a graph, with edge labels showing how the equations are connected. I read the equations in from a file, then replace any backslashes with two backslashes. Then I use TeXForm to convert them to Mathematica notation. I use the HoldForm option to prevent Mathematica from changing b+a into a+b. However, when I display the graph, the "HoldForm" seems to be ignored. Here is an example:

nodeList = {a, b, c}; 
edgeList = {a <-> b, b <-> c, c <-> a}; 
aShape = ToExpression["$c=\\sqrt{a^2+b^2}$", TeXForm, HoldForm]; 
bShape = ToExpression["$c=\\sqrt{b^2+a^2}$", TeXForm, HoldForm]; 
cShape = ToExpression["$\\text{Area equals A}$", TeXForm, HoldForm]; 
Print["The 3 labels are: ", {aShape, bShape, cShape}]; 
shapeList = {a -> aShape, b -> bShape, c -> cShape}; 
g = Graph[nodeList, edgeList, VertexShape -> shapeList, VertexSize -> Large]

This is what the output looks like:

enter image description here

enter image description here

Note that the b^2+a^2 appears as a^2+b^2 in the display of the node. Also "Area equals A" is displayed as the product of three variables, "Area", "equals", and "A".

How can I get the equations to display without any form changes in the nodes of the graph?

$\endgroup$
  • 1
    $\begingroup$ maybe define aShape = ToString[#, StandardForm] &@ToExpression["$c=\\sqrt{a^2+b^2}$", TeXForm, HoldForm];? Similarly, for bShape and cShape. $\endgroup$ – kglr Jan 18 at 0:49
3
$\begingroup$

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
]

enter image description here

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

enter image description here

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

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.