codexfinite-field-vs-mod-four.py
finite-field-vs-mod-four.py
"""Compare F4's permutation with a collapsing map modulo four; PNG to cwd.
Tested with Python 3.14.4 and the repository's matplotlib dependency.
Field products are computed by polynomial multiplication and binary reduction.
"""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
def field_multiply(x, y):
raw = 0
for bit in range(2):
if y & (1 << bit):
raw ^= x << bit
if raw & 4:
raw ^= 0b111 # t**2 + t + 1
return raw
def node(ax, point, label, color):
ax.add_patch(Circle(point, 0.26, facecolor=color, edgecolor="#52616e", lw=1.2,
zorder=3))
ax.text(*point, label, fontsize=13 if "+" in label else 17,
ha="center", va="center", zorder=4)
def edge(ax, start, end, color, curve=0):
ax.annotate("", xy=end, xytext=start,
arrowprops={"arrowstyle": "-|>", "lw": 2.2, "color": color,
"shrinkA": 20, "shrinkB": 20, "mutation_scale": 16,
"connectionstyle": f"arc3,rad={curve}"}, zorder=2)
def loop(ax, point, color):
x, y = point
ax.annotate("", xy=(x + 0.20, y + 0.16), xytext=(x - 0.20, y + 0.16),
arrowprops={"arrowstyle": "-|>", "color": color, "lw": 2,
"mutation_scale": 15, "connectionstyle": "arc3,rad=-2.4"})
def main():
field_outputs = [field_multiply(2, x) for x in range(4)]
ring_outputs = [(2 * x) % 4 for x in range(4)]
assert field_outputs == [0, 2, 3, 1]
assert ring_outputs == [0, 2, 0, 2]
assert len(set(field_outputs)) == 4 and len(set(ring_outputs)) == 2
assert [(1 ^ 1), (1 + 1) % 4] == [0, 2]
assert [field_multiply(x, x) for x in range(1, 4)] == [1, 3, 2]
assert [x for x in range(1, 4)
if any((x * y) % 4 == 1 for y in range(1, 4))] == [1, 3]
swap = [0, 1, 3, 2]
for x in range(4):
for y in range(4):
assert swap[x ^ y] == swap[x] ^ swap[y]
assert swap[field_multiply(x, y)] == field_multiply(swap[x], swap[y])
print("Multiply by alpha in F4:", field_outputs)
print("Multiply by 2 modulo 4:", ring_outputs)
print("Checked characteristic 2 versus 4, modular units {1,3}, and alpha swap isomorphism.")
fig, axes = plt.subplots(1, 2, figsize=(10.2, 5.9), dpi=120, facecolor="white")
blue, orange = "#176997", "#a8521e"
for ax in axes:
ax.set_xlim(-2.45, 2.45)
ax.set_ylim(-1.35, 3.3)
ax.set_aspect("equal")
ax.axis("off")
left, right = axes
left.text(0, 3.05, r"Field $\mathbb{F}_4$", fontsize=19, ha="center", weight="bold")
right.text(0, 3.05, r"Ring $\mathbb{Z}/4\mathbb{Z}$", fontsize=19, ha="center", weight="bold")
left.text(0, 2.58, r"$1+1=0$ (characteristic 2)", fontsize=13, ha="center")
right.text(0, 2.58, r"$1+1=2\ne0$ (characteristic 4)", fontsize=13, ha="center")
left.text(0, 2.12, r"Multiply by $\alpha$", fontsize=14, ha="center", color=blue)
right.text(0, 2.12, "Multiply by 2", fontsize=14, ha="center", color=orange)
field_points = {0: (-1.8, 0.7), 1: (0, 1.35), 2: (-0.7, -0.25), 3: (1.35, -0.25)}
field_labels = ["0", "1", r"$\alpha$", r"$\alpha+1$"]
colors = ["#f0f2f4", "#cce8f6", "#f9ddb3", "#ded5ed"]
for x, point in field_points.items():
node(left, point, field_labels[x], colors[x])
if x:
edge(left, point, field_points[field_outputs[x]], blue, curve=0.1)
loop(left, field_points[0], blue)
ring_points = {0: (-1.2, 0), 1: (-1.2, 1.35), 2: (1.2, 0), 3: (1.2, 1.35)}
for x, point in ring_points.items():
node(right, point, str(x), colors[x])
if x:
edge(right, point, ring_points[ring_outputs[x]], orange,
curve=0.1 if x == 1 else 0)
loop(right, ring_points[0], orange)
left.text(0, -0.9, "All three nonzero elements have inverses.", ha="center", fontsize=11)
left.text(0, -1.2, "Four distinct inputs → four distinct outputs", ha="center", fontsize=11, color=blue)
right.text(0, -0.9, r"$2^2=0$: nonzero 2 has no inverse.", ha="center", fontsize=11)
right.text(0, -1.2, "Four distinct inputs → only two outputs", ha="center", fontsize=11, color=orange)
fig.suptitle("Same number of elements, different arithmetic", fontsize=18, y=0.96)
fig.subplots_adjust(left=0.035, right=0.98, top=0.89, bottom=0.065, wspace=0.12)
fig.savefig(Path.cwd() / Path(__file__).with_suffix(".png").name,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()