codex/percolation-monotone-grid.py

percolation-monotone-grid.py
"""A seeded monotone coupling on one finite nearest-neighbor square box."""

from pathlib import Path

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import numpy as np


def root_cluster(edges, opened, root):
    neighbors = {}
    for (a, b), keep in zip(edges, opened):
        if keep:
            neighbors.setdefault(a, []).append(b)
            neighbors.setdefault(b, []).append(a)
    reached, stack = {root}, [root]
    while stack:
        for neighbor in neighbors.get(stack.pop(), []):
            if neighbor not in reached:
                reached.add(neighbor)
                stack.append(neighbor)
    return reached


def main():
    size = 17
    edges = []
    for x in range(size):
        for y in range(size):
            if x+1 < size:
                edges.append(((x, y), (x+1, y)))
            if y+1 < size:
                edges.append(((x, y), (x, y+1)))
    labels = np.random.default_rng(20261011).uniform(size=len(edges))
    root = (size//2, size//2)
    previous = {root}
    color = "#b55d20"
    fig, axes = plt.subplots(1, 3, figsize=(11.4, 4.4), dpi=120)
    for ax, p in zip(axes, [.3, .5, .7]):
        opened = labels <= p
        cluster = root_cluster(edges, opened, root)
        assert previous.issubset(cluster)
        previous = cluster
        assert opened.sum() >= len(cluster)-1
        ax.add_collection(LineCollection([edge for edge, keep in zip(edges, opened) if keep],
                                        colors="#c3cdd4", linewidths=1.4))
        cluster_edges = [edge for edge, keep in zip(edges, opened)
                         if keep and edge[0] in cluster]
        ax.add_collection(LineCollection(cluster_edges, colors=color, linewidths=1.8))
        points = np.array(sorted(cluster))
        ax.scatter(points[:, 0], points[:, 1], s=9, color=color, zorder=3)
        ax.scatter(*root, marker="*", s=140, color="#243746", edgecolor="white",
                   linewidth=.8, zorder=4)
        ax.set(xlim=(-.7, size-.3), ylim=(-.7, size-.3))
        ax.set_aspect("equal")
        ax.axis("off")
        ax.set_title(f"p = {p:.1f}\nRoot cluster: {len(cluster)} of {size**2} vertices",
                     fontsize=12)
    fig.suptitle("Raise the threshold; keep the same random edge labels", fontsize=15)
    fig.text(.5, .045, "Orange: connected to the root ★    Gray: other open edges    "
             "Finite box; no inference of infinite percolation", ha="center", fontsize=10)
    fig.subplots_adjust(left=.025, right=.975, bottom=.12, top=.77, wspace=.12)
    fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name, facecolor="white")
    plt.close(fig)


if __name__ == "__main__":
    main()