codex/additive-energy-and-doubling.py

additive-energy-and-doubling.py
"""Compare exact counts and energy bounds; tested with Python 3.14.

Write additive-energy-and-doubling.png to the current working directory.
"""

from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np


def main():
    examples = [np.array([0, 1, 2, 3]), np.array([0, 1, 4, 10]), np.array([0, 2, 4])]
    sizes, energies, lower_bounds, upper_bounds = [], [], [], []
    for index, values in enumerate(examples):
        sums = values[:, None] + values[None, :]
        differences = values[:, None] - values[None, :]
        if index == 2:
            sums %= 6
            differences %= 6
        sums, counts = np.unique(sums, return_counts=True)
        differences, difference_counts = np.unique(differences, return_counts=True)
        energy = int(counts @ counts)
        assert energy == int(difference_counts @ difference_counts)
        sizes.append([len(values), len(sums), len(differences)])
        energies.append(energy)
        lower_bounds.append(len(values) ** 4 / len(sums))
        upper_bounds.append(len(values) ** 3)
        assert lower_bounds[-1] <= energy <= upper_bounds[-1]
    assert sizes == [[4, 7, 7], [4, 10, 13], [3, 3, 3]]
    assert energies == [44, 28, 27]
    assert np.allclose(lower_bounds, [256 / 7, 256 / 10, 27])
    assert np.allclose(np.array(sizes)[:, 1] / np.array(sizes)[:, 0], [7 / 4, 5 / 2, 1])

    plt.rcParams.update({"font.size": 11, "axes.titlesize": 14})
    fig, axes = plt.subplots(1, 2, figsize=(10, 5.8), dpi=120, facecolor="white")
    fig.suptitle("Small doubling forces large additive energy", fontsize=16, y=0.975)
    row_positions = np.arange(3)
    bar_height = 0.21
    offsets = [-0.23, 0, 0.23]
    colors = ["#bdcbd5", "#266e9e", "#cc7822"]
    ax = axes[0]
    sizes = np.array(sizes)
    for offset, color, values, label in zip(
            offsets, colors, sizes.T, [r"$|S|$", r"$|S+S|$", r"$|S-S|$"]):
        bars = ax.barh(row_positions + offset, values, height=bar_height,
                       color=color, label=label)
        ax.bar_label(bars, labels=list(map(str, values)), padding=4, fontsize=11)
    ax.set_title("Set sizes and doubling")
    ax.set_xlabel("Number of distinct elements")
    ax.set_xlim(0, 14.7)
    ax.set_xticks([0, 3, 6, 9, 12])
    ax.set_yticks(row_positions, labels=["A\nK = 7/4", "B\nK = 5/2", "H\nK = 1"])
    ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.16), ncol=3,
              frameon=False, handlelength=1.2, columnspacing=1.0)

    ax = axes[1]
    energy_colors = ["#77a89c", "#266e9e", "#bdcbd5"]
    for offset, color, values, labels, label in zip(
            offsets, energy_colors, [lower_bounds, energies, upper_bounds],
            [["256/7 ≈ 36.57", "256/10 = 25.6", "27"], ["44", "28", "27"],
             ["64", "64", "27"]],
            [r"Lower: $|S|^4/|S+S|$", r"Actual: $E(S)$", r"Upper: $|S|^3$"]):
        bars = ax.barh(row_positions + offset, values, height=bar_height,
                       color=color, label=label)
        ax.bar_label(bars, labels=labels, padding=4, fontsize=10)
    ax.set_title("Energy and its bounds")
    ax.set_xlabel("Quadruple count (bounds may be fractional)")
    ax.set_xlim(0, 86)
    ax.set_xticks([0, 16, 32, 48, 64])
    ax.set_yticks(row_positions, labels=["A", "B", "H"])
    ax.legend(loc="upper center", bbox_to_anchor=(0.5, -0.15),
              frameon=False, fontsize=10)
    for ax in axes:
        ax.set_ylim(2.55, -0.55)
        ax.spines[["top", "right", "left"]].set_visible(False)
        ax.tick_params(axis="y", length=0, pad=9)
        ax.set_axisbelow(True)
        ax.grid(axis="x", color="#e3e8eb")
    fig.text(0.5, 0.075, "A = {0, 1, 2, 3} and B = {0, 1, 4, 10}: ordinary integer addition",
             ha="center", fontsize=11)
    fig.text(0.5, 0.035, "H = {0, 2, 4} in Z/6Z: addition modulo 6; H + H = H − H = H",
             ha="center", fontsize=11)
    fig.subplots_adjust(left=0.085, right=0.97, top=0.84, bottom=0.31, wspace=0.30)
    fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name,
                facecolor="white", transparent=False)
    plt.close(fig)


if __name__ == "__main__":
    main()