TransWikia.com

Drawing a graph using commands throughout TeX file

TeX - LaTeX Asked by Eklavya Sharma on June 22, 2021

I have commands of the form myedge{u}{v} spread throughout my TeX file. I want to add a (TikZ) graph at the end of the document containing all the myedge edges seen so far. What would be the best way to do this?

For context, I’m trying to visualize theorem dependencies in my LaTeX document. If the proof of theorem 1 uses lemma 2 and lemma 3, and the proof of lemma 2 uses lemma 4, then I would like a graph of the form 1 -> 2, 1 -> 3, 2 -> 4. To do this, I want to appropriately define myedge and then I’ll manually add commands like myedge{1}{2} in the proofs of theorems/lemmas to document this dependency information. I don’t want to keep this dependency information separately at the end of the document in a tikzpicture, because that way it would be hard to keep it in sync with the theorems above.

I’m also considering the option of doing this outside TeX, like writing a python script that reads all myedge commands and outputs a TeX file containing a tikzpicture, which I’ll input in my document. This works, but I’ll prefer a TeX-only solution if it’s not much more difficult.

A short example that demonstrates what I want. See the comments (%) for what changes I want to make but don’t know how to:

documentclass{minimal}
usepackage{amsthm}
usepackage{tikz}
usetikzlibrary{graphs,graphdrawing}
usegdlibrary{layered}
usepackage{hyperref}

newtheorem{theorem}{Theorem}
newcommand*{myedge}[2]{} % what should I put here?

begin{document}
begin{theorem}label{minor} Minor result.end{theorem}

begin{theorem}label{major1} First major result.end{theorem}
begin{proof}
(Long and complicated proof) $ldots$ 
Using theorem ref{minor}, we get that $ldots$ 
myedge{major1}{minor} % document that we used minor in the proof of major1
(more theorem proving follows)
end{proof}

begin{theorem}label{major2} Second major result.end{theorem}

begin{theorem}label{grand} My grand theorem.end{theorem}
begin{proof}
(Long and complicated proof) $ldots$ 
Since ?, theorem ref{major1} gives us that $ldots$ 
myedge{grand}{major1} % document that we used major1 in the proof of grand
(more theorem proving follows) $ldots$ 
Using theorem ref{major2}, we get that $ldots$ 
myedge{grand}{major2} % document that we used major2 in the proof of grand
(more theorem proving follows)
end{proof}

begin{tikzpicture}
graph[layered layout, sibling distance=8mm, level distance=8mm]
{
% How do I specify the edges below automatically based on the
% myedge occurences above?
"Theorem ref{major1}" -> "Theorem ref{minor}";
"Theorem ref{grand}" -> "Theorem ref{major1}";
"Theorem ref{grand}" -> "Theorem ref{major2}";
};
end{tikzpicture}
end{document}

output of MWE

Edit: It would be great if I could also place the graph at the beginning of the document instead of at the end, but that’s not a hard requirement.

One Answer

This was an interesting problem to approach. Building up the list is pretty simple: We can use macro expansion to start with an empty macro and add in the nodes as they're declared along the way:

newcommand{edges}{}
makeatletter
newcommand{myedge}[2]{%
  {letprotect@unexpandable@protect
  xdefedges{edges "Theorem protectref{#1}" -> "Theorem protectref{#2}";}}%
}
makeatother

Note that we wrap everything in a group so that protect keeps its previous meaning outside the expansion. xdef tells TeX to expand all the macros inside of it and make the definition global. We set protect to @unexpandable@protect which tells TeX that whenever it sees protectfoo that it should expand that as protectfoo (and now you know a little about the underlying mechanisms behind fragile commands and protect).

The first problem arises when we try to pass edges to the graph command. TikZ is expecting a plain token list here and it won't expand the edges macro. Perhaps someone more versed in TikZ than I am can offer a better solution, but I ended up using a variation on the command that we did before to simply create a new macro, mygraph which will create a macro that wraps up graph with the edges expanded as above:

newcommand{makegraph}{%
  {letprotect@unexpandable@protect
  xdefmygraph{protectgraph[layered layout, sibling distance=8mm,
    level distance=8mm]{edges};}%
  }%
}

(this goes just before the makeatother when you put the above in your document preamble).

Now, you can at the end of your document write

makegraph

begin{tikzpicture}
  mygraph
end{tikzpicture}

And get your desired result.

I had hoped that I could just include the tikzpicture environment inside makegraph and further simplify the results, but when I tried that, I got

All the commands disappeared and it shows tikzpicture [layered layout, sibling distance=8mm, level distance=8mm]”Theorem major1” -> ”Theorem minor”;”Theorem grand” -> ”Theorem major1”;”Theorem grand” -> ”Theorem major2”;;tikzpicture

instead of the expected graph, so I assume that some of the Lua magic that doesn't allow us to just throw edges into the argument to graph also doesn't let us wrap up a tikzpicture environment in a macro. In any event, it's past my bedtime so I'll leave this where it is and hope it's helpful. I'll cheerfully update it tomorrow if anyone has improvements to be made.

Correct answer by Don Hosek on June 22, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP