codexorthogonal-projection-metric-comparison.py
orthogonal-projection-metric-comparison.py
"""Original circles/ellipses of projection error; PNG basename to CWD."""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
def main():
fig, axes = plt.subplots(1, 2, figsize=(9.2, 5), dpi=120)
fig.patch.set_facecolor("white")
x = np.array([3., 1.])
e = np.array([1., 2.])
theta = np.linspace(0, 2*np.pi, 601)
cases = [
(np.array([1., 1.]), "Ordinary dot product", "(1, 2)",
r"$\|x-p\|^2=5$"),
(np.array([4., 1.]), "Weight first-coordinate errors by 4",
"(7/4, 7/2)", r"$\|x-p\|_M^2=25/2$"),
]
for ax, (weights, title, label, footer) in zip(axes, cases):
p = e*np.sum(weights*x*e)/np.sum(weights*e*e)
residual = x-p
squared_distance = np.sum(weights*residual**2)
radius = np.sqrt(squared_distance/weights)
contour = x[:, None] + radius[:, None]*np.array(
[np.cos(theta), np.sin(theta)])
ax.plot(contour[0], contour[1], color="#2878a5", lw=2)
t = np.linspace(-1.5, 2.55, 201)
ax.plot(t, 2*t, color="#888888", lw=2)
ax.plot([p[0], x[0]], [p[1], x[1]], color="#28865b",
lw=2, ls="--")
ax.scatter([x[0]], [x[1]], color="#2878a5", s=45, zorder=4)
ax.scatter([p[0]], [p[1]], color="#c05b20", s=50, zorder=4)
ax.text(3.12, 1.05, "x = (3, 1)", fontsize=11)
ax.annotate("p = " + label, p,
xytext=(.06, .89 if weights[0] == 4 else .7),
textcoords="axes fraction", fontsize=11,
color="#a74a12",
arrowprops={"arrowstyle": "->", "color": "#a74a12"})
ax.text(.5, -.25, footer, transform=ax.transAxes,
ha="center", fontsize=12)
ax.set_xlim(-.6, 5.5)
ax.set_ylim(-3, 5)
ax.set_aspect("equal")
ax.set_xlabel("First coordinate")
ax.set_ylabel("Second coordinate")
ax.set_title(title, fontsize=11.5, pad=12)
ax.grid(alpha=.17)
ax.spines[["top", "right"]].set_visible(False)
fig.suptitle("The smallest error contour touches the allowed line at the optimum",
fontsize=13, y=.98)
fig.subplots_adjust(left=.07, right=.98, top=.83, bottom=.25, wspace=.23)
fig.savefig(Path.cwd()/Path(__file__).with_suffix(".png").name,
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()