codexbinary-rate-distortion-information-bound.py
binary-rate-distortion-information-bound.py
"""Fair-bit Hamming rate-distortion curve; write matching PNG to cwd."""
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt
def main():
distortion = np.linspace(0, .5, 501)
entropy = np.zeros_like(distortion)
mask = distortion > 0
entropy[mask] = (-distortion[mask] * np.log2(distortion[mask])
- (1 - distortion[mask]) * np.log2(1 - distortion[mask]))
fig, ax = plt.subplots(figsize=(9.4, 4.8), layout="constrained")
ax.plot(distortion, 1 - entropy, lw=2.6, color="#285f87",
label="Asymptotic minimum R(D) = 1 − binary entropy(D)")
ax.plot([.5, .62], [0, 0], lw=2.6, color="#285f87")
ax.fill_between(distortion, 0, 1 - entropy, color="#b45b59", alpha=.14,
label="Rates below the bound cannot meet this distortion")
points = [(0, 1, "Exact recovery\n1 bit / source symbol", (.035, .91)),
(.25, 1/3, "Three-bit majority code\nrate 1/3, average error 1/4", (.31, .50)),
(.5, 0, "Always reconstruct zero\nrate 0, average error 1/2", (.33, .12))]
for x, y, label, pos in points:
ax.scatter([x], [y], s=55, c="#bc7328", zorder=4)
ax.annotate(label, (x, y), xytext=pos, textcoords="data", fontsize=10,
arrowprops={"arrowstyle": "->", "color": ".35"})
exact = 1 + .25*np.log2(.25) + .75*np.log2(.75)
ax.plot([.25, .25], [exact, 1/3], color="#bc7328", ls="--", lw=1.4)
ax.scatter([.25], [exact], s=35, color="#285f87", zorder=4)
ax.set(xlim=(-.015, .62), ylim=(-.055, 1.10),
xlabel="Allowed average fraction of incorrect source bits D",
ylabel="Bits per original source symbol",
title="Lossy compression of independent fair bits")
ax.grid(alpha=.20)
ax.legend(loc="upper right", fontsize=9)
fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=120, facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()