codex/efron-stein-variance-and-independence.py

efron-stein-variance-and-independence.py
"""Exact variances versus coordinate replacement budgets in three toy models.

Tested with Python 3.14, matplotlib 3.10.7. Run from _media; output to CWD.
"""
from fractions import Fraction as F
from itertools import product
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Patch


def summarize(mass, marginal, function):
    mean = sum(q*function(x) for x, q in mass.items())
    variance = sum(q*(function(x)-mean)**2 for x, q in mass.items())
    halves = [sum(q*(marginal[i] if y else 1-marginal[i])
                   * (function(x)-function(x[:i]+(y,)+x[i+1:]))**2
                   for x, q in mass.items() for y in (0, 1))/2 for i in range(2)]
    return variance, halves


def main():
    p = (F(3, 10), F(3, 5))
    mass = {x: (p[0] if x[0] else 1-p[0])*(p[1] if x[1] else 1-p[1])
            for x in product((0, 1), repeat=2)}
    data = [summarize(mass, p, max), summarize(mass, p, lambda x: x[0]+2*x[1]),
            summarize({(0, 0): F(1, 2), (1, 1): F(1, 2)}, (F(1, 2), F(1, 2)), sum)]
    assert data == [(F(126, 625), [F(21, 250), F(21, 125)]),
                    (F(117, 100), [F(21, 100), F(24, 25)]), (F(1), [F(1, 4), F(1, 4)])]
    plt.rcParams.update({'font.size': 12, 'figure.facecolor': 'white', 'savefig.facecolor': 'white'})
    fig, axs = plt.subplots(1, 3, figsize=(11, 5.7), dpi=100, sharey=True)
    fig.subplots_adjust(left=0.07, right=0.98, bottom=0.27, top=0.70, wspace=0.20)
    colors = ['#1764a0', '#c56812']
    titles = ['Independent, maximum', 'Independent, weighted sum', 'Dependent, shared input']
    subtitles = [r'$Z=\max(X_1,X_2)$', r'$W=X_1+2X_2$', r'$X_1=X_2=B,\quad W=2B$']
    for ax, (variance, halves), title, subtitle in zip(axs, data, titles, subtitles):
        v = float(variance); h = list(map(float, halves)); bound = sum(h)
        ax.bar(0, v, width=0.62, color='#45596b')
        ax.bar(1, h[0], width=0.62, color=colors[0])
        ax.bar(1, h[1], bottom=h[0], width=0.62, color=colors[1])
        ax.text(0, v+0.035, f'{v:g}', ha='center', weight='bold')
        ax.text(1, bound+0.035, f'{bound:g}', ha='center', weight='bold')
        ax.set_xticks([0, 1], ['Actual\nvariance', 'Replacement\nsum'])
        ax.set(xlim=(-0.6, 1.6), ylim=(0, 1.38))
        ax.set_title(title+'\n'+subtitle, fontsize=12, pad=17)
        ax.grid(axis='y', alpha=0.18); ax.set_axisbelow(True)
        ax.spines[['top', 'right']].set_visible(False)
    axs[0].set_ylabel('Variance or half squared-change expectation')
    axs[0].text(0.5, -0.38, 'Valid bound\n0.2016 ≤ 0.252', transform=axs[0].transAxes, ha='center', color='#1764a0')
    axs[1].text(0.5, -0.38, 'Equality\n1.17 = 0.21 + 0.96', transform=axs[1].transAxes, ha='center', color='#1764a0')
    axs[2].text(0.5, -0.38, 'NOT a valid bound\n1 > 0.25 + 0.25', transform=axs[2].transAxes, ha='center', color='#b13c32', weight='bold')
    axs[2].annotate('Independence fails', xy=(1, 0.51), xytext=(0.45, 0.85), ha='center',
                    fontsize=11, color='#b13c32', arrowprops={'arrowstyle': '->', 'color': '#b13c32'})
    fig.suptitle('Efron–Stein: a variance budget needs independent inputs', y=0.96, fontsize=17)
    fig.legend(handles=[Patch(color='#45596b', label='Actual variance'),
                        Patch(color=colors[0], label='Coordinate 1 contribution'),
                        Patch(color=colors[1], label='Coordinate 2 contribution')],
               loc='upper center', bbox_to_anchor=(0.5, 0.895), ncol=3, frameon=False, fontsize=11)
    fig.text(0.5, 0.035, 'Constructed models, exact enumeration • First two: p₁ = 0.3, p₂ = 0.6. Third: P(B = 1) = 0.5.', ha='center', fontsize=11)
    fig.savefig(Path(__file__).stem+'.png', dpi=100, transparent=False)
    plt.close(fig)


if __name__ == '__main__':
    main()