codex/hoeffding-bounded-interval-exponential-tilt.py

hoeffding-bounded-interval-exponential-tilt.py
"""Exponential tilting within fixed endpoints; tested with Python 3.14.

Uses matplotlib 3.10.7 and numpy 2.3.5. Run from _media to write the matching PNG.
"""

from math import cosh, isclose, log
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np


POINTS = np.array([-2.0, 0.0, 2.0])
MASSES = np.array([0.25, 0.5, 0.25])


def tilted(parameter):
    logits = np.log(MASSES) + parameter * POINTS
    largest = np.max(logits)
    weights = np.exp(logits - largest)
    normalizer = np.sum(weights)
    return weights / normalizer, largest + np.log(normalizer)


def check_model():
    assert np.dot(POINTS, MASSES) == 0
    assert np.dot(POINTS**2, MASSES) == 2
    for parameter in np.linspace(-8, 8, 321):
        weights, psi = tilted(parameter)
        mean = np.dot(weights, POINTS)
        variance = np.dot(weights, (POINTS - mean)**2)
        assert isclose(float(np.sum(weights)), 1, abs_tol=2e-15)
        assert np.all(weights > 0)
        assert isclose(float(psi), 2 * log(cosh(parameter)), abs_tol=3e-15)
        assert isclose(float(variance), 2 / cosh(parameter)**2, rel_tol=3e-12)
        assert variance <= 4 + 1e-14
        assert psi <= 2 * parameter**2 + 1e-14
        # The second derivative computed numerically must agree with tilted variance.
        h = 0.0005
        curvature = (tilted(parameter + h)[1] - 2 * psi + tilted(parameter - h)[1]) / h**2
        assert isclose(float(curvature), float(variance), rel_tol=3e-6, abs_tol=3e-8)
    # The equal-endpoint law forces the sharp 1/8 coefficient for width four.
    parameter = 0.001
    endpoint_ratio = log(cosh(2 * parameter)) / parameter**2
    assert isclose(endpoint_ratio, 16 / 8, rel_tol=1e-6)


def main():
    check_model()
    plt.rcParams.update({"font.size": 11, "axes.spines.top": False,
                         "axes.spines.right": False, "figure.facecolor": "white",
                         "axes.facecolor": "white", "savefig.facecolor": "white"})
    fig, axes = plt.subplots(1, 2, figsize=(10.6, 4.7), layout="constrained")
    colors = ["#246d99", "#647444", "#bb5528"]
    for parameter, offset, color in zip((-1, 0, 1), (-0.37, 0, 0.37), colors):
        weights, _ = tilted(parameter)
        axes[0].bar(POINTS + offset, weights, width=0.34, color=color,
                    label=rf"$\lambda={parameter}$")
    axes[0].set(title="Tilted masses stay at the same locations", xlabel=r"Value $x$",
                ylabel=r"Tilted probability $P_\lambda(X=x)$",
                xticks=POINTS, ylim=(0, 0.85), xlim=(-2.7, 2.7))
    axes[0].legend(loc="upper center", ncol=3, fontsize=9.5)
    axes[0].text(0.5, 0.71, r"Original masses: $1/4,\ 1/2,\ 1/4$" + "\n" +
                 r"Fixed interval: $[-2,2]$, width $4$", transform=axes[0].transAxes,
                 ha="center", fontsize=10)
    parameters = np.linspace(-2, 2, 401)
    psis = np.array([tilted(t)[1] for t in parameters])
    axes[1].plot(parameters, 2 * parameters**2, lw=2.2, color="#bb5528",
                 label=r"Width-only bound: $2\lambda^2$")
    axes[1].plot(parameters, psis, lw=2.2, color="#246d99",
                 label=r"Exact: $\psi(\lambda)=2\log\cosh\lambda$")
    axes[1].set(title="A quadratic ceiling for the log moment", xlabel=r"Tilt parameter $\lambda$",
                ylabel=r"$\log E[e^{\lambda X}]$ (original mean is zero)",
                xlim=(-2, 2), ylim=(0, 8.5))
    axes[1].legend(loc="upper center", fontsize=9.5)
    axes[1].grid(alpha=0.22)
    fig.suptitle("Hoeffding's lemma: fixed width under exponential tilting", fontsize=14)
    fig.savefig(Path(__file__).stem + ".png", dpi=110, transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()