codexapproximate-spectral-vectors.py
approximate-spectral-vectors.py
"""Write approximate-spectral-vectors.png to cwd; Python 3.14, NumPy, Matplotlib."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def interval(lam, epsilon):
a, b = max(0.0, lam - epsilon), min(1.0, lam + epsilon)
length = b - a
residual = np.sqrt(((b - lam) ** 3 - (a - lam) ** 3) / (3 * length))
return a, b, length**-0.5, residual
def main():
plt.rcParams.update({"font.size": 11, "axes.titlesize": 13})
colors = ["#1765a8", "#bc570e", "#853795"]
epsilons = [0.2, 0.1, 0.05]
fig, axes = plt.subplots(1, 3, figsize=(11.2, 4.7), facecolor="white")
fig.subplots_adjust(left=0.065, right=0.985, bottom=0.23, top=0.77, wspace=0.38)
fig.suptitle("Concentrate a unit vector to make its spectral residual small", fontsize=15, y=0.96)
for ax, lam, heading in zip(axes[:2], [0.5, 0.0], ["Interior: λ = 1/2", "Endpoint: λ = 0"]):
for epsilon, color in zip(epsilons, colors):
a, b, amplitude, residual = interval(lam, epsilon)
ax.plot([a, a, b, b], [0, amplitude, amplitude, 0], color=color, lw=2,
label=rf"$\varepsilon={epsilon:g}$")
ax.set_title(heading)
ax.set_xlim(-0.025, 1.025)
ax.set_ylim(-0.12, 4.95)
ax.set_xticks([0, 0.5, 1])
ax.set_xlabel("x")
ax.set_ylabel(r"$u_{\lambda,\varepsilon}(x)$")
ax.text(0.53 if lam == 0 else 0.98, 4.3,
r"$\int_0^1 |u|^2\,dx=1$", ha="center" if lam == 0 else "right", fontsize=11)
ax.grid(color="#e7ebef", lw=0.7)
ax.spines[["top", "right"]].set_visible(False)
axes[0].legend(loc="upper left", fontsize=10, frameon=False)
ax = axes[2]
epsilon_grid = np.linspace(0, 0.22, 200)
ax.plot(epsilon_grid, epsilon_grid, "--", color="#919ba5", lw=1.5, label=r"Bound $\varepsilon$")
ax.plot(epsilon_grid, epsilon_grid / np.sqrt(3), color="#3e4954", lw=2,
label=r"Exact $\varepsilon/\sqrt{3}$")
for epsilon, color in zip(epsilons, colors):
ax.scatter([epsilon], [interval(0.5, epsilon)[3]], color=color, s=65, zorder=5)
ax.set_title("Residual for both panels")
ax.set_xlabel(r"Interval radius $\varepsilon$")
ax.set_ylabel(r"$\|(M-\lambda I)u\|_2$")
ax.set_xlim(0, 0.22)
ax.set_ylim(0, 0.23)
ax.set_xticks([0, 0.1, 0.2])
ax.grid(color="#e7ebef", lw=0.7)
ax.spines[["top", "right"]].set_visible(False)
ax.legend(loc="upper left", fontsize=10, frameon=False)
fig.text(0.5, 0.09, r"Amplitude = (interval length)$^{-1/2}$; clipping at an endpoint halves the interval length.",
ha="center", fontsize=12)
fig.text(0.5, 0.025, "Every vector has norm one, but no nonzero L² eigenvector exists at the limit.",
ha="center", fontsize=12)
fig.savefig(Path.cwd() / "approximate-spectral-vectors.png", dpi=145, facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()