codexfunction-image-preimage-subset-flow.py
function-image-preimage-subset-flow.py
"""Generate function-image-preimage-subset-flow.png in the current directory."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, FancyArrowPatch
def diagram(ax, selected_inputs, selected_outputs, heading, footer):
ys = [3, 2, 1, 0]
mapping = [0, 0, 1, 2]
blue, green, gray = "#2875ad", "#23815b", "#c4c9ce"
for i, out in enumerate(mapping):
active = i in selected_inputs and out in selected_outputs
ax.add_patch(FancyArrowPatch((0.16, ys[i]), (2.82, ys[out]),
arrowstyle="-|>", mutation_scale=14,
color=blue if active else gray,
linewidth=2.0 if active else 1.2,
zorder=2 if active else 1, shrinkA=5, shrinkB=5))
for x, labels, selected, color in [
(0, ["a", "b", "c", "d"], selected_inputs, blue),
(3, ["0", "1", "2", "3"], selected_outputs, green),
]:
for i, label in enumerate(labels):
ax.add_patch(Circle((x, ys[i]), 0.18,
facecolor=color if i in selected else "white",
edgecolor=color if i in selected else "#777777",
linewidth=1.6, zorder=3))
ax.text(x, ys[i], label, ha="center", va="center", fontsize=13,
color="white" if i in selected else "#333333", zorder=4)
ax.text(0, 3.52, "Input set A", ha="center", fontsize=12)
ax.text(3, 3.52, "Codomain B", ha="center", fontsize=12)
ax.text(1.5, 3.30, "f", ha="center", fontsize=15, style="italic")
ax.set_title(heading, fontsize=14, pad=18)
ax.text(1.5, -0.62, footer, ha="center", fontsize=12, linespacing=1.5)
ax.set(xlim=(-0.65, 3.65), ylim=(-1.25, 3.85))
ax.axis("off")
def main():
fig, axes = plt.subplots(1, 2, figsize=(10.6, 4.6), dpi=120,
facecolor="white")
diagram(axes[0], {0, 2}, {0, 1}, "Image: follow selected inputs",
"E = {a, c} → f(E) = {0, 1}")
diagram(axes[1], {0, 1, 3}, {0, 2}, "Preimage: select outputs, find every input",
"U = {0, 2} → f⁻¹(U) = {a, b, d}")
fig.suptitle("Images move forward; preimages collect inputs",
fontsize=16, y=0.98)
fig.subplots_adjust(left=0.04, right=0.98, top=0.83, bottom=0.13, wspace=0.23)
fig.text(0.5, 0.045,
"Output 0 has two inputs. Output 3 is allowed but never reached.",
ha="center", fontsize=12)
fig.savefig(Path.cwd() / "function-image-preimage-subset-flow.png",
facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()