codex/linear-system-solution-sets.py

linear-system-solution-sets.py
"""Draw the three solution-set examples in linear-algebra.bigb; output to CWD.

Tested with Python 3.14.4, NumPy 2.3.5 and Matplotlib 3.10.7.
"""

from pathlib import Path

import matplotlib

matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np


def main():
    unique = np.array([[1, 1], [1, -1]])
    answer = np.linalg.solve(unique, [3, 1])
    assert np.allclose(answer, [2, 1])
    parameters = np.array([0, 1, 3])
    family = np.column_stack((3 - parameters, parameters))
    assert np.allclose(family.sum(axis=1), 3)
    incompatible = np.array([[1, 1, 3], [2, 2, 7]])
    assert np.array_equal(incompatible[1] - 2 * incompatible[0], [0, 0, 1])
    assert np.linalg.matrix_rank(incompatible[:, :2]) == 1
    assert np.linalg.matrix_rank(incompatible) == 2

    plt.rcParams.update({"font.size": 12, "figure.facecolor": "white"})
    fig, axes = plt.subplots(1, 3, figsize=(11.4, 5.0), facecolor="white")
    fig.subplots_adjust(left=0.055, right=0.985, bottom=0.24, top=0.80, wspace=0.30)
    blue, orange, ink = "#2365a0", "#c05621", "#183a2a"
    samples = np.linspace(-1, 4.5, 300)
    for ax in axes:
        ax.set_facecolor("white")
        ax.set_aspect("equal")
        ax.set_xlim(-1, 4.5)
        ax.set_ylim(-1, 4.5)
        ax.set_xticks(range(-1, 5))
        ax.set_yticks(range(-1, 5))
        ax.grid(color="#e5e5e5", lw=0.6)
        ax.axhline(0, color="#999999", lw=0.9)
        ax.axvline(0, color="#999999", lw=0.9)
        ax.set_axisbelow(True)
        ax.set_xlabel("x", labelpad=1)
        ax.set_ylabel("y", rotation=0, labelpad=8)
        ax.tick_params(labelsize=10)
        for spine in ax.spines.values():
            spine.set_color("#cccccc")

    axes[0].set_title("One solution", pad=12, fontsize=15)
    axes[0].plot(samples, 3 - samples, color=blue, lw=2.4, label=r"$x+y=3$")
    axes[0].plot(samples, samples - 1, color=orange, lw=2.4, label=r"$x-y=1$")
    axes[0].scatter(*answer, color=ink, s=55, zorder=5)
    axes[0].annotate("(2, 1)", answer, xytext=(0.35, 1.15), fontsize=12,
                     arrowprops={"arrowstyle": "-", "color": ink})
    axes[0].legend(loc="upper right", fontsize=10, framealpha=1)

    axes[1].set_title("A line of solutions", pad=12, fontsize=15)
    axes[1].plot(samples, 3 - samples, color=blue, lw=2.4, label=r"$x+y=3$")
    axes[1].scatter(family[:, 0], family[:, 1], color=ink, s=40, zorder=5)
    for xy, offset, label in zip(family, [(8, 10), (8, 10), (8, 10)],
                                  ["t = 0", "t = 1", "t = 3"]):
        axes[1].annotate(label, xy, xytext=offset, textcoords="offset points",
                         color=ink, fontsize=11)
    axes[1].legend(loc="upper right", fontsize=10, framealpha=1)

    axes[2].set_title("No solutions", pad=12, fontsize=15)
    axes[2].plot(samples, 3 - samples, color=blue, lw=2.4, label=r"$x+y=3$")
    axes[2].plot(samples, 3.5 - samples, color=orange, lw=2.4,
                 linestyle="--", label=r"$2x+2y=7$")
    axes[2].legend(loc="upper right", fontsize=10, framealpha=1)

    fig.suptitle("Linear equations: three possible solution sets", y=0.97, fontsize=19)
    for ax, text in zip(axes, ["Both equations hold at (2, 1)",
                               r"$(x,y)=(3-t,t)$ for any real $t$",
                               r"Row subtraction gives $0=1$"]):
        bounds = ax.get_position()
        fig.text((bounds.x0 + bounds.x1) / 2, 0.095, text,
                 ha="center", fontsize=12)
    fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=120,
                facecolor="white", transparent=False)
    plt.close(fig)
    print("Checked: unique (2,1); family t=0,1,3; incompatible row (0,0|1), ranks 1 and 2.")


if __name__ == "__main__":
    main()