codexgraph-laplacian-connected-components.py
graph-laplacian-connected-components.py
"""Plot the kernel for two disconnected edges; write an opaque PNG in the CWD."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
def main():
incidence = np.array([[1, -1, 0, 0], [0, 0, 1, -1]])
laplacian = incidence.T @ incidence
indicators = np.array([[1, 1, 0, 0], [0, 0, 1, 1]])
assert np.array_equal(laplacian @ indicators.T, np.zeros((4, 2)))
assert np.linalg.matrix_rank(indicators) == 2
assert np.allclose(np.linalg.eigvalsh(laplacian), [0, 0, 2, 2])
colors = ["#2868a6", "#d07826"]
fig = plt.figure(figsize=(9.6, 4.8), dpi=110, facecolor="white")
grid = fig.add_gridspec(2, 2, height_ratios=[0.85, 1], hspace=0.4,
left=0.075, right=0.97, bottom=0.18, top=0.86,
wspace=0.3)
graph = fig.add_subplot(grid[0, :])
positions = [0, 0.8, 2, 2.8]
for component, (i, j) in enumerate([(0, 1), (2, 3)]):
color = colors[component]
graph.plot([positions[i], positions[j]], [0, 0], color=color,
lw=4, zorder=1)
graph.scatter([positions[i], positions[j]], [0, 0], s=850,
facecolor="white", edgecolor=color, linewidth=2,
zorder=3)
graph.text((positions[i] + positions[j]) / 2, 0.4,
f"Component {component + 1}: independent constant level",
ha="center", fontsize=12, color=color)
for x, label in zip(positions, "ABCD"):
graph.text(x, 0, label, ha="center", va="center", fontsize=15,
zorder=4)
graph.set_xlim(-0.4, 3.2)
graph.set_ylim(-0.3, 0.75)
graph.axis("off")
for k, vector in enumerate(indicators):
ax = fig.add_subplot(grid[1, k])
ax.bar(range(4), vector, color=colors[k], width=0.55)
ax.axhline(0, color="#777777", lw=0.8)
for i, value in enumerate(vector):
ax.text(i, value + 0.055, str(value), ha="center", fontsize=12)
ax.set_xticks(range(4), list("ABCD"))
ax.set_yticks([0, 1])
ax.set_ylim(-0.06, 1.35)
ax.set_title(rf"Zero eigenvector $u_{k+1}$: $Lu_{k+1}=0$",
fontsize=13)
ax.set_ylabel("Entry at vertex", fontsize=11)
ax.grid(axis="y", alpha=0.15)
fig.suptitle("Two components give a two-dimensional Laplacian kernel",
fontsize=15, y=0.965)
fig.text(0.5, 0.065,
r"Every kernel vector is $a u_1 + b u_2$: "
r"values $(a,a,b,b)$. Eigenvalues: $0,0,2,2$.",
ha="center", fontsize=12)
fig.savefig(Path.cwd() / "graph-laplacian-connected-components.png",
facecolor="white", transparent=False)
plt.close(fig)
if __name__ == "__main__":
main()