codex/past-exam-of-the-groups-and-representations-course-of-the-university-of-oxford/2023-dynkin-diagrams.py

past-exam-of-the-groups-and-representations-course-of-the-university-of-oxford/2023-dynkin-diagrams.py
"""Draw the numbered diagrams used in the 2023 Oxford solutions.

Tested with Python 3.14, NumPy 2.3.5 and Matplotlib 3.10.7.
The only output is a PNG in the caller's current directory.
"""

from pathlib import Path

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt


def diagram(ax, positions, edges, title, removed=None):
    for a, b in edges:
        x1, y1 = positions[a]
        x2, y2 = positions[b]
        muted = removed in (a, b)
        ax.plot([x1, x2], [y1, y2], color="#bbbbbb" if muted else "#25364a",
                linewidth=2, linestyle="--" if muted else "-", zorder=1)
    for label, (x, y) in positions.items():
        ax.scatter([x], [y], s=240, facecolor="white",
                   edgecolor="#bf3939" if label == removed else "#25364a",
                   linewidth=2, zorder=2)
        ax.text(x, y + .30, str(label), ha="center", va="bottom", fontsize=13)
        if label == removed:
            ax.plot([x-.13, x+.13], [y-.13, y+.13], color="#bf3939", linewidth=2, zorder=3)
            ax.plot([x-.13, x+.13], [y+.13, y-.13], color="#bf3939", linewidth=2, zorder=3)
    ax.set_title(title, fontsize=13, pad=17)
    ax.set_xlim(-.5, 3.9)
    ax.set_ylim(-1.45, 1.6)
    ax.set_aspect("equal")
    ax.axis("off")


fig, axes = plt.subplots(1, 3, figsize=(10.8, 3.5), facecolor="white")
diagram(axes[0], {1:(0,0), 2:(1.4,0), 3:(2.8,0)}, [(1,2),(2,3)], r"$A_3$")
d5 = {1:(0,0), 2:(1.15,0), 3:(2.3,0), 4:(3.4,.85), 5:(3.4,-.85)}
diagram(axes[1], d5, [(1,2),(2,3),(3,4),(3,5)], r"$D_5$")
extended = {0:(0,.85), 1:(0,-.85), 2:(1.15,0), 3:(2.3,0), 4:(3.4,.85), 5:(3.4,-.85)}
diagram(axes[2], extended, [(0,2),(1,2),(2,3),(3,4),(3,5)],
        r"Extended $D_5$: delete node 2", removed=2)
axes[2].text(1.5, -1.6, r"$A_1\oplus A_1\oplus A_3$", ha="center", fontsize=13)
fig.subplots_adjust(left=.025, right=.99, top=.85, bottom=.17, wspace=.2)
fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name,
            dpi=120, facecolor="white", transparent=False,
            metadata={"Software":"Oxford 2023 Dynkin diagram generator"})
plt.close(fig)