"""Draw finite failure-event budgets and their exact complements. Run from _media. Tested with Python 3.14.4, matplotlib 3.10.7, numpy 2.3.5. Every outcome has probability 1/20 in each of the two illustrative models. """ from fractions import Fraction from pathlib import Path import matplotlib.pyplot as plt from matplotlib.patches import Patch, Rectangle import numpy as np def main(): plt.rcParams.update({"font.size": 11, "font.family": "DejaVu Sans"}) omega = set(range(1, 21)) cases = [ ("Separate failure outcomes", [{1}, {2}, {3}], Fraction(3, 20)), ("One shared failure outcome", [{1}, {1}, {1}], Fraction(1, 20)), ] colors = ["#276888", "#ba6421", "#8150a5"] fig, axes = plt.subplots(1, 2, figsize=(10.8, 6.8), facecolor="white") fig.subplots_adjust(left=0.04, right=0.97, bottom=0.10, top=0.80, wspace=0.18) fig.suptitle("Three failure allowances, one simultaneous-success guarantee", fontsize=15, y=0.97) fig.text(0.5, 0.915, "20 equally likely outcomes; each P(Fᵢ) = 1/20; total budget = 3/20", ha="center") fig.legend(handles=[Patch(facecolor=c, label=f"Failure F{i + 1}") for i, c in enumerate(colors)], loc="upper center", bbox_to_anchor=(0.5, 0.887), ncol=3, frameon=False) for ax, (title, events, expected) in zip(axes, cases, strict=True): union = set().union(*events) exact = Fraction(len(union), len(omega)) budget = sum((Fraction(len(event), len(omega)) for event in events), Fraction()) success = Fraction(len(omega - union), len(omega)) assert exact == expected and budget == Fraction(3, 20) assert success == 1 - exact and success >= 1 - budget ax.set(xlim=(-0.65, 4.70), ylim=(-3.5, 4.2), aspect="equal") ax.axis("off") ax.set_title(title, fontsize=13, pad=6) ax.add_patch(Rectangle((-0.54, 0.12), 5.08, 3.98, facecolor="white", edgecolor="#8a919c", lw=1)) for index, outcome in enumerate(sorted(omega)): x, y = index % 5, 3.55 - index // 5 ax.add_patch(Rectangle((x - 0.39, y - 0.34), 0.78, 0.76, facecolor="#fff3e7" if outcome in union else "white", edgecolor="#586273", lw=0.9)) ax.text(x, y + 0.14, str(outcome), ha="center", va="center", fontsize=11) for i, event in enumerate(events): ax.add_patch(Rectangle((x - 0.30 + 0.21 * i, y - 0.21), 0.17, 0.12, facecolor=colors[i] if outcome in event else "white", edgecolor=colors[i], lw=0.7)) ax.text(2, -0.13, f"{len(union)} failure outcomes; {len(omega - union)} success outcomes", ha="center", fontsize=11) for y, value, label, color in [ (-0.65, exact, "Exact any-failure probability", "#1b627f"), (-1.50, budget, "Union bound / total budget", "#a65b20"), ]: ax.text(-0.48, y + 0.28, f"{label}: {value}", fontsize=11) ax.add_patch(Rectangle((-0.48, y - 0.10), 4.94, 0.20, facecolor="#f0f1f3", edgecolor="none")) ax.add_patch(Rectangle((-0.48, y - 0.10), 4.94 * float(value), 0.20, facecolor=color, edgecolor="none")) for tick in np.array([0, 0.5, 1.0]): ax.plot([-0.48 + 4.94 * tick] * 2, [-1.70, -1.61], color="#586273", lw=0.8) ax.text(-0.48 + 4.94 * tick, -1.93, f"{tick:g}", ha="center", fontsize=9) ax.text(2, -2.55, f"Exact all-success probability: {success}", ha="center", fontsize=12) ax.text(2, -3.0, "Guaranteed all-success probability: at least 17/20", ha="center", fontsize=11) fig.text(0.5, 0.035, "Colored marks show event membership. The budget is valid under either pattern of dependence.", ha="center", fontsize=11) destination = Path.cwd() / (Path(__file__).stem + ".png") fig.savefig(destination, dpi=100, facecolor="white", transparent=False) plt.close(fig) print(destination) if __name__ == "__main__": main()