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}
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.
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
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
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP