![微信图片_20260627140546_30810_42]()
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 1. 可对角化矩阵:斜向拉伸,视觉上像剪切
A = np.array([[2, 1],
[1, 2]])
eigvals, P = np.linalg.eig(A)
# 2. 原生剪切矩阵:不可对角化,真实剪切
S = np.array([[1, 1.2],
[0, 1]])
# 生成细密网格
x = np.linspace(-1, 2, 12)
y = np.linspace(-1, 2, 12)
X, Y = np.meshgrid(x, y)
pts = np.vstack([X.ravel(), Y.ravel()])
pts_A = A @ pts
pts_S = S @ pts
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14,6))
# 左图:可对角化矩阵(斜向拉伸,表观剪切)
# 原始网格线 + 放大散点
ax1.plot(X, Y, color='gray', lw=0.7, alpha=0.4)
ax1.plot(X.T, Y.T, color='gray', lw=0.7, alpha=0.4)
ax1.scatter(pts[0], pts[1], s=15, c='gray', alpha=0.7, label='原始网格点')
# 变换后网格线+散点
X_A = pts_A[0, :].reshape(X.shape)
Y_A = pts_A[1, :].reshape(Y.shape)
ax1.plot(X_A, Y_A, color='darkred', lw=0.8, alpha=0.5)
ax1.plot(X_A.T, Y_A.T, color='darkred', lw=0.8, alpha=0.5)
ax1.scatter(pts_A[0], pts_A[1], s=15, c='red', alpha=0.8, label='线性变换后点')
# 绘制两个不变特征方向
v1, v2 = P[:,0], P[:,1]
ax1.arrow(0,0,v1[0]*3, v1[1]*3, head_width=0.08, lw=2, color='blue', label='不变特征方向1')
ax1.arrow(0,0,v2[0]*3, v2[1]*3, head_width=0.08, lw=2, color='green', label='不变特征方向2')
ax1.set_title("可对角化矩阵:斜向拉伸 → 视觉表观剪切\n存在两个不变方向,换基可消除剪切", fontsize=12)
ax1.set_aspect('equal')
ax1.grid(alpha=0.3)
ax1.legend()
# 右图:原生剪切矩阵(真实剪切,不可对角化)
X_S = pts_S[0, :].reshape(X.shape)
Y_S = pts_S[1, :].reshape(Y.shape)
ax2.plot(X, Y, color='gray', lw=0.7, alpha=0.4)
ax2.plot(X.T, Y.T, color='gray', lw=0.7, alpha=0.4)
ax2.scatter(pts[0], pts[1], s=15, c='gray', alpha=0.7, label='原始网格点')
ax2.plot(X_S, Y_S, color='darkorange', lw=0.8, alpha=0.5)
ax2.plot(X_S.T, Y_S.T, color='darkorange', lw=0.8, alpha=0.5)
ax2.scatter(pts_S[0], pts_S[1], s=15, c='orange', alpha=0.8, label='线性变换后点')
ax2.arrow(0,0,3,0, head_width=0.08, lw=2, color='blue', label='唯一不变方向')
ax2.set_title("原生剪切矩阵:真实错切形变\n仅1个不变方向,无法对角化,剪切无法消除", fontsize=12)
ax2.set_aspect('equal')
ax2.grid(alpha=0.3)
ax2.legend()
plt.tight_layout()
plt.show()
print("可对角化矩阵特征值:", eigvals)
print("剪切矩阵特征值:", np.linalg.eigvals(S))