diff --git a/papers/medial_tire_cuts/experiments/draw_medial_tire_cut.py b/papers/medial_tire_cuts/experiments/draw_medial_tire_cut.py index 1feffba..6db626e 100644 --- a/papers/medial_tire_cuts/experiments/draw_medial_tire_cut.py +++ b/papers/medial_tire_cuts/experiments/draw_medial_tire_cut.py @@ -2,23 +2,29 @@ Paper-graphics companion to ``run_medial_tire_cut_experiment.py``: it imports ``run_experiment`` from there, runs the pipeline on a random maximal planar -graph, and emits a TikZ ``tikzpicture`` (walk-depth labels + cut slits) for each -recognised full medial tire graph of the decomposition, using ``to_tikz`` from -``medial_tire_cut_labelling``. +graph, and emits TikZ. By default it draws one ``tikzpicture`` (walk-depth +labels + cut slits) per recognised full medial tire graph, using ``to_tikz`` +from ``medial_tire_cut_labelling``. With ``--whole`` it instead draws the whole +medial graph M(G) with every tire's cuts applied, on a Kamada--Kawai layout, the +recognised tires highlighted and the rest of M(G) in grey. This script only renders; the experiment itself draws nothing. Run with the repo venv (networkx): ``.venv/bin/python``. -Example: +Examples: .venv/bin/python draw_medial_tire_cut.py -n 20 --seed 72 > panels.tex + .venv/bin/python draw_medial_tire_cut.py -n 20 --seed 72 --whole > whole.tex """ from __future__ import annotations import argparse +import math import os import sys +import networkx as nx + _HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, _HERE) @@ -38,14 +44,102 @@ def tikz_panels(n: int, seed: int, scale: float = 1.6) -> tuple[dict, list[str]] return result, panels +# --------------------------------------------------------------------------- # +# The whole medial graph: M(G) with all tire cuts applied. +# --------------------------------------------------------------------------- # + +def _is_split(node) -> bool: + return isinstance(node, tuple) and len(node) == 3 and node[1] in ("A", "B") + + +def _medial_layout(H: nx.Graph) -> dict: + """A Kamada--Kawai layout of the (planar) cut graph, normalised to the unit + box. The two copies of a cut vertex have different neighbours, so the layout + separates them automatically, showing the slit.""" + pos = nx.kamada_kawai_layout(H) + xs = [p[0] for p in pos.values()] + ys = [p[1] for p in pos.values()] + cx, cy = 0.5 * (max(xs) + min(xs)), 0.5 * (max(ys) + min(ys)) + span = max(max(xs) - min(xs), max(ys) - min(ys)) or 1.0 + return {v: ((p[0] - cx) / span, (p[1] - cy) / span) for v, p in pos.items()} + + +def medial_tikz(result: dict, scale: float = 9.0) -> str: + """A TikZ ``tikzpicture`` of the whole medial graph M(G) with every tire's + cuts applied. Tire teeth are coloured and carry their walk depth; annular + medial vertices are black; medial vertices outside any recognised tire are + grey; cut (split) vertices are drawn as separated copies.""" + H = result["cut_graph"] + pos = _medial_layout(H) + + # role of each medial vertex: annular / up / down / bite, and walk depth. + annular = set() + for d in sorted(result["results"]): + g, bij = result["results"][d]["g"], result["results"][d]["bij"] + annular.update(bij[f"a{k}"] for k in range(g.n)) + apex = {r["apex"]: (r["role"], r["walk"]) for r in result["labels"]} + + def edge_of(node): + return node[0] if _is_split(node) else node + + L = [] + A = L.append + A(f"\\begin{{tikzpicture}}[scale={scale},") + A(" med/.style={black!30, line width=0.3pt},") + A(" grey/.style={circle, draw=black!45, fill=black!8, inner sep=0.9pt},") + A(" ann/.style={circle, fill=black, inner sep=1.0pt},") + A(" cutv/.style={circle, draw=red!75!black, fill=red!12, inner sep=1.0pt},") + A(" upv/.style={circle, draw=blue!70!black, fill=blue!15, inner sep=1.3pt},") + A(" downv/.style={circle, draw=red!70!black, fill=red!15, inner sep=1.3pt},") + A(" bitev/.style={circle, draw=red!70!black, fill=red!35, inner sep=1.6pt},") + A(" dlbl/.style={font=\\tiny\\bfseries, text=black, inner sep=0.5pt}]") + + def pt(node): + x, y = pos[node] + return f"({x:.3f},{y:.3f})" + + for u, v in H.edges(): + A(f"\\draw[med] {pt(u)}--{pt(v)};") + for node in H.nodes(): + mv = edge_of(node) + if mv in apex: + role, _ = apex[mv] + style = {"up": "upv", "down": "downv", "bite": "bitev"}[role] + elif mv in annular: + style = "cutv" if _is_split(node) else "ann" + else: + style = "grey" + A(f"\\node[{style}] at {pt(node)} {{}};") + for node in H.nodes(): + mv = edge_of(node) + if _is_split(node) or mv not in apex: + continue + x, y = pos[node] + A(f"\\node[dlbl] at ({x:.3f},{y:.3f}) [yshift=4.5pt] {{{apex[mv][1]}}};") + A("\\end{tikzpicture}") + return "\n".join(L) + + def main() -> None: parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("-n", type=int, default=20) parser.add_argument("--seed", type=int, default=72) parser.add_argument("--scale", type=float, default=1.6) + parser.add_argument("--whole", action="store_true", + help="draw the whole medial graph M(G) with all cuts, " + "instead of one panel per tread") args = parser.parse_args() + if args.whole: + result = run_experiment(n=args.n, seed=args.seed) + treads = sorted(result["results"]) + print(f"% whole medial graph: n={args.n} seed={args.seed} " + f"source={result['source']} recognised treads={treads} " + f"|M(G)|={result['M'].number_of_nodes()}") + print(medial_tikz(result, scale=args.scale if args.scale != 1.6 else 9.0)) + return + result, panels = tikz_panels(args.n, args.seed, scale=args.scale) treads = sorted(result["results"]) print(f"% medial tire cut: n={args.n} seed={args.seed} " diff --git a/papers/medial_tire_cuts/paper.aux b/papers/medial_tire_cuts/paper.aux index 55636d1..f94bc02 100644 --- a/papers/medial_tire_cuts/paper.aux +++ b/papers/medial_tire_cuts/paper.aux @@ -24,4 +24,6 @@ \@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces The recognised tread $T_2$ of the medial tire decomposition of a random maximal planar graph on $20$ vertices (Example\nonbreakingspace 3.2\hbox {}), with its walk-depth labelling and cut. Black vertices are the annular medial vertices of $A(T)$; blue vertices are up-tooth apexes and red vertices down-tooth apexes, the larger red vertex being the shared apex of the bite on annular edges $2$ and $5$. Each tooth carries its walk depth; the red slits are the two cuts.}}{4}{}\protected@file@percent } \newlabel{fig:real-cut}{{2}{4}} \@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{4}{}\protected@file@percent } -\gdef \@abspage@last{4} +\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces The whole medial graph $M(G)$ of the random maximal planar graph on $20$ vertices from Example\nonbreakingspace 3.2\hbox {}, with all tire cuts applied. Grey vertices are medial vertices outside any recognised tire; the highlighted tread $T_2$ (cf.\ Figure\nonbreakingspace 2\hbox {}) has black annular medial vertices, blue up-tooth and red down-tooth apexes carrying their walk depths, and the larger red vertex is the bite apex. Drawn by \texttt {experiments/draw\_medial\_tire\_cut.py} with the \texttt {--whole} option.}}{5}{}\protected@file@percent } +\newlabel{fig:whole-medial}{{3}{5}} +\gdef \@abspage@last{5} diff --git a/papers/medial_tire_cuts/paper.log b/papers/medial_tire_cuts/paper.log index 5c08961..65f1142 100644 --- a/papers/medial_tire_cuts/paper.log +++ b/papers/medial_tire_cuts/paper.log @@ -1,4 +1,4 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 14 JUN 2026 23:54 +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 15 JUN 2026 00:06 entering extended mode restricted \write18 enabled. %&-line parsing enabled. @@ -498,33 +498,37 @@ e LaTeX Warning: `h' float specifier changed to `ht'. -[2] [3] [4] (./paper.aux) ) +[2] [3] (./whole_medial_seed72.tikz) + +LaTeX Warning: `h' float specifier changed to `ht'. + +[4] [5] (./paper.aux) ) Here is how much of TeX's memory you used: - 13652 strings out of 478268 - 272685 string characters out of 5846347 - 559301 words of memory out of 5000000 - 31481 multiletter control sequences out of 15000+600000 - 477049 words of font info for 58 fonts, out of 8000000 for 9000 + 13729 strings out of 478268 + 274095 string characters out of 5846347 + 595448 words of memory out of 5000000 + 31553 multiletter control sequences out of 15000+600000 + 477361 words of font info for 59 fonts, out of 8000000 for 9000 1302 hyphenation exceptions out of 8191 - 84i,9n,89p,801b,704s stack positions out of 10000i,1000n,20000p,200000b,200000s - -Output written on paper.pdf (4 pages, 180590 bytes). + 84i,9n,89p,801b,724s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on paper.pdf (5 pages, 198793 bytes). PDF statistics: - 85 PDF objects out of 1000 (max. 8388607) - 52 compressed objects within 1 object stream + 93 PDF objects out of 1000 (max. 8388607) + 57 compressed objects within 1 object stream 0 named destinations out of 1000 (max. 500000) 13 words of extra memory for PDF output out of 10000 (max. 10000000) diff --git a/papers/medial_tire_cuts/paper.pdf b/papers/medial_tire_cuts/paper.pdf index aed0895..c95d463 100644 Binary files a/papers/medial_tire_cuts/paper.pdf and b/papers/medial_tire_cuts/paper.pdf differ diff --git a/papers/medial_tire_cuts/paper.tex b/papers/medial_tire_cuts/paper.tex index 5199488..bc3088a 100644 --- a/papers/medial_tire_cuts/paper.tex +++ b/papers/medial_tire_cuts/paper.tex @@ -387,6 +387,31 @@ tooth carries its walk depth; the red slits are the two cuts.} \label{fig:real-cut} \end{figure} +The same data sit inside the whole medial graph $M(G)$. +Figure~\ref{fig:whole-medial} draws all of $M(G)$ for the graph of +Example~\ref{ex:real-cut}, with the tread $T_2$ of +Figure~\ref{fig:real-cut} highlighted in place: its annular medial cycle +in black, its up and down teeth in blue and red carrying their walk +depths, and the remaining medial vertices---those outside any recognised +tire---in grey. This is the assembled cut graph emitted by the +experiment: every recognised tread contributes its cuts, and the tire +pieces are glued to the rest of $M(G)$ along their boundary medial +vertices. + +\begin{figure}[h] +\centering +\input{whole_medial_seed72.tikz} +\caption{The whole medial graph $M(G)$ of the random maximal planar graph +on $20$ vertices from Example~\ref{ex:real-cut}, with all tire cuts +applied. Grey vertices are medial vertices outside any recognised tire; +the highlighted tread $T_2$ (cf.\ Figure~\ref{fig:real-cut}) has black +annular medial vertices, blue up-tooth and red down-tooth apexes carrying +their walk depths, and the larger red vertex is the bite apex. Drawn by +\texttt{experiments/draw\_medial\_tire\_cut.py} with the \texttt{--whole} +option.} +\label{fig:whole-medial} +\end{figure} + \begin{thebibliography}{9} \bibitem{bauerfeld-medial-tire} diff --git a/papers/medial_tire_cuts/whole_medial_seed72.tikz b/papers/medial_tire_cuts/whole_medial_seed72.tikz new file mode 100644 index 0000000..fcd2967 --- /dev/null +++ b/papers/medial_tire_cuts/whole_medial_seed72.tikz @@ -0,0 +1,181 @@ +\begin{tikzpicture}[scale=9.0, + med/.style={black!30, line width=0.3pt}, + grey/.style={circle, draw=black!45, fill=black!8, inner sep=0.9pt}, + ann/.style={circle, fill=black, inner sep=1.0pt}, + cutv/.style={circle, draw=red!75!black, fill=red!12, inner sep=1.0pt}, + upv/.style={circle, draw=blue!70!black, fill=blue!15, inner sep=1.3pt}, + downv/.style={circle, draw=red!70!black, fill=red!15, inner sep=1.3pt}, + bitev/.style={circle, draw=red!70!black, fill=red!35, inner sep=1.6pt}, + dlbl/.style={font=\tiny\bfseries, text=black, inner sep=0.5pt}] +\draw[med] (0.137,0.152)--(0.228,0.102); +\draw[med] (0.137,0.152)--(0.080,0.066); +\draw[med] (0.137,0.152)--(0.029,0.177); +\draw[med] (0.137,0.152)--(0.242,0.193); +\draw[med] (0.080,0.066)--(0.135,-0.006); +\draw[med] (0.080,0.066)--(0.029,0.177); +\draw[med] (0.080,0.066)--(0.115,-0.072); +\draw[med] (0.214,0.011)--(0.228,0.102); +\draw[med] (0.214,0.011)--(0.135,-0.006); +\draw[med] (0.214,0.011)--(0.068,-0.062); +\draw[med] (0.214,0.011)--(0.294,0.130); +\draw[med] (0.135,-0.006)--(0.115,-0.072); +\draw[med] (0.135,-0.006)--(0.068,-0.062); +\draw[med] (0.228,0.102)--(0.294,0.130); +\draw[med] (0.228,0.102)--(0.242,0.193); +\draw[med] (0.029,0.177)--(0.004,0.286); +\draw[med] (0.029,0.177)--(-0.082,0.223); +\draw[med] (0.286,0.270)--(0.291,0.380); +\draw[med] (0.286,0.270)--(0.242,0.193); +\draw[med] (0.286,0.270)--(0.294,0.130); +\draw[med] (0.286,0.270)--(0.232,0.388); +\draw[med] (0.004,0.286)--(0.064,0.386); +\draw[med] (0.004,0.286)--(-0.031,0.393); +\draw[med] (0.004,0.286)--(-0.082,0.223); +\draw[med] (0.064,0.386)--(0.167,0.434); +\draw[med] (0.064,0.386)--(0.072,0.500); +\draw[med] (0.064,0.386)--(-0.031,0.393); +\draw[med] (0.167,0.434)--(0.291,0.380); +\draw[med] (0.167,0.434)--(0.243,0.486); +\draw[med] (0.167,0.434)--(0.072,0.500); +\draw[med] (0.242,0.193)--(0.294,0.130); +\draw[med] (0.291,0.380)--(0.232,0.388); +\draw[med] (0.291,0.380)--(0.243,0.486); +\draw[med] (-0.274,0.101)--(-0.238,0.008); +\draw[med] (-0.274,0.101)--(-0.196,0.185); +\draw[med] (-0.274,0.101)--(-0.317,-0.021); +\draw[med] (-0.274,0.101)--(-0.285,0.218); +\draw[med] (0.115,-0.072)--(0.007,-0.115); +\draw[med] (0.115,-0.072)--(0.126,-0.186); +\draw[med] (-0.082,0.223)--(-0.196,0.185); +\draw[med] (-0.082,0.223)--(-0.183,0.280); +\draw[med] (-0.141,-0.061)--(0.007,-0.115); +\draw[med] (-0.141,-0.061)--(-0.238,0.008); +\draw[med] (-0.141,-0.061)--(-0.265,-0.085); +\draw[med] (-0.141,-0.061)--(-0.096,-0.135); +\draw[med] (0.007,-0.115)--(-0.096,-0.135); +\draw[med] (0.007,-0.115)--(0.126,-0.186); +\draw[med] (-0.196,0.185)--(-0.183,0.280); +\draw[med] (-0.196,0.185)--(-0.285,0.218); +\draw[med] (-0.238,0.008)--(-0.317,-0.021); +\draw[med] (-0.238,0.008)--(-0.265,-0.085); +\draw[med] (0.068,-0.062)--(-0.057,-0.111); +\draw[med] (0.068,-0.062)--(0.001,-0.185); +\draw[med] (-0.125,0.434)--(-0.011,0.486); +\draw[med] (-0.125,0.434)--(-0.242,0.353); +\draw[med] (-0.125,0.434)--(-0.031,0.393); +\draw[med] (-0.125,0.434)--(-0.212,0.403); +\draw[med] (-0.282,-0.159)--(-0.317,-0.021); +\draw[med] (-0.282,-0.159)--(-0.187,-0.179); +\draw[med] (-0.282,-0.159)--(-0.220,-0.274); +\draw[med] (-0.282,-0.159)--(-0.265,-0.085); +\draw[med] (-0.011,0.486)--(0.138,0.497); +\draw[med] (-0.011,0.486)--(-0.031,0.393); +\draw[med] (-0.011,0.486)--(0.072,0.500); +\draw[med] (-0.285,0.218)--(-0.242,0.353); +\draw[med] (-0.285,0.218)--(-0.295,0.311); +\draw[med] (-0.317,-0.021)--(-0.265,-0.085); +\draw[med] (0.138,0.497)--(0.232,0.388); +\draw[med] (0.138,0.497)--(0.072,0.500); +\draw[med] (0.138,0.497)--(0.243,0.486); +\draw[med] (-0.242,0.353)--(-0.295,0.311); +\draw[med] (-0.242,0.353)--(-0.212,0.403); +\draw[med] (-0.187,-0.179)--(-0.057,-0.111); +\draw[med] (-0.187,-0.179)--(-0.104,-0.210); +\draw[med] (-0.187,-0.179)--(-0.220,-0.274); +\draw[med] (-0.057,-0.111)--(0.001,-0.185); +\draw[med] (-0.057,-0.111)--(-0.104,-0.210); +\draw[med] (0.232,0.388)--(0.243,0.486); +\draw[med] (-0.137,-0.372)--(-0.104,-0.282); +\draw[med] (-0.137,-0.372)--(-0.134,-0.475); +\draw[med] (-0.137,-0.372)--(-0.220,-0.274); +\draw[med] (-0.137,-0.372)--(-0.035,-0.453); +\draw[med] (0.126,-0.186)--(0.212,-0.281); +\draw[med] (0.126,-0.186)--(0.119,-0.298); +\draw[med] (0.212,-0.281)--(0.280,-0.380); +\draw[med] (0.212,-0.281)--(0.119,-0.298); +\draw[med] (0.212,-0.281)--(0.193,-0.407); +\draw[med] (-0.104,-0.282)--(0.001,-0.185); +\draw[med] (-0.104,-0.282)--(-0.220,-0.274); +\draw[med] (-0.104,-0.282)--(-0.104,-0.210); +\draw[med] (0.280,-0.380)--(0.317,-0.480); +\draw[med] (0.280,-0.380)--(0.193,-0.407); +\draw[med] (0.280,-0.380)--(0.212,-0.500); +\draw[med] (0.001,-0.185)--(-0.104,-0.210); +\draw[med] (-0.183,0.280)--(-0.212,0.403); +\draw[med] (-0.183,0.280)--(-0.295,0.311); +\draw[med] (-0.212,0.403)--(-0.295,0.311); +\draw[med] (0.051,-0.411)--(0.133,-0.397); +\draw[med] (0.051,-0.411)--(-0.035,-0.453); +\draw[med] (0.051,-0.411)--(0.090,-0.495); +\draw[med] (0.051,-0.411)--(0.119,-0.298); +\draw[med] (-0.035,-0.453)--(-0.134,-0.475); +\draw[med] (-0.035,-0.453)--(0.090,-0.495); +\draw[med] (0.119,-0.298)--(0.133,-0.397); +\draw[med] (0.090,-0.495)--(0.193,-0.407); +\draw[med] (0.090,-0.495)--(0.212,-0.500); +\draw[med] (0.193,-0.407)--(0.212,-0.500); +\draw[med] (0.212,-0.500)--(0.317,-0.480); +\node[grey] at (0.137,0.152) {}; +\node[grey] at (0.080,0.066) {}; +\node[grey] at (0.214,0.011) {}; +\node[grey] at (0.135,-0.006) {}; +\node[grey] at (0.228,0.102) {}; +\node[grey] at (0.029,0.177) {}; +\node[grey] at (0.286,0.270) {}; +\node[grey] at (0.004,0.286) {}; +\node[grey] at (0.064,0.386) {}; +\node[grey] at (0.167,0.434) {}; +\node[grey] at (0.242,0.193) {}; +\node[grey] at (0.291,0.380) {}; +\node[grey] at (-0.274,0.101) {}; +\node[upv] at (0.115,-0.072) {}; +\node[grey] at (-0.082,0.223) {}; +\node[upv] at (-0.141,-0.061) {}; +\node[ann] at (0.007,-0.115) {}; +\node[grey] at (-0.196,0.185) {}; +\node[grey] at (-0.238,0.008) {}; +\node[grey] at (0.068,-0.062) {}; +\node[grey] at (-0.125,0.434) {}; +\node[grey] at (-0.282,-0.159) {}; +\node[grey] at (-0.011,0.486) {}; +\node[grey] at (-0.285,0.218) {}; +\node[grey] at (-0.317,-0.021) {}; +\node[grey] at (0.138,0.497) {}; +\node[grey] at (-0.242,0.353) {}; +\node[grey] at (-0.187,-0.179) {}; +\node[grey] at (0.294,0.130) {}; +\node[grey] at (-0.057,-0.111) {}; +\node[grey] at (0.232,0.388) {}; +\node[upv] at (-0.137,-0.372) {}; +\node[ann] at (0.126,-0.186) {}; +\node[ann] at (0.212,-0.281) {}; +\node[grey] at (-0.104,-0.282) {}; +\node[ann] at (0.280,-0.380) {}; +\node[grey] at (0.001,-0.185) {}; +\node[grey] at (-0.031,0.393) {}; +\node[grey] at (-0.183,0.280) {}; +\node[grey] at (-0.212,0.403) {}; +\node[ann] at (0.051,-0.411) {}; +\node[grey] at (-0.265,-0.085) {}; +\node[ann] at (-0.035,-0.453) {}; +\node[grey] at (-0.220,-0.274) {}; +\node[bitev] at (0.119,-0.298) {}; +\node[downv] at (0.090,-0.495) {}; +\node[downv] at (0.193,-0.407) {}; +\node[grey] at (0.072,0.500) {}; +\node[grey] at (-0.295,0.311) {}; +\node[grey] at (0.243,0.486) {}; +\node[downv] at (0.212,-0.500) {}; +\node[grey] at (-0.104,-0.210) {}; +\node[cutv] at (-0.134,-0.475) {}; +\node[cutv] at (0.317,-0.480) {}; +\node[cutv] at (-0.096,-0.135) {}; +\node[cutv] at (0.133,-0.397) {}; +\node[dlbl] at (0.115,-0.072) [yshift=4.5pt] {6}; +\node[dlbl] at (-0.141,-0.061) [yshift=4.5pt] {7}; +\node[dlbl] at (-0.137,-0.372) [yshift=4.5pt] {0}; +\node[dlbl] at (0.119,-0.298) [yshift=4.5pt] {3}; +\node[dlbl] at (0.090,-0.495) [yshift=4.5pt] {1}; +\node[dlbl] at (0.193,-0.407) [yshift=4.5pt] {4}; +\node[dlbl] at (0.212,-0.500) [yshift=4.5pt] {5}; +\end{tikzpicture}