codexmatching-augmenting-path-symmetric-difference.py
matching-augmenting-path-symmetric-difference.py
"""Original P6 alternating-path toggle from a size-two to size-three matching.
Tested with Python 3.14.4 and matplotlib 3.10.7 (project dependencies).
Run from _media; saves its own basename PNG to the current directory.
"""
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
EDGES = ((1, 2), (2, 3), (3, 4), (4, 5), (5, 6))
BEFORE = {(2, 3), (4, 5)}
AFTER = BEFORE.symmetric_difference(EDGES)
BLUE = "#1765a8"
ORANGE = "#b15d08"
def path_row(ax, y, selected, label, toggle=False):
used = {v for edge in selected for v in edge}
ax.text(0.55, y + 0.42, label, ha="left", fontsize=14, weight="bold")
for u, v in EDGES:
chosen = (u, v) in selected
color = BLUE if chosen else ORANGE if toggle else "#a4abb2"
ax.plot([u, v], [y, y], color=color,
linewidth=5.5 if chosen else 3 if toggle else 2.2,
linestyle="-" if chosen else "--", zorder=1)
if toggle:
ax.text((u + v) / 2, y - 0.3, "remove" if chosen else "add",
color=color, ha="center", fontsize=12)
for v in range(1, 7):
free = v not in used
ax.add_patch(Circle((v, y), 0.15, facecolor="#fff2d6" if free else "white",
edgecolor=ORANGE if free else BLUE,
linewidth=2.3, zorder=3))
ax.text(v, y, str(v), ha="center", va="center", fontsize=14, zorder=4)
if free:
ax.text(v, y + 0.24, "free", color=ORANGE, ha="center", fontsize=12)
def main():
plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 13})
fig, ax = plt.subplots(figsize=(9, 5.8), dpi=120, facecolor="white")
fig.subplots_adjust(left=0.045, right=0.97, top=0.85, bottom=0.18)
fig.suptitle("An augmenting path reassigns partners on P₆", y=0.965,
fontsize=18, weight="bold")
path_row(ax, 1.95, BEFORE, "Before: M = {(2,3), (4,5)} |M| = 2", toggle=True)
ax.text(3.5, 1.03, "Toggle all five path edges together: M′ = M △ E(P)",
ha="center", fontsize=14)
path_row(ax, 0, AFTER, "After: M′ = {(1,2), (3,4), (5,6)} |M′| = 3")
ax.set(xlim=(0.5, 6.5), ylim=(-0.45, 2.55), aspect="equal")
ax.axis("off")
fig.text(0.5, 0.115, "The endpoints 1 and 6 are free before the toggle; afterwards all vertices are paired.",
ha="center", fontsize=12)
fig.text(0.5, 0.055, "Three added edges − two removed edges = one extra pair.",
ha="center", fontsize=13)
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"),
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()