codex/integer-interval-and-batch-counts.py

integer-interval-and-batch-counts.py
"""Exact integer counts, contrasted with ceiling capacity requirements."""
from pathlib import Path
import math

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np


def main():
    plt.rcParams.update({"font.size": 11, "figure.facecolor": "white"})
    fig, (interval, batch) = plt.subplots(1, 2, figsize=(11.6, 5.8),
                                         layout="constrained")
    cases = [(-2.7, 1.1), (-2, 2), (.2, 4.7), (.2, .8)]
    lattice = np.arange(-3, 6)
    for row, (a, b) in enumerate(cases):
        y = 3 - row
        selected = lattice[(lattice >= a) & (lattice <= b)]
        count = max(0, math.floor(b) - math.ceil(a) + 1)
        assert len(selected) == count
        interval.plot(lattice, np.full_like(lattice, y), color="#d4dde1", lw=.8)
        interval.plot([a, b], [y, y], color="#c26030", lw=4,
                      solid_capstyle="butt", alpha=.7)
        interval.scatter(lattice, np.full_like(lattice, y), color="#b6c2c9",
                         s=30, zorder=3)
        interval.scatter(selected, np.full_like(selected, y), color="#167e8d",
                         s=48, zorder=4)
        endpoint_colors = ["#167e8d" if float(value).is_integer() else "#c26030"
                           for value in (a, b)]
        interval.scatter([a, b], [y, y], facecolors=endpoint_colors,
                         edgecolors="#c26030", s=43, linewidths=1.3, zorder=5)
        interval.text(-3.35, y + .30, f"[{a:g}, {b:g}]: {count} integer points",
                      fontsize=11)
    interval.set(title="Real endpoints choose the allowed integers",
                  xlabel="Real number line", xlim=(-3.5, 5.3), ylim=(-.5, 3.75),
                  xticks=lattice, yticks=[])
    interval.spines[["top", "right", "left"]].set_visible(False)
    interval.text(-3.35, -.33, "Blue points are counted; orange bars show closed intervals.",
                  fontsize=9)
    items, capacity = 102, 20
    batches = math.ceil(items / capacity)
    assert batches == 6 and (batches - 1) * capacity < items <= batches * capacity
    for index in range(batches):
        x, y = index % 3 * 1.42, 1 - index // 3 * 1.18
        used = min(capacity, max(0, items - index * capacity))
        batch.add_patch(Rectangle((x - .08, y - .08), 1.12, .92,
                                   facecolor="white", edgecolor="#8396a2", lw=1.2))
        for place in range(capacity):
            px, py = place % 5, place // 5
            batch.add_patch(Rectangle((x + .2 * px, y + .2 * py), .16, .16,
                                       facecolor="#167e8d" if place < used else "#e4ebee",
                                       edgecolor="white", lw=.4))
        batch.text(x + .46, y - .27, f"Batch {index + 1}: {used}/20",
                    ha="center", fontsize=10)
    batch.text(1.85, 2.02, r"$\lceil102/20\rceil=6$", ha="center", fontsize=17)
    batch.text(1.85, -.93, "5 full batches + 1 with two items\n18 unused places",
                ha="center", fontsize=12, linespacing=1.5)
    batch.set(title="A partly filled batch still counts as one",
               xlim=(-.26, 4.2), ylim=(-1.27, 2.35))
    batch.set_aspect("equal")
    batch.set_axis_off()
    fig.suptitle("Floor and ceiling turn boundaries into exact discrete counts", fontsize=17)
    fig.get_layout_engine().set(rect=(0, .065, 1, .90))
    fig.text(.5, .017, "Interval length differs from its integer-point count; complete groups differ from sufficient capacity.",
             ha="center", fontsize=10)
    fig.savefig(Path(__file__).with_suffix(".png").name, dpi=100, facecolor="white")
    plt.close(fig)


if __name__ == "__main__":
    main()