codex/quadratic-integer-embeddings.py

quadratic-integer-embeddings.py
"""Draw the coefficient lattice and both real embeddings of Z[sqrt(2)].

PNG output goes to the current working directory.
Tested with Python 3.14.4, NumPy 2.3.5, and Matplotlib 3.10.7.
"""

from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
import numpy as np


def main():
    root_two = np.sqrt(2)
    transform = np.array([[1, root_two], [1, -root_two]])
    coefficients = np.array([(a, b) for a in range(-8, 9) for b in range(-8, 9)])
    images = coefficients @ transform.T
    cell = np.array([[0, 0], [1, 0], [1, 1], [0, 1]])
    assert np.isclose(abs(np.linalg.det(transform)), np.sqrt(8))
    assert np.allclose(images[:, 0] * images[:, 1],
                       coefficients[:, 0]**2 - 2 * coefficients[:, 1]**2)

    plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
                         "axes.spines.right": False})
    fig, axes = plt.subplots(1, 2, figsize=(10.2, 5.3), dpi=120)
    colors = ["#186b9c", "#a65419", "#853a96", "#16815a"]
    marked = [(1, 0), (0, 1), (1, 1), (3, 2)]
    labels = [r"$1$", r"$\sqrt{2}$", r"$1+\sqrt{2}$", r"$3+2\sqrt{2}$"]
    offsets = [[(8, -19), (-15, 12), (9, 10), (-74, 12)],
               [(-13, 14), (-35, -23), (11, -20), (-72, 30)]]
    for panel, ax in enumerate(axes):
        points = coefficients if panel == 0 else images
        ax.scatter(points[:, 0], points[:, 1], s=12, color="#b3bec8", zorder=2)
        ax.add_patch(Polygon(cell if panel == 0 else cell @ transform.T,
                             facecolor="#dbeaf7", edgecolor="#48779a", linewidth=1.6,
                             zorder=1))
        ax.axhline(0, color="#c0c7ce", lw=0.8)
        ax.axvline(0, color="#c0c7ce", lw=0.8)
        for k, (pair, label, color) in enumerate(zip(marked, labels, colors)):
            point = np.array(pair) if panel == 0 else transform @ pair
            ax.scatter(*point, s=65, color=color, zorder=4)
            ax.annotate(label, point, xytext=offsets[panel][k],
                        textcoords="offset points", color=color, fontsize=12,
                        bbox={"facecolor": "white", "edgecolor": "none", "pad": 1},
                        arrowprops={"arrowstyle": "-", "color": color} if k == 3 else None,
                        zorder=5)
        ax.set_aspect("equal")
        ax.grid(alpha=0.12)
    axes[0].set(xlim=(-3.5, 4.5), ylim=(-3.5, 4.5), xlabel=r"coefficient $a$",
                ylabel=r"coefficient $b$", title=r"$a+b\sqrt{2}$: integer coefficients")
    axes[0].set_xticks(range(-3, 5))
    axes[0].set_yticks(range(-3, 5))
    axes[1].set(xlim=(-7.5, 7.5), ylim=(-7.5, 7.5), xlabel=r"$x=a+b\sqrt{2}$",
                ylabel=r"$y=a-b\sqrt{2}$", title=r"Both embeddings: $N=xy$")
    for sign, color in [(1, "#16815a"), (-1, "#853a96")]:
        for branch in [-1, 1]:
            x = branch * np.geomspace(1 / 7.5, 7.5, 350)
            axes[1].plot(x, sign / x, color=color, lw=1, alpha=0.65, zorder=0)
    axes[1].text(-7, 6.7, r"$xy=-1$", color="#853a96", fontsize=11)
    axes[1].text(4.7, 6.7, r"$xy=1$", color="#16815a", fontsize=11)
    fig.suptitle(r"One quadratic integer, two real values", fontsize=16, y=0.97)
    fig.text(0.5, 0.035, r"Shaded basis cells: area $1$ on the left, $2\sqrt{2}$ on the right."
             "  Colored points represent the same elements.", ha="center", fontsize=11)
    fig.subplots_adjust(left=0.065, right=0.98, bottom=0.17, top=0.85, wspace=0.27)
    fig.savefig(Path.cwd() / "quadratic-integer-embeddings.png", facecolor="white",
                transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()