"""Generate lie-affine-noncommutation.png in the current directory. Tested with Python 3.14.4, NumPy 2.3.5, Matplotlib 3.10.7. Run from _media. Products act on column vectors, rightmost factor first. """ from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt import numpy as np def scale(a): return np.array([[np.exp(a), 0.], [0., 1.]]) def translate(b): return np.array([[1., b], [0., 1.]]) def main(): d = np.array([[1., 0.], [0., 0.]]) t = np.array([[0., 1.], [0., 0.]]) assert np.array_equal(d @ t - t @ d, t) point = np.array([1., 1.]) a = np.log(2.) first = (scale(a) @ translate(1.) @ point)[0] second = (translate(1.) @ scale(a) @ point)[0] assert np.isclose(first, 4.) and np.isclose(second, 3.) for a, b in [(np.log(2), 1.), (.1, .1), (-.2, .3)]: product = scale(a) @ translate(b) @ scale(-a) @ translate(-b) assert np.allclose(product, translate(np.expm1(a) * b)) displacement = .1 * np.expm1(.1) assert np.isclose(displacement, .010517091807564762, atol=1e-15) eps_checks = np.array([.1, .05, .01]) ratios = np.expm1(eps_checks) / eps_checks assert np.all(np.diff(np.abs(ratios - 1)) < 0) blue, orange, gray = "#276ba3", "#bf6224", "#667887" fig, axes = plt.subplots(1, 2, figsize=(10.8, 4.7), dpi=120, facecolor="white", gridspec_kw={"width_ratios": [1.2, 1]}) ax = axes[0] ax.set_title("Reverse the order, change the endpoint", fontsize=12, pad=15) ax.set(xlim=(.6, 4.4), ylim=(-.55, 2.15), xlabel="Position on the real line") ax.set_xticks([1, 2, 3, 4]) ax.set_yticks([]) ax.spines[["top", "right", "left"]].set_visible(False) for y, end, color, title, first_label, second_label in [ (1.25, 4., blue, r"Translate, then double: $S_{\log 2}U_1$", "+1", "×2"), (.1, 3., orange, r"Double, then translate: $U_1S_{\log 2}$", "×2", "+1")]: ax.axhline(y, color="#d4dce1", lw=1, zorder=0) ax.text(.72, y + .65, title, color=color, fontsize=11) for start, finish, label in [(1., 2., first_label), (2., end, second_label)]: ax.annotate("", xy=(finish - .07, y), xytext=(start + .07, y), arrowprops=dict(arrowstyle="->", color=color, lw=2)) ax.text((start + finish) / 2, y + .17, label, color=color, fontsize=12, ha="center") ax.scatter([1, 2, end], [y] * 3, color=color, s=40, zorder=5) for value in [1, 2, end]: ax.text(value, y - .27, f"{value:g}", ha="center", color=color, fontsize=12) ax = axes[1] eps = np.linspace(0., .4, 400) ax.plot(eps, eps * np.expm1(eps), color=blue, lw=2, label=r"Exact: $\varepsilon(e^\varepsilon-1)$") ax.plot(eps, eps**2, "--", color=orange, lw=2, label=r"Leading term: $\varepsilon^2$") ax.scatter([.1], [displacement], color=blue, s=35, zorder=4) ax.annotate("ε = 0.1\nshift = 0.01051709", xy=(.1, displacement), xytext=(.04, .085), fontsize=10, color=gray, arrowprops=dict(arrowstyle="->", color=gray)) ax.set(xlim=(0, .4), ylim=(0, .21), xlabel=r"Equal parameters $a=b=\varepsilon$", ylabel="Residual translation") ax.set_title("Four moves leave a second-order shift", fontsize=12, pad=15) ax.spines[["top", "right"]].set_visible(False) ax.grid(alpha=.18) ax.legend(loc="upper left", fontsize=10, frameon=False) fig.tight_layout(pad=1.5, w_pad=2) output = Path.cwd() / Path(__file__).with_suffix(".png").name fig.savefig(output, facecolor="white", transparent=False) plt.close(fig) print(f"endpoints: {first:g}, {second:g}") print(f"commutator displacement at a=b=.1 = {displacement:.12f}") print(f"displacement/epsilon^2 for .1, .05, .01 = {ratios}") print(output.name) if __name__ == "__main__": main()