codexpast-exam-of-the-computer-science-course-of-the-university-of-oxford2015concurrency-2015-ring-counterexample.py
past-exam-of-the-computer-science-course-of-the-university-of-oxford/2015/concurrency-2015-ring-counterexample.py
"""Draw the three-node counterexample; Python 3.14.4, matplotlib 3.10.7.
Run from the desired output directory. Uses only the repository's declared
matplotlib dependency and writes one opaque PNG in the current directory.
"""
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, FancyArrowPatch
def main():
fig, axes = plt.subplots(1, 3, figsize=(10.2, 3.8), dpi=110)
fig.patch.set_facecolor("white")
coords = [(0, 0.8), (0.75, -0.45), (-0.75, -0.45)]
subtitles = [
"Survey starts\nring.1.true",
"Before node 2 is sampled\nactive.2",
"Node 2 forwards false\nring.0.false",
]
state_labels = [
["idle, frozen", "idle, frozen", "idle, free"],
["idle, frozen", "idle, frozen", "active, free"],
["idle, frozen", "idle, frozen", "active, frozen"],
]
for panel, ax in enumerate(axes):
ax.set(xlim=(-1.4, 1.4), ylim=(-1.2, 1.4), aspect="equal")
ax.axis("off")
ax.set_title(subtitles[panel], fontsize=11, pad=12)
for i in range(3):
j = (i + 1) % 3
ax.add_patch(FancyArrowPatch(
coords[i], coords[j], shrinkA=19, shrinkB=19,
arrowstyle="-|>", mutation_scale=15, color="#64748b",
linewidth=1.8, connectionstyle="arc3,rad=-0.15",
))
for i, (x, y) in enumerate(coords):
active = panel >= 1 and i == 2
ax.add_patch(Circle((x, y), 0.19,
facecolor="#fbd6d0" if active else "#d9eee5",
edgecolor="#a63825" if active else "#23684d",
linewidth=1.6))
ax.text(x, y, str(i), ha="center", va="center", fontsize=12)
ax.text(x, y + (0.31 if i == 0 else -0.38),
state_labels[panel][i], ha="center", va="center", fontsize=9)
if panel == 2:
ax.text(-0.95, 0.35, "false", color="#a63825", fontsize=10)
fig.suptitle("All idle at the start does not guarantee a successful survey",
fontsize=13, y=0.99)
fig.text(0.5, 0.045,
"The false decision completes a second round; no node shuts down.",
ha="center", fontsize=10)
fig.subplots_adjust(left=0.025, right=0.975, bottom=0.13, top=0.76, wspace=0.2)
fig.savefig("concurrency-2015-ring-counterexample.png", facecolor="white",
transparent=False, metadata={"Software": "codex-wiki figure generator"})
plt.close(fig)
if __name__ == "__main__":
main()