diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_generator.py b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_generator.py new file mode 100644 index 0000000..7a6f5f5 --- /dev/null +++ b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_generator.py @@ -0,0 +1,312 @@ +"""Exhaustive generator for full medial tire graphs, indexed by |A(T)|. + +Model (Definitions/Remarks 3.1--3.9 of the medial tire decompositions paper). + + * The annular medial vertices induce a cycle A(T), the *annular cycle* + (Theorem 3.3). Write n = |A(T)| for its number of vertices = number of + annular faces = number of annular edges e_0,...,e_{n-1}. + + * Each edge e_i of A(T) carries exactly one tooth (a triangle of M(T)) + whose third vertex is a non-annular apex (Definition 3.4). A tooth is an + *up tooth* (apex in the outer region) or a *down tooth* (apex in the inner + region). We record the tooth types as a word in {U, D}^n. + + * No two up teeth share an apex; at most two down teeth share an apex + (Remark 3.5). Two down teeth sharing an apex form a *bite* (Definition + 3.7). So the down teeth are partitioned into singletons and bite pairs. + A bite pairs two down-edges and is drawn as an apex inside the disk with + spokes to the four endpoints; bites must be mutually non-crossing, i.e. + the bite pairs form a non-crossing (laminar) matching of the down-edges. + The two annular edges of a bite must be non-incident (Definition 3.7): + they share no annular vertex, so cyclically adjacent edges cannot pair. + + * There are at least three up teeth (Remark 3.6). + + * Bite-face condition (Remark 3.8). Let B(T) = A(T) together with the bite + apexes. Its interior non-tooth faces are the root face plus one inner-gap + face per bite. A singleton down tooth lies in the innermost bite enclosing + its edge (or in the root face if none). For every interior non-tooth face + the number of down-tooth apexes lying in that face must be 0 or at least 3. + Equivalently: no face holds exactly one or two singleton down teeth. + +The generator enumerates, for a given n, every (tooth word, bite matching) +pair satisfying these properties and emits the resulting full medial tire +graph as an explicit vertex/edge structure. Configurations may optionally be +reduced modulo the dihedral symmetry of the cycle. +""" + +from __future__ import annotations + +import argparse +import itertools +from collections import defaultdict +from dataclasses import dataclass +from functools import lru_cache +from typing import Iterator + +# A bite is an unordered pair of down-edge indices (i, j) with i < j. +Bite = tuple[int, int] +Matching = frozenset[Bite] + + +# --------------------------------------------------------------------------- +# Non-crossing (laminar) matchings of the down edges. +# --------------------------------------------------------------------------- + +@lru_cache(maxsize=None) +def noncrossing_matchings(positions: tuple[int, ...]) -> tuple[Matching, ...]: + """All non-crossing partial matchings of ``positions`` (sorted ascending). + + Bite pairs drawn inside the disk are non-crossing iff, read in cyclic + order, no two pairs interleave. Cutting the cycle at the gap before the + first edge turns this into ordinary non-crossing interval matchings, which + obey the Catalan recursion below. + """ + if not positions: + return (frozenset(),) + head, *rest = positions + out: list[Matching] = [] + # head left unmatched (a singleton down tooth, if its edge is down) + for tail in noncrossing_matchings(tuple(rest)): + out.append(tail) + # head matched with positions[k]; the strictly-enclosed block must be + # matched within itself to stay non-crossing. + for k in range(1, len(positions)): + partner = positions[k] + inside = tuple(positions[1:k]) + outside = tuple(positions[k + 1:]) + for m_in in noncrossing_matchings(inside): + for m_out in noncrossing_matchings(outside): + out.append(frozenset({(head, partner)}) | m_in | m_out) + return tuple(out) + + +# --------------------------------------------------------------------------- +# The bite-face condition (Remark 3.8). +# --------------------------------------------------------------------------- + +def incident_edges(i: int, j: int, n: int) -> bool: + """Whether annular edges i and j share an annular vertex on the n-cycle.""" + return (j - i) % n == 1 or (i - j) % n == 1 + + +def has_incident_bite(bites: Matching, n: int) -> bool: + """Whether any bite pairs two incident (cyclically adjacent) edges.""" + return any(incident_edges(i, j, n) for i, j in bites) + + +def innermost_bite(edge: int, bites: Matching) -> Bite | None: + """The minimal-span bite whose open interval contains ``edge``, or None.""" + enclosing = [b for b in bites if b[0] < edge < b[1]] + if not enclosing: + return None + return min(enclosing, key=lambda b: b[1] - b[0]) + + +def face_singleton_counts( + tooth_word: str, bites: Matching +) -> dict[Bite | None, int]: + """Down-singletons per interior non-tooth face of B(T). + + The key ``None`` is the root face; a bite key is that bite's inner-gap + face. Faces with no singletons are simply absent from the result. + """ + matched = {edge for pair in bites for edge in pair} + counts: dict[Bite | None, int] = defaultdict(int) + for edge, tooth in enumerate(tooth_word): + if tooth != "D" or edge in matched: + continue # only singleton down teeth contribute apexes + counts[innermost_bite(edge, bites)] += 1 + return dict(counts) + + +def satisfies_bite_face_condition(tooth_word: str, bites: Matching) -> bool: + """Remark 3.8: every non-tooth face holds 0 or >=3 down-tooth apexes.""" + return all(count >= 3 for count in face_singleton_counts(tooth_word, bites).values()) + + +# --------------------------------------------------------------------------- +# The full medial tire graph as an explicit object. +# --------------------------------------------------------------------------- + +@dataclass(frozen=True) +class FullMedialTireGraph: + """A full medial tire graph M(T) determined by its combinatorial data. + + Vertices are named: + a{k} annular medial vertex k (k = 0..n-1), forming A(T); + u{i} apex of the up tooth on edge i; + d{i} apex of the singleton down tooth on edge i; + p{i}_{j} apex of the bite pairing edges i and j (i < j). + """ + + n: int + tooth_word: str + bites: Matching + + @property + def up_edges(self) -> tuple[int, ...]: + return tuple(i for i, t in enumerate(self.tooth_word) if t == "U") + + @property + def down_edges(self) -> tuple[int, ...]: + return tuple(i for i, t in enumerate(self.tooth_word) if t == "D") + + @property + def bite_edges(self) -> frozenset[int]: + return frozenset(edge for pair in self.bites for edge in pair) + + @property + def singleton_down_edges(self) -> tuple[int, ...]: + bite = self.bite_edges + return tuple(i for i in self.down_edges if i not in bite) + + def apex_of_edge(self, edge: int) -> str: + if self.tooth_word[edge] == "U": + return f"u{edge}" + for i, j in self.bites: + if edge in (i, j): + return f"p{i}_{j}" + return f"d{edge}" + + def vertices(self) -> list[str]: + verts = [f"a{k}" for k in range(self.n)] + for i in self.up_edges: + verts.append(f"u{i}") + for i in self.singleton_down_edges: + verts.append(f"d{i}") + for i, j in sorted(self.bites): + verts.append(f"p{i}_{j}") + return verts + + def edges(self) -> list[tuple[str, str]]: + n = self.n + out: list[tuple[str, str]] = [] + # annular cycle A(T) + for k in range(n): + out.append((f"a{k}", f"a{(k + 1) % n}")) + # singleton teeth (up and down): two spokes each + for i in self.up_edges: + out += [(f"u{i}", f"a{i}"), (f"u{i}", f"a{(i + 1) % n}")] + for i in self.singleton_down_edges: + out += [(f"d{i}", f"a{i}"), (f"d{i}", f"a{(i + 1) % n}")] + # bites: a shared apex with four spokes + for i, j in sorted(self.bites): + apex = f"p{i}_{j}" + for edge in (i, j): + out += [(apex, f"a{edge}"), (apex, f"a{(edge + 1) % n}")] + return [tuple(sorted(e)) for e in out] + + def canonical_key(self) -> tuple: + """Representative under the dihedral group of the cycle (rotations and + reflections), so symmetric configurations collapse to one key.""" + n = self.n + best: tuple | None = None + for a in (1, -1): + for b in range(n): + relabel = lambda i: (a * i + b) % n + word = [""] * n + for i, t in enumerate(self.tooth_word): + word[relabel(i)] = t + mapped = tuple(sorted( + tuple(sorted((relabel(i), relabel(j)))) for i, j in self.bites + )) + key = (tuple(word), mapped) + if best is None or key < best: + best = key + return best + + +# --------------------------------------------------------------------------- +# Enumeration. +# --------------------------------------------------------------------------- + +def generate( + n: int, min_up_teeth: int = 3, dedup: bool = False +) -> Iterator[FullMedialTireGraph]: + """Yield every full medial tire graph whose annular cycle has size ``n``. + + ``min_up_teeth`` defaults to 3 (Remark 3.6). With ``dedup`` set, only one + representative per dihedral symmetry class is returned. + """ + seen: set[tuple] = set() + for word_tuple in itertools.product("UD", repeat=n): + tooth_word = "".join(word_tuple) + if tooth_word.count("U") < min_up_teeth: + continue + down = tuple(i for i, t in enumerate(tooth_word) if t == "D") + for bites in noncrossing_matchings(down): + if has_incident_bite(bites, n): + continue + if not satisfies_bite_face_condition(tooth_word, bites): + continue + graph = FullMedialTireGraph(n=n, tooth_word=tooth_word, bites=bites) + if dedup: + key = graph.canonical_key() + if key in seen: + continue + seen.add(key) + yield graph + + +# --------------------------------------------------------------------------- +# CLI. +# --------------------------------------------------------------------------- + +def figure_one() -> FullMedialTireGraph: + """The example graph of Figure 1 (Remark 3.8): 12 edges, one bite (0,6).""" + return FullMedialTireGraph( + n=12, + tooth_word="DDDDDUDUUUUU", # edges 0-4,6 down; 5,7,8,9,10,11 up + bites=frozenset({(0, 6)}), + ) + + +def describe(graph: FullMedialTireGraph) -> str: + counts = face_singleton_counts(graph.tooth_word, graph.bites) + face_strs = [] + for face, c in sorted(counts.items(), key=lambda kv: (kv[0] is not None, kv[0])): + name = "root" if face is None else f"bite{face}" + face_strs.append(f"{name}:{c}") + bites = ",".join(f"({i},{j})" for i, j in sorted(graph.bites)) or "-" + faces = " ".join(face_strs) or "-" + return ( + f"word={graph.tooth_word} up={len(graph.up_edges)} " + f"down={len(graph.down_edges)} bites={bites} faces[{faces}]" + ) + + +def run(args: argparse.Namespace) -> None: + if args.check_figure: + g = figure_one() + print("Figure 1 check:") + print(f" {describe(g)}") + ok = satisfies_bite_face_condition(g.tooth_word, g.bites) + print(f" satisfies Remark 3.8: {ok} (expect True; faces 4 and 0)") + print() + + for n in range(args.min_n, args.max_n + 1): + graphs = list(generate(n, min_up_teeth=args.min_up, dedup=args.dedup)) + label = "classes" if args.dedup else "graphs" + print(f"n={n}: {len(graphs)} {label}") + if args.show: + for g in graphs[: args.show]: + print(f" {describe(g)}") + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--min-n", type=int, default=3) + parser.add_argument("--max-n", type=int, default=8) + parser.add_argument("--min-up", type=int, default=3, help="Remark 3.6 bound") + parser.add_argument("--dedup", action="store_true", + help="reduce modulo dihedral symmetry of the cycle") + parser.add_argument("--show", type=int, default=0, + help="print up to this many graphs per n") + parser.add_argument("--check-figure", action="store_true", + help="verify the Figure 1 example against Remark 3.8") + run(parser.parse_args()) + + +if __name__ == "__main__": + main() diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9.pdf b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9.pdf new file mode 100644 index 0000000..636b7b5 Binary files /dev/null and b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9.pdf differ diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9.png b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9.png new file mode 100644 index 0000000..3481400 Binary files /dev/null and b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9.png differ diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9_atlas.md b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9_atlas.md new file mode 100644 index 0000000..fa12ff5 --- /dev/null +++ b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9_atlas.md @@ -0,0 +1,69 @@ +# Atlas of full medial tire graphs with |A(T)| = 9 + +This note collects every full medial tire graph whose annular cycle `A(T)` has +nine vertices, generated exhaustively from the structural properties in +Definitions/Remarks 3.1–3.9 of `paper.tex`. + +## What is being enumerated + +A full medial tire graph of size `n = |A(T)|` is determined by: + +- a tooth word in `{U, D}^n` — one up (`U`) or down (`D`) tooth per annular + edge (Def. 3.4), with **at least three up teeth** (Rem. 3.6); +- a **non-crossing matching** of the down edges into *bites* — pairs of down + teeth sharing an apex (Rem. 3.5, Def. 3.7); unmatched down teeth are + singletons. The two annular edges of a bite must be **non-incident** + (Def. 3.7): they share no annular vertex, so cyclically adjacent edges + cannot pair; +- subject to the **bite-face condition** (Rem. 3.8): in `B(T) = A(T) + bite + apexes`, every interior non-tooth face must contain `0` or `≥ 3` + down-tooth apexes in its interior (equivalently, no face holds exactly one + or two singleton down teeth). + +Graphs are identified up to the dihedral symmetry of the annular cycle +(rotations and reflections), since these give isomorphic plane graphs. + +## The atlas + +![All full medial tire graphs with |A(T)| = 9](full_medial_tire_n9.png) + +High-resolution vector copy: [`full_medial_tire_n9.pdf`](full_medial_tire_n9.pdf). +Full textual index: [`full_medial_tire_n9_index.txt`](full_medial_tire_n9_index.txt). + +In each diagram the thick black ring is `A(T)`; **blue** outer apexes are up +teeth, **red** inner apexes are singleton down teeth, and a **dark-red** inner +apex with four spokes is a bite (its two paired annular edges). The label under +each diagram is the tooth word and the bite pairs (edge indices). + +## Counts + +There are **81** classes for `n = 9` (cf. `3:1, 4:1, 5:2, 6:6, 7:13, 8:36, +9:81` for `n = 3..9`, with the non-incidence stipulation in force). Breakdown +of the 81 classes: + +| down teeth | classes | | bites | classes | | up teeth | classes | +|-----------:|--------:|---|------:|--------:|---|---------:|--------:| +| 0 | 1 | | 0 | 35 | | 3 | 23 | +| 2 | 3 | | 1 | 35 | | 4 | 29 | +| 3 | 7 | | 2 | 8 | | 5 | 18 | +| 4 | 18 | | 3 | 3 | | 6 | 7 | +| 5 | 29 | | | | | 7 | 3 | +| 6 | 23 | | | | | 9 | 1 | + +46 of the 81 classes contain at least one bite. (Every singleton down tooth +must sit in a face holding `≥ 3` of them, so e.g. words with exactly one or two +down teeth only survive when those down teeth are paired into a bite — and now +only when the paired edges are non-incident, which is why the counts fall +sharply from the unrestricted `n = 9` total of 159.) + +## Reproduce + +```sh +# from this directory, using the repo .venv +../../../.venv/bin/python plot_full_medial_tire_n9.py # figure + index +python full_medial_tire_generator.py --min-n 9 --max-n 9 --dedup --show 5 +``` + +`full_medial_tire_generator.py` is the generator (`generate(n, dedup=True)` +yields `FullMedialTireGraph` objects); `plot_full_medial_tire_n9.py` draws the +atlas. diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9_index.txt b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9_index.txt new file mode 100644 index 0000000..094326f --- /dev/null +++ b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/full_medial_tire_n9_index.txt @@ -0,0 +1,81 @@ + 0 word=UUUUUUUUU up=9 down=0 bites=- + 1 word=UUUUUUDUD up=7 down=2 bites=(6,8) + 2 word=UUUUUUDDD up=6 down=3 bites=- + 3 word=UUUUUDUUD up=7 down=2 bites=(5,8) + 4 word=UUUUUDUDD up=6 down=3 bites=- + 5 word=UUUUUDDDD up=5 down=4 bites=- + 6 word=UUUUDUUUD up=7 down=2 bites=(4,8) + 7 word=UUUUDUUDD up=6 down=3 bites=- + 8 word=UUUUDUDUD up=6 down=3 bites=- + 9 word=UUUUDUDDD up=5 down=4 bites=- + 10 word=UUUUDDUDD up=5 down=4 bites=- + 11 word=UUUUDDUDD up=5 down=4 bites=(4,8),(5,7) + 12 word=UUUUDDDDD up=4 down=5 bites=- + 13 word=UUUUDDDDD up=4 down=5 bites=(4,8) + 14 word=UUUDUUUDD up=6 down=3 bites=- + 15 word=UUUDUUDUD up=6 down=3 bites=- + 16 word=UUUDUUDDD up=5 down=4 bites=- + 17 word=UUUDUDUDD up=5 down=4 bites=- + 18 word=UUUDUDUDD up=5 down=4 bites=(3,8),(5,7) + 19 word=UUUDUDDUD up=5 down=4 bites=- + 20 word=UUUDUDDUD up=5 down=4 bites=(3,5),(6,8) + 21 word=UUUDUDDDD up=4 down=5 bites=- + 22 word=UUUDUDDDD up=4 down=5 bites=(3,5) + 23 word=UUUDUDDDD up=4 down=5 bites=(3,8) + 24 word=UUUDDUUDD up=5 down=4 bites=- + 25 word=UUUDDUUDD up=5 down=4 bites=(3,8),(4,7) + 26 word=UUUDDUDDD up=4 down=5 bites=- + 27 word=UUUDDUDDD up=4 down=5 bites=(4,6) + 28 word=UUUDDUDDD up=4 down=5 bites=(3,8) + 29 word=UUUDDDDDD up=3 down=6 bites=- + 30 word=UUUDDDDDD up=3 down=6 bites=(3,8) + 31 word=UUDUUDUUD up=6 down=3 bites=- + 32 word=UUDUUDUDD up=5 down=4 bites=- + 33 word=UUDUUDUDD up=5 down=4 bites=(2,8),(5,7) + 34 word=UUDUUDDDD up=4 down=5 bites=- + 35 word=UUDUUDDDD up=4 down=5 bites=(2,5) + 36 word=UUDUDUUDD up=5 down=4 bites=- + 37 word=UUDUDUUDD up=5 down=4 bites=(2,8),(4,7) + 38 word=UUDUDUDUD up=5 down=4 bites=- + 39 word=UUDUDUDUD up=5 down=4 bites=(2,4),(6,8) + 40 word=UUDUDUDUD up=5 down=4 bites=(2,8),(4,6) + 41 word=UUDUDUDDD up=4 down=5 bites=- + 42 word=UUDUDUDDD up=4 down=5 bites=(4,6) + 43 word=UUDUDUDDD up=4 down=5 bites=(2,4) + 44 word=UUDUDUDDD up=4 down=5 bites=(2,8) + 45 word=UUDUDDUDD up=4 down=5 bites=- + 46 word=UUDUDDUDD up=4 down=5 bites=(5,7) + 47 word=UUDUDDUDD up=4 down=5 bites=(2,4) + 48 word=UUDUDDUDD up=4 down=5 bites=(2,8) + 49 word=UUDUDDDUD up=4 down=5 bites=- + 50 word=UUDUDDDUD up=4 down=5 bites=(6,8) + 51 word=UUDUDDDUD up=4 down=5 bites=(2,8) + 52 word=UUDUDDDDD up=3 down=6 bites=- + 53 word=UUDUDDDDD up=3 down=6 bites=(2,4) + 54 word=UUDUDDDDD up=3 down=6 bites=(2,8) + 55 word=UUDDUUDDD up=4 down=5 bites=- + 56 word=UUDDUUDDD up=4 down=5 bites=(3,6) + 57 word=UUDDUDUDD up=4 down=5 bites=- + 58 word=UUDDUDUDD up=4 down=5 bites=(5,7) + 59 word=UUDDUDUDD up=4 down=5 bites=(2,8) + 60 word=UUDDUDDDD up=3 down=6 bites=- + 61 word=UUDDUDDDD up=3 down=6 bites=(3,5) + 62 word=UUDDUDDDD up=3 down=6 bites=(2,8) + 63 word=UUDDDUDDD up=3 down=6 bites=- + 64 word=UUDDDUDDD up=3 down=6 bites=(4,6) + 65 word=UUDDDUDDD up=3 down=6 bites=(2,8) + 66 word=UUDDDUDDD up=3 down=6 bites=(2,8),(3,7),(4,6) + 67 word=UDUDUDUDD up=4 down=5 bites=- + 68 word=UDUDUDUDD up=4 down=5 bites=(5,7) + 69 word=UDUDUDUDD up=4 down=5 bites=(3,5) + 70 word=UDUDUDDDD up=3 down=6 bites=- + 71 word=UDUDUDDDD up=3 down=6 bites=(3,5) + 72 word=UDUDUDDDD up=3 down=6 bites=(1,3) + 73 word=UDUDDUDDD up=3 down=6 bites=- + 74 word=UDUDDUDDD up=3 down=6 bites=(4,6) + 75 word=UDUDDUDDD up=3 down=6 bites=(1,3) + 76 word=UDUDDUDDD up=3 down=6 bites=(1,8) + 77 word=UDUDDUDDD up=3 down=6 bites=(1,8),(3,7),(4,6) + 78 word=UDDUDDUDD up=3 down=6 bites=- + 79 word=UDDUDDUDD up=3 down=6 bites=(5,7) + 80 word=UDDUDDUDD up=3 down=6 bites=(1,8),(2,4),(5,7) diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/experiments/plot_full_medial_tire_n9.py b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/plot_full_medial_tire_n9.py new file mode 100644 index 0000000..caa49c2 --- /dev/null +++ b/papers/medial_tire_decompositions_of_plane_triangulations/experiments/plot_full_medial_tire_n9.py @@ -0,0 +1,139 @@ +"""Draw every full medial tire graph with |A(T)| = 9. + +Generates the dihedral-symmetry classes from ``full_medial_tire_generator`` and +draws each one in the tooth style of the paper figures: the annular cycle A(T) +as a thick ring of black vertices, up teeth pointing outward (blue apexes), +singleton down teeth pointing inward (red apexes), and bites as a single inner +apex (dark red) with four spokes to the two paired annular edges. + +Output is a single grid figure (PNG + PDF) plus a text index of the classes. +""" + +from __future__ import annotations + +import argparse +import math +import os + +import matplotlib + +matplotlib.use("Agg") +import matplotlib.pyplot as plt + +from full_medial_tire_generator import FullMedialTireGraph, generate + +HERE = os.path.dirname(os.path.abspath(__file__)) + + +def vertex_xy(k: int, n: int, radius: float) -> tuple[float, float]: + """Annular vertex k, placed clockwise from the top of the unit circle.""" + angle = math.pi / 2 - 2 * math.pi * k / n + return radius * math.cos(angle), radius * math.sin(angle) + + +def edge_midpoint_angle(i: int, n: int) -> float: + return math.pi / 2 - 2 * math.pi * (i + 0.5) / n + + +def draw_graph(ax, g: FullMedialTireGraph) -> None: + n = g.n + ann = [vertex_xy(k, n, 1.0) for k in range(n)] + matched = g.bite_edges + + # annular cycle A(T) + cyc_x = [p[0] for p in ann] + [ann[0][0]] + cyc_y = [p[1] for p in ann] + [ann[0][1]] + ax.plot(cyc_x, cyc_y, color="black", lw=1.6, zorder=2) + + # up teeth (outer apexes) and singleton down teeth (inner apexes) + for i, tooth in enumerate(g.tooth_word): + if tooth == "U": + r, color = 1.42, "#2b6cb0" + elif i not in matched: # singleton down tooth + r, color = 0.58, "#c53030" + else: + continue + ang = edge_midpoint_angle(i, n) + apex = (r * math.cos(ang), r * math.sin(ang)) + a0, a1 = ann[i], ann[(i + 1) % n] + ax.plot([apex[0], a0[0]], [apex[1], a0[1]], color="#9a9a9a", lw=0.5, zorder=1) + ax.plot([apex[0], a1[0]], [apex[1], a1[1]], color="#9a9a9a", lw=0.5, zorder=1) + ax.scatter([apex[0]], [apex[1]], s=14, color=color, zorder=3) + + # bites: one shared inner apex with four spokes + for i, j in sorted(g.bites): + corners = [ann[i], ann[(i + 1) % n], ann[j], ann[(j + 1) % n]] + cx = sum(p[0] for p in corners) / 4.0 + cy = sum(p[1] for p in corners) / 4.0 + # pull slightly toward the centre so nested bites stay distinguishable + apex = (cx * 0.82, cy * 0.82) + for corner in corners: + ax.plot([apex[0], corner[0]], [apex[1], corner[1]], + color="#9a9a9a", lw=0.5, zorder=1) + ax.scatter([apex[0]], [apex[1]], s=26, color="#7b1f1f", + edgecolors="black", linewidths=0.4, zorder=4) + + # annular vertices on top + ax.scatter([p[0] for p in ann], [p[1] for p in ann], + s=10, color="black", zorder=5) + + bites = ",".join(f"{i}{j}" for i, j in sorted(g.bites)) or "-" + ax.set_title(f"{g.tooth_word}\n{bites}", fontsize=5.5, pad=1.5) + ax.set_xlim(-1.6, 1.6) + ax.set_ylim(-1.6, 1.6) + ax.set_aspect("equal") + ax.axis("off") + + +def run(args: argparse.Namespace) -> None: + graphs = list(generate(args.n, min_up_teeth=args.min_up, dedup=True)) + print(f"n={args.n}: {len(graphs)} dihedral classes") + + cols = args.cols + rows = math.ceil(len(graphs) / cols) + fig, axes = plt.subplots(rows, cols, figsize=(cols * 1.45, rows * 1.6)) + axes = axes.reshape(rows, cols) + for idx in range(rows * cols): + ax = axes[idx // cols][idx % cols] + if idx < len(graphs): + draw_graph(ax, graphs[idx]) + else: + ax.axis("off") + + fig.suptitle( + f"All full medial tire graphs with $|A(T)|={args.n}$ " + f"({len(graphs)} classes up to dihedral symmetry)", + fontsize=12, y=0.997, + ) + fig.tight_layout(rect=(0, 0, 1, 0.985)) + + png = os.path.join(HERE, f"full_medial_tire_n{args.n}.png") + pdf = os.path.join(HERE, f"full_medial_tire_n{args.n}.pdf") + fig.savefig(png, dpi=200) + fig.savefig(pdf) + print(f"wrote {png}") + print(f"wrote {pdf}") + + if args.index: + index_path = os.path.join(HERE, f"full_medial_tire_n{args.n}_index.txt") + with open(index_path, "w") as fh: + for idx, g in enumerate(graphs): + bites = ",".join(f"({i},{j})" for i, j in sorted(g.bites)) or "-" + fh.write( + f"{idx:3d} word={g.tooth_word} up={len(g.up_edges)} " + f"down={len(g.down_edges)} bites={bites}\n" + ) + print(f"wrote {index_path}") + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--n", type=int, default=9) + parser.add_argument("--min-up", type=int, default=3) + parser.add_argument("--cols", type=int, default=12) + parser.add_argument("--index", action="store_true", default=True) + run(parser.parse_args()) + + +if __name__ == "__main__": + main() diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux b/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux index 511ea74..e845bb1 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.aux @@ -11,23 +11,30 @@ \@writefile{toc}{\contentsline {section}{\tocsection {}{3}{Medial tire pieces}}{2}{}\protected@file@percent } \newlabel{def:full-medial-tire}{{3.1}{2}} \newlabel{thm:annular-medial-colour-bound}{{3.3}{3}} -\newlabel{def:boundary-medial-vertices}{{3.4}{3}} -\newlabel{def:medial-restriction-relation}{{3.5}{3}} +\newlabel{def:annular-teeth}{{3.4}{3}} +\newlabel{rem:teeth-sharing}{{3.5}{3}} +\newlabel{rem:up-teeth-count}{{3.6}{3}} +\newlabel{def:bite}{{3.7}{4}} +\newlabel{rem:bite-face-count}{{3.8}{4}} +\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces A full medial tire graph $\mathsf {M}(T)$ illustrating the tooth terminology. The thick cycle is the annular medial cycle $A(T)$, whose black vertices are the annular medial vertices. Each edge of $A(T)$ carries one tooth: up teeth (blue apexes, outer-boundary medial vertices) point into the outer region, and down teeth (red apexes, inner-boundary medial vertices) point into the inner region. The two down teeth meeting at the central shared apex (larger red vertex) form a bite; that shared apex splits the inner region into two faces, one with four down teeth on its boundary and one with none.}}{4}{}\protected@file@percent } +\newlabel{fig:medial-teeth-example}{{1}{4}} +\newlabel{def:boundary-medial-vertices}{{3.9}{4}} \citation{bauerfeld-nested-tire-decompositions} +\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces Three six-face full medial tire graphs found by the boundary-state restriction search. Black vertices are annular medial vertices; blue vertices are outer boundary medial vertices and red vertices are inner boundary medial vertices. The word below each diagram records the outer/inner type of the six annular faces in cyclic order. Boundary states are identified only up to colour permutation, not by rotation or reflection of the boundary order.}}{5}{}\protected@file@percent } +\newlabel{fig:medial-restriction-worst-cases}{{2}{5}} +\@writefile{lof}{\contentsline {figure}{\numberline {3}{\ignorespaces A proper vertex $3$-colouring of the full medial graph of the first seven-vertex counterexample found by the experiment. The medial vertex labelled $ij$ corresponds to the edge $(i,j)$ of the triangulation. For the vertex-source decomposition at source $1$, the highlighted annular medial cycle has colour counts $(2,2,2)$, so it is not coloured with two colours except at at most one vertex.}}{5}{}\protected@file@percent } +\newlabel{fig:medial-annular-cycle-counterexample}{{3}{5}} +\newlabel{def:medial-restriction-relation}{{3.10}{5}} \citation{bauerfeld-nested-tire-decompositions} -\@writefile{lof}{\contentsline {figure}{\numberline {1}{\ignorespaces Three six-face full medial tire graphs found by the boundary-state restriction search. Black vertices are annular medial vertices; blue vertices are outer boundary medial vertices and red vertices are inner boundary medial vertices. The word below each diagram records the outer/inner type of the six annular faces in cyclic order. Boundary states are identified only up to colour permutation, not by rotation or reflection of the boundary order.}}{4}{}\protected@file@percent } -\newlabel{fig:medial-restriction-worst-cases}{{1}{4}} -\@writefile{lof}{\contentsline {figure}{\numberline {2}{\ignorespaces A proper vertex $3$-colouring of the full medial graph of the first seven-vertex counterexample found by the experiment. The medial vertex labelled $ij$ corresponds to the edge $(i,j)$ of the triangulation. For the vertex-source decomposition at source $1$, the highlighted annular medial cycle has colour counts $(2,2,2)$, so it is not coloured with two colours except at at most one vertex.}}{4}{}\protected@file@percent } -\newlabel{fig:medial-annular-cycle-counterexample}{{2}{4}} -\@writefile{toc}{\contentsline {section}{\tocsection {}{4}{Decomposition}}{4}{}\protected@file@percent } -\newlabel{cor:medial-tire-decomposition}{{4.1}{4}} -\newlabel{def:compatible-family}{{4.2}{5}} -\newlabel{prop:gluing-criterion}{{4.3}{5}} -\@writefile{toc}{\contentsline {section}{\tocsection {}{5}{A medial pigeonhole programme}}{5}{}\protected@file@percent } -\newlabel{def:medial-boundary-state}{{5.1}{5}} -\newlabel{conj:medial-chain-pigeonhole}{{5.2}{5}} -\newlabel{conj:medial-route-fct}{{5.3}{6}} -\@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{5.1}{Kempe-cycle conservation across medial tires}}{6}{}\protected@file@percent } +\@writefile{toc}{\contentsline {section}{\tocsection {}{4}{Decomposition}}{6}{}\protected@file@percent } +\newlabel{cor:medial-tire-decomposition}{{4.1}{6}} +\newlabel{def:compatible-family}{{4.2}{6}} +\newlabel{prop:gluing-criterion}{{4.3}{6}} +\@writefile{toc}{\contentsline {section}{\tocsection {}{5}{A medial pigeonhole programme}}{6}{}\protected@file@percent } +\newlabel{def:medial-boundary-state}{{5.1}{6}} +\newlabel{conj:medial-chain-pigeonhole}{{5.2}{7}} +\newlabel{conj:medial-route-fct}{{5.3}{7}} +\@writefile{toc}{\contentsline {subsection}{\tocsubsection {}{5.1}{Kempe-cycle conservation across medial tires}}{7}{}\protected@file@percent } \bibcite{bauerfeld-nested-tire-decompositions}{1} \bibcite{tait-original}{2} \newlabel{tocindent-1}{0pt} @@ -35,5 +42,5 @@ \newlabel{tocindent1}{17.77782pt} \newlabel{tocindent2}{29.38873pt} \newlabel{tocindent3}{0pt} -\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{8}{}\protected@file@percent } -\gdef \@abspage@last{8} +\@writefile{toc}{\contentsline {section}{\tocsection {}{}{References}}{10}{}\protected@file@percent } +\gdef \@abspage@last{10} diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk b/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk index 4751c0b..6898b6e 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.fdb_latexmk @@ -1,6 +1,5 @@ # Fdb version 3 -["pdflatex"] 1780957013 "/Users/didericis/Code/math-research/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex" "paper.pdf" "paper" 1780957014 - "/Users/didericis/Code/math-research/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex" 1780957012 31877 e1531fb82c355208b5b7c8e57cfb6e8a "" +["pdflatex"] 1781194762 "paper.tex" "paper.pdf" "paper" 1781194763 "/usr/local/texlive/2022/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" "/usr/local/texlive/2022/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex8.tfm" 1246382020 988 bdf658c3bfc2d96d3c8b02cfc1c94c20 "" @@ -133,8 +132,8 @@ "/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map" 1647878959 4410336 7d30a02e9fa9a16d7d1f8d037ba69641 "" "/usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt" 1665017617 2826443 7e98410c533054b636c6470db83a27bc "" "/usr/local/texlive/2022/texmf.cnf" 1647878952 577 209b46be99c9075fd74d4c0369380e8c "" - "paper.aux" 1780957014 3096 87a6f727fdb250a8819be3b4fc862d4e "pdflatex" - "paper.tex" 1780957012 31877 e1531fb82c355208b5b7c8e57cfb6e8a "" + "paper.aux" 1781194763 4035 146533a306519cb8688d4e85db1d3f80 "pdflatex" + "paper.tex" 1781194559 37363 b7b005cfaefc0e3a582f756b993a034e "" (generated) "paper.aux" "paper.log" diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.fls b/papers/medial_tire_decompositions_of_plane_triangulations/paper.fls index 8fff45e..0275ecf 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.fls +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.fls @@ -2,7 +2,7 @@ PWD /Users/didericis/Code/math-research/papers/medial_tire_decompositions_of_pla INPUT /usr/local/texlive/2022/texmf.cnf INPUT /usr/local/texlive/2022/texmf-dist/web2c/texmf.cnf INPUT /usr/local/texlive/2022/texmf-var/web2c/pdftex/pdflatex.fmt -INPUT /Users/didericis/Code/math-research/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex +INPUT paper.tex OUTPUT paper.log INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsart.cls INPUT /usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsart.cls diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.log b/papers/medial_tire_decompositions_of_plane_triangulations/paper.log index 3439d11..4fc5435 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.log +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.log @@ -1,12 +1,12 @@ -This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 8 JUN 2026 18:16 +This is pdfTeX, Version 3.141592653-2.6-1.40.24 (TeX Live 2022) (preloaded format=pdflatex 2022.10.5) 11 JUN 2026 12:19 entering extended mode restricted \write18 enabled. - file:line:error style messages enabled. %&-line parsing enabled. -**/Users/didericis/Code/math-research/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex -(/Users/didericis/Code/math-research/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex +**paper.tex +(./paper.tex LaTeX2e <2021-11-15> patch level 1 -L3 programming layer <2022-02-24> (/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsart.cls +L3 programming layer <2022-02-24> +(/usr/local/texlive/2022/texmf-dist/tex/latex/amscls/amsart.cls Document Class: amsart 2020/05/29 v2.20.6 \linespacing=\dimen138 \normalparindent=\dimen139 @@ -18,14 +18,17 @@ Package: amsmath 2021/10/15 v2.17l AMS math features For additional information on amsmath, use the `?' option. (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amstext.sty Package: amstext 2021/08/26 v2.01 AMS text - (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsgen.sty File: amsgen.sty 1999/11/30 v2.0 generic functions \@emptytoks=\toks16 \ex@=\dimen140 -)) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty +)) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsbsy.sty Package: amsbsy 1999/11/29 v1.2d Bold Symbols \pmbraise@=\dimen141 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsmath/amsopn.sty Package: amsopn 2021/08/26 v2.02 operator names ) \inf@bad=\count185 @@ -66,10 +69,13 @@ LaTeX Font Info: Redeclaring font encoding OMS on input line 744. LaTeX Info: Redefining \[ on input line 2938. LaTeX Info: Redefining \] on input line 2939. ) -LaTeX Font Info: Trying to load font information for U+msa on input line 397. - (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd +LaTeX Font Info: Trying to load font information for U+msa on input line 397 +. + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd File: umsa.fd 2013/01/14 v3.01 AMS symbols A -) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amsfonts.sty Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support \symAMSa=\mathgroup4 \symAMSb=\mathgroup5 @@ -100,42 +106,63 @@ LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' \thm@postskip=\skip55 \thm@headsep=\skip56 \dth@everypar=\toks26 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amssymb.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/amssymb.sty Package: amssymb 2013/01/14 v3.01 AMS font symbols -) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphicx.sty Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR) - (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/keyval.sty Package: keyval 2014/10/28 v1.15 key=value parser (DPC) \KV@toks@=\toks27 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/graphics.sty Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR) - (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics/trig.sty Package: trig 2021/08/11 v1.11 sin cos tan (DPC) -) (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/graphics.cfg File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration ) Package graphics Info: Driver file: pdftex.def on input line 107. - (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-def/pdftex.def File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex )) \Gin@req@height=\dimen150 \Gin@req@width=\dimen151 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/frontendlayer/tikz.sty +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgf.sty +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfrcs.sty +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common.te +x \pgfutil@everybye=\toks28 \pgfutil@tempdima=\dimen152 \pgfutil@tempdimb=\dimen153 - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-lists.tex)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-common-li +sts.tex)) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfutil-latex.def \pgfutil@abb=\box53 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex) +) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfrcs.code.tex +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/pgf.revision.tex) Package: pgfrcs 2021/05/15 v3.1.9a (3.1.9a) )) Package: pgf 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex + +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/basiclayer/pgfcore.sty +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/systemlayer/pgfsys.sty +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys.code.tex Package: pgfsys 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex \pgfkeys@pathtoks=\toks29 \pgfkeys@temptoks=\toks30 - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.tex + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.c +ode.tex \pgfkeys@tmptoks=\toks31 )) \pgf@x=\dimen154 @@ -158,23 +185,33 @@ Package: pgfsys 2021/05/15 v3.1.9a (3.1.9a) \t@pgf@tokb=\toks33 \t@pgf@tokc=\toks34 \pgf@sys@id@count=\count276 - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgf.cfg File: pgf.cfg 2021/05/15 v3.1.9a (3.1.9a) ) Driver file for pgf: pgfsys-pdftex.def - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.def + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-pdftex.d +ef File: pgfsys-pdftex.def 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-pdf.def + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsys-common-p +df.def File: pgfsys-common-pdf.def 2021/05/15 v3.1.9a (3.1.9a) -))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath.code.tex +))) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsyssoftpath. +code.tex File: pgfsyssoftpath.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgfsyssoftpath@smallbuffer@items=\count277 \pgfsyssoftpath@bigbuffer@items=\count278 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/systemlayer/pgfsysprotocol. +code.tex File: pgfsysprotocol.code.tex 2021/05/15 v3.1.9a (3.1.9a) )) (/usr/local/texlive/2022/texmf-dist/tex/latex/xcolor/xcolor.sty Package: xcolor 2021/10/31 v2.13 LaTeX color extensions (UK) - (/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg + +(/usr/local/texlive/2022/texmf-dist/tex/latex/graphics-cfg/color.cfg File: color.cfg 2016/01/02 v1.6 sample color configuration ) Package xcolor Info: Driver file: pdftex.def on input line 227. @@ -187,18 +224,43 @@ Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1372. Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1373. Package xcolor Info: Model `Gray' substituted by `gray' on input line 1374. Package xcolor Info: Model `wave' substituted by `hsb' on input line 1375. -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcore.code.tex Package: pgfcore 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathcalc.code.tex +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathutil.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathparser.code.tex \pgfmath@dimen=\dimen164 \pgfmath@count=\count279 \pgfmath@box=\box54 \pgfmath@toks=\toks35 \pgfmath@stack@operand=\toks36 \pgfmath@stack@operation=\toks37 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code.tex (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigonometric.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.random.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.comparison.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integerarithmetics.code.tex))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.code. +tex +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.basic +.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.trigo +nometric.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.rando +m.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.compa +rison.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.base. +code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.round +.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.misc. +code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfunctions.integ +erarithmetics.code.tex))) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmathfloat.code.tex \c@pgfmathroundto@lastzeros=\count280 -)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.code.tex +)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfint.code.tex) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepoints.co +de.tex File: pgfcorepoints.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@picminx=\dimen165 \pgf@picmaxx=\dimen166 @@ -214,76 +276,127 @@ File: pgfcorepoints.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@yy=\dimen176 \pgf@zx=\dimen177 \pgf@zy=\dimen178 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconstruct.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathconst +ruct.code.tex File: pgfcorepathconstruct.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@path@lastx=\dimen179 \pgf@path@lasty=\dimen180 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathusage +.code.tex File: pgfcorepathusage.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@shorten@end@additional=\dimen181 \pgf@shorten@start@additional=\dimen182 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorescopes.co +de.tex File: pgfcorescopes.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgfpic=\box55 \pgf@hbox=\box56 \pgf@layerbox@main=\box57 \pgf@picture@serial@count=\count281 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicstate.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoregraphicst +ate.code.tex File: pgfcoregraphicstate.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgflinewidth=\dimen183 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransformations.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransform +ations.code.tex File: pgfcoretransformations.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@pt@x=\dimen184 \pgf@pt@y=\dimen185 \pgf@pt@temp=\dimen186 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorequick.cod +e.tex File: pgfcorequick.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreobjects.c +ode.tex File: pgfcoreobjects.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathprocessing.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepathproce +ssing.code.tex File: pgfcorepathprocessing.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorearrows.co +de.tex File: pgfcorearrows.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgfarrowsep=\dimen187 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreshade.cod +e.tex File: pgfcoreshade.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@max=\dimen188 \pgf@sys@shading@range@num=\count282 \pgf@shadingcount=\count283 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreimage.cod +e.tex File: pgfcoreimage.code.tex 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal.code.tex + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoreexternal. +code.tex File: pgfcoreexternal.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgfexternal@startupbox=\box58 -)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.code.tex +)) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorelayers.co +de.tex File: pgfcorelayers.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretransparency.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcoretranspare +ncy.code.tex File: pgfcoretransparency.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorepatterns. +code.tex File: pgfcorepatterns.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/basiclayer/pgfcorerdf.code. +tex File: pgfcorerdf.code.tex 2021/05/15 v3.1.9a (3.1.9a) -))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.code.tex +))) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleshapes.cod +e.tex File: pgfmoduleshapes.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgfnodeparttextbox=\box59 -) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code.tex +) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmoduleplot.code. +tex File: pgfmoduleplot.code.tex 2021/05/15 v3.1.9a (3.1.9a) -) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-0-65.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-0-65.sty Package: pgfcomp-version-0-65 2021/05/15 v3.1.9a (3.1.9a) \pgf@nodesepstart=\dimen189 \pgf@nodesepend=\dimen190 -) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version-1-18.sty +) +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/compatibility/pgfcomp-version +-1-18.sty Package: pgfcomp-version-1-18 2021/05/15 v3.1.9a (3.1.9a) -)) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex)) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex +)) +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgffor.sty +(/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex) +) (/usr/local/texlive/2022/texmf-dist/tex/latex/pgf/math/pgfmath.sty +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex)) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/utilities/pgffor.code.tex Package: pgffor 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex) + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/math/pgfmath.code.tex) \pgffor@iter=\dimen191 \pgffor@skip=\dimen192 \pgffor@stack=\toks38 \pgffor@toks=\toks39 -)) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.code.tex +)) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/tikz.cod +e.tex Package: tikz 2021/05/15 v3.1.9a (3.1.9a) - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothandlers.code.tex + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/libraries/pgflibraryplothan +dlers.code.tex File: pgflibraryplothandlers.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@plot@mark@count=\count284 \pgfplotmarksize=\dimen193 @@ -304,26 +417,34 @@ File: pgflibraryplothandlers.code.tex 2021/05/15 v3.1.9a (3.1.9a) \tikznumberofchildren=\count286 \tikznumberofcurrentchild=\count287 \tikz@fig@count=\count288 - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.code.tex + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/modules/pgfmodulematrix.cod +e.tex File: pgfmodulematrix.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgfmatrixcurrentrow=\count289 \pgfmatrixcurrentcolumn=\count290 \pgf@matrix@numberofcolumns=\count291 ) \tikz@expandcount=\count292 - (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarytopaths.code.tex + +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarytopaths.code.tex File: tikzlibrarytopaths.code.tex 2021/05/15 v3.1.9a (3.1.9a) -))) (/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/libraries/tikzlibrarybackgrounds.code.tex +))) +(/usr/local/texlive/2022/texmf-dist/tex/generic/pgf/frontendlayer/tikz/librarie +s/tikzlibrarybackgrounds.code.tex File: tikzlibrarybackgrounds.code.tex 2021/05/15 v3.1.9a (3.1.9a) \pgf@layerbox@background=\box64 \pgf@layerboxsaved@background=\box65 ) \c@theorem=\count293 - (/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def + +(/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def File: l3backend-pdftex.def 2022-02-07 L3 backend support: PDF output (pdfTeX) \l__color_backend_stack_int=\count294 \l__pdf_internal_box=\box66 -) (./paper.aux) +) +(./paper.aux) \openout1 = `paper.aux'. LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 29. @@ -341,13 +462,17 @@ LaTeX Font Info: ... okay on input line 29. LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 29. LaTeX Font Info: ... okay on input line 29. LaTeX Font Info: Trying to load font information for U+msa on input line 29. + (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsa.fd File: umsa.fd 2013/01/14 v3.01 AMS symbols A ) LaTeX Font Info: Trying to load font information for U+msb on input line 29. - (/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd + + +(/usr/local/texlive/2022/texmf-dist/tex/latex/amsfonts/umsb.fd File: umsb.fd 2013/01/14 v3.01 AMS symbols B -) (/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +) +(/usr/local/texlive/2022/texmf-dist/tex/context/base/mkii/supp-pdf.mkii [Loading MPS to PDF converter (version 2006.09.02).] \scratchcounter=\count295 \scratchdimen=\dimen259 @@ -362,30 +487,58 @@ File: umsb.fd 2013/01/14 v3.01 AMS symbols B \everyMPtoPDFconversion=\toks41 ) (/usr/local/texlive/2022/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf -Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 485. - (/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg -File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Live -)) [1{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] [2] +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4 +85. + +(/usr/local/texlive/2022/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv +e +)) +[1{/usr/local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] +[2] [3] +Overfull \hbox (62.13657pt too wide) in paragraph at lines 363--372 + [][] + [] + LaTeX Warning: `h' float specifier changed to `ht'. LaTeX Warning: `h' float specifier changed to `ht'. -[3] [4] [5] [6] [7] [8] (./paper.aux) ) +[4] [5] [6] [7] [8] [9] [10] (./paper.aux) ) Here is how much of TeX's memory you used: - 14159 strings out of 478268 - 280330 string characters out of 5846347 - 592946 words of memory out of 5000000 - 31987 multiletter control sequences out of 15000+600000 + 14415 strings out of 478268 + 283664 string characters out of 5846347 + 609309 words of memory out of 5000000 + 32244 multiletter control sequences out of 15000+600000 477048 words of font info for 58 fonts, out of 8000000 for 9000 1302 hyphenation exceptions out of 8191 - 84i,8n,89p,676b,841s stack positions out of 10000i,1000n,20000p,200000b,200000s - -Output written on paper.pdf (8 pages, 265030 bytes). + 84i,8n,89p,736b,838s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on paper.pdf (10 pages, 272876 bytes). PDF statistics: - 129 PDF objects out of 1000 (max. 8388607) - 80 compressed objects within 1 object stream + 135 PDF objects out of 1000 (max. 8388607) + 84 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_decompositions_of_plane_triangulations/paper.pdf b/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf index 7528a59..4d69bcd 100644 Binary files a/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf and b/papers/medial_tire_decompositions_of_plane_triangulations/paper.pdf differ diff --git a/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex b/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex index 2aff88d..65d0dfb 100644 --- a/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex +++ b/papers/medial_tire_decompositions_of_plane_triangulations/paper.tex @@ -195,8 +195,8 @@ Let $T = (B_{\mathrm{out}}, O, E_{\mathrm{ann}})$ be a tire tread with non-degenerate boundaries and simple inner boundary $B_{\mathrm{in}}$. Let $A(T)$ be the subgraph of $\mathsf{M}(T)$ induced by the annular medial vertices. For a graph $H$, write $\operatorname{Col}_3(H)$ for -the set of proper $3$-vertex-colourings of $H$. Then $A(T)$ is a cycle -and +the set of proper $3$-vertex-colourings of $H$. Then $A(T)$ is a +cycle---the \emph{annular cycle} of $T$---and \[ |\operatorname{Col}_3(\mathsf{M}(T))| \;\leq\; |\operatorname{Col}_3(A(T))|. @@ -234,6 +234,145 @@ same restriction to $A(T)$ are identical, so the restriction map is injective. The stated inequality follows. \end{proof} +\begin{definition}[Annular teeth] +\label{def:annular-teeth} +By Theorem~\ref{thm:annular-medial-colour-bound} the annular medial +vertices induce the cycle $A(T)$ in $\mathsf{M}(T)$, the annular cycle, so +the edges of $\mathsf{M}(T)$ joining two annular medial vertices are +exactly the edges of $A(T)$. Each such edge lies in exactly one triangle ($3$-cycle) of +$\mathsf{M}(T)$, and the third vertex of that triangle is necessarily +non-annular, since $A(T)$ has no chords. We call this triangle an +\emph{annular tooth} and its non-annular vertex the \emph{apex} of the +tooth. + +The cycle $A(T)$ separates the plane into two regions: the \emph{outer +region}, which contains the outer-boundary medial vertices, and the +\emph{inner region}, which contains the inner-boundary medial vertices. +An annular tooth is an \emph{up tooth} if its apex lies in the outer +region, and a \emph{down tooth} if its apex lies in the inner region. +\end{definition} + +\begin{remark} +\label{rem:teeth-sharing} +The apexes of annular teeth satisfy two sharing bounds: no two up teeth +share an apex, and at most two down teeth share an apex. +\end{remark} + +\begin{remark} +\label{rem:up-teeth-count} +The number of up teeth in $\mathsf{M}(T)$ is at least three. +\end{remark} + +\begin{definition}[Bites] +\label{def:bite} +By Remark~\ref{rem:teeth-sharing} an apex is shared by at most two down +teeth. When two down teeth share an apex, the pair is called a +\emph{bite}, and their common apex is the \emph{apex of the bite}. A down +tooth that belongs to a bite is a \emph{bite tooth}. We further require the +two annular edges carrying the teeth of a bite to be \emph{non-incident}: +they share no annular vertex of $A(T)$. Equivalently, the two bite teeth +meet only at their common apex. +\end{definition} + +\begin{remark} +\label{rem:bite-face-count} +Let $B(T)$ be the subgraph of $\mathsf{M}(T)$ consisting of $A(T)$ +together with all bite apexes (equivalently, $A(T)$ together with all +bite teeth), drawn as a plane graph. For every interior face of $B(T)$ +that is not a bite tooth, the number of down teeth whose apex lies in +the interior of that face is either $0$ or at least $3$. Such an apex is +necessarily that of a singleton down tooth: every bite apex is a vertex +of $B(T)$, so it lies on a face boundary rather than in any face +interior. +\end{remark} + +\begin{figure}[h] +\centering +\begin{tikzpicture}[scale=2.3, + ann/.style={circle, fill=black, inner sep=1.1pt}, + upv/.style={circle, draw=blue!70!black, fill=blue!15, inner sep=1.5pt}, + downv/.style={circle, draw=red!70!black, fill=red!15, inner sep=1.5pt}, + bitev/.style={circle, draw=red!70!black, fill=red!35, inner sep=1.9pt}, + cyc/.style={black, line width=1.0pt}, + tth/.style={black!55, line width=0.45pt}, + lbl/.style={font=\scriptsize}, + lead/.style={black!55, line width=0.3pt}] + +% annular medial vertices forming the cycle A(T) +\foreach \k/\a in {0/105,1/75,2/45,3/15,4/-15,5/-45,6/-75,7/-105,8/-135,9/-165,10/165,11/135} + \coordinate (v\k) at (\a:1); + +% down-tooth apexes (inner region) +\coordinate (d1) at (60:0.60); +\coordinate (d2) at (30:0.60); +\coordinate (d3) at (0:0.60); +\coordinate (d4) at (-30:0.60); + +% shared apex of the bite +\coordinate (p) at (0,0); + +% up-tooth apexes (outer region) +\coordinate (u1) at (-60:1.35); +\coordinate (u2) at (-120:1.35); +\coordinate (u3) at (-150:1.35); +\coordinate (u4) at (180:1.35); +\coordinate (u5) at (150:1.35); +\coordinate (u6) at (120:1.35); + +% annular medial cycle +\draw[cyc] (v0)--(v1)--(v2)--(v3)--(v4)--(v5)--(v6)--(v7)--(v8)--(v9)--(v10)--(v11)--cycle; + +% down teeth into the right inner region +\draw[tth] (d1)--(v1) (d1)--(v2); +\draw[tth] (d2)--(v2) (d2)--(v3); +\draw[tth] (d3)--(v3) (d3)--(v4); +\draw[tth] (d4)--(v4) (d4)--(v5); + +% up teeth +\draw[tth] (u1)--(v5) (u1)--(v6); +\draw[tth] (u2)--(v7) (u2)--(v8); +\draw[tth] (u3)--(v8) (u3)--(v9); +\draw[tth] (u4)--(v9) (u4)--(v10); +\draw[tth] (u5)--(v10) (u5)--(v11); +\draw[tth] (u6)--(v11) (u6)--(v0); + +% the bite: two down teeth sharing the apex p +\draw[tth] (p)--(v0) (p)--(v1) (p)--(v6) (p)--(v7); + +% vertices +\foreach \k in {0,...,11} \node[ann] at (v\k) {}; +\foreach \u in {u1,u2,u3,u4,u5,u6} \node[upv] at (\u) {}; +\foreach \dd in {d1,d2,d3,d4} \node[downv] at (\dd) {}; +\node[bitev] at (p) {}; + +% annotations +\node[lbl, anchor=west] at (42:1.78) (Ldt) {down tooth}; +\draw[lead] (Ldt.west) -- (30:0.74); + +\node[lbl, anchor=east] at (150:1.86) (Lut) {up tooth}; +\draw[lead] (Lut.east) -- (150:1.22); + +\node[lbl] at (90:1.62) (Lbite) {bite}; +\draw[lead] (Lbite.south) -- (0,0.08); + +\node[lbl, anchor=west] at (-12:1.78) (L4) {region with 4 down teeth}; +\draw[lead] (L4.west) -- (-9:0.80); + +\node[lbl, anchor=east] at (192:1.86) (L0) {region with 0 down teeth}; +\draw[lead] (L0.east) -- (180:0.45); +\end{tikzpicture} +\caption{A full medial tire graph $\mathsf{M}(T)$ illustrating the tooth +terminology. The thick cycle is the annular medial cycle $A(T)$, whose +black vertices are the annular medial vertices. Each edge of $A(T)$ +carries one tooth: up teeth (blue apexes, outer-boundary medial vertices) +point into the outer region, and down teeth (red apexes, inner-boundary +medial vertices) point into the inner region. The two down teeth meeting +at the central shared apex (larger red vertex) form a bite; that shared +apex splits the inner region into two faces, one with four down teeth on +its boundary and one with none.} +\label{fig:medial-teeth-example} +\end{figure} + \begin{figure}[h] \centering \begin{tikzpicture}[scale=0.82,