从‘旋转正方形’到‘魔方公式’:用Python代码可视化理解群同构与同态
数学中的群论常被视为抽象难懂的领域,但当我们用代码将群的结构可视化时,这些概念会突然变得清晰起来。本文将带你用Python构建两个具体的群实例——正方形的旋转对称群和模4加法群,通过动画演示和交互式操作,直观感受群同构与同态的本质区别。无论你是正在学习抽象代数的学生,还是对数学可视化感兴趣的编程爱好者,这些可运行的代码示例都将为你打开一扇理解群论的新窗口。
1. 准备工作:搭建Python数学可视化环境
1.1 安装必要库
我们需要以下Python库来实现数学可视化:
pip install numpy matplotlib ipywidgets sympy1.2 创建基础绘图函数
先定义一个绘制正方形的函数,它将作为我们可视化旋转群的基础:
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation def draw_square(ax, rotation=0): """绘制旋转指定角度的正方形""" square = np.array([[1,1], [-1,1], [-1,-1], [1,-1], [1,1]]) rotation_matrix = np.array([ [np.cos(rotation), -np.sin(rotation)], [np.sin(rotation), np.cos(rotation)] ]) rotated_square = np.dot(square, rotation_matrix) ax.clear() ax.plot(rotated_square[:,0], rotated_square[:,1], 'b-') ax.set_xlim(-2, 2) ax.set_ylim(-2, 2) ax.set_aspect('equal') ax.grid(True) ax.set_title(f'旋转角度: {np.degrees(rotation):.0f}°')2. 构建正方形旋转对称群
2.1 定义群元素与运算
正方形的旋转对称群由四个旋转操作组成:
- 0°旋转(恒等元)
- 90°旋转
- 180°旋转
- 270°旋转
这些旋转操作构成一个四阶循环群,记作C₄。我们可以用Python类来表示这个群:
class RotationGroup: def __init__(self): self.elements = { 0: lambda x: x, 1: lambda x: (x + 1) % 4, 2: lambda x: (x + 2) % 4, 3: lambda x: (x + 3) % 4 } def operate(self, a, b): """群的二元运算:旋转的复合""" return self.elements[b](a)2.2 可视化群运算
让我们创建一个动画来展示这些旋转操作:
fig, ax = plt.subplots(figsize=(6,6)) rotations = [0, np.pi/2, np.pi, 3*np.pi/2] def animate(i): draw_square(ax, rotations[i % 4]) ani = FuncAnimation(fig, animate, frames=4, interval=1000, repeat=True) plt.show()提示:在实际Jupyter Notebook中运行这段代码,你会看到一个正方形依次旋转90°的动画效果。
3. 构建模4加法群
3.1 定义模4加法群
模4加法群(ℤ/4ℤ)由四个余数类组成:
- [0] = {..., -4, 0, 4, ...}
- [1] = {..., -3, 1, 5, ...}
- [2] = {..., -2, 2, 6, ...}
- [3] = {..., -1, 3, 7, ...}
其群运算为模4加法。Python实现如下:
class Mod4Group: def __init__(self): self.elements = [0, 1, 2, 3] def operate(self, a, b): """群的二元运算:模4加法""" return (a + b) % 43.2 可视化群运算关系
我们可以用Cayley表来展示这个群的结构:
| + | 0 | 1 | 2 | 3 |
|---|---|---|---|---|
| 0 | 0 | 1 | 2 | 3 |
| 1 | 1 | 2 | 3 | 0 |
| 2 | 2 | 3 | 0 | 1 |
| 3 | 3 | 0 | 1 | 2 |
4. 建立群同构:旋转群与模4加法群
4.1 构造同构映射
我们发现旋转群C₄和模4加法群ℤ/4ℤ之间存在一个自然的双射:
| 旋转群元素 | 模4群元素 |
|---|---|
| 0°旋转 | 0 |
| 90°旋转 | 1 |
| 180°旋转 | 2 |
| 270°旋转 | 3 |
这个映射保持群运算关系,Python实现如下:
def is_isomorphic(group1, group2, mapping): """验证两个群是否同构""" for a in group1.elements: for b in group1.elements: # 检查运算是否保持 if mapping[group1.operate(a,b)] != group2.operate(mapping[a], mapping[b]): return False return True rotation_group = RotationGroup() mod4_group = Mod4Group() mapping = {0:0, 1:1, 2:2, 3:3} # 简单的恒等映射 print(f"两群是否同构: {is_isomorphic(rotation_group, mod4_group, mapping)}")4.2 可视化同构关系
我们可以创建一个双重动画来展示这种对应关系:
def combined_animation(i): plt.clf() # 绘制旋转正方形 plt.subplot(1,2,1) draw_square(plt.gca(), rotations[i % 4]) # 绘制模4加法表示 plt.subplot(1,2,2) plt.text(0.5, 0.5, f"[{i % 4}]", fontsize=40, ha='center', va='center') plt.xlim(0,1) plt.ylim(0,1) plt.axis('off') plt.title('模4加法群元素') plt.figure(figsize=(10,5)) ani = FuncAnimation(plt.gcf(), combined_animation, frames=4, interval=1000, repeat=True) plt.show()5. 探索群同态:从旋转群到模2加法群
5.1 构造同态映射
现在考虑一个不那么严格的双射关系——同态。我们定义从旋转群C₄到模2加法群ℤ/2ℤ的映射:
| 旋转群元素 | 模2群元素 |
|---|---|
| 0°旋转 | 0 |
| 90°旋转 | 1 |
| 180°旋转 | 0 |
| 270°旋转 | 1 |
这个映射不是双射(因为不是单射),但它保持群运算:
mod2_group = Mod4Group() # 重用之前的类,只需模2运算 def homomorphism(x): """从旋转群到模2群的同态映射""" return x % 2 # 验证同态性质 for a in range(4): for b in range(4): assert homomorphism(rotation_group.operate(a,b)) == mod2_group.operate(homomorphism(a), homomorphism(b))5.2 可视化同态关系
创建一个三重可视化来展示这种关系:
def triple_animation(i): plt.clf() # 旋转正方形 plt.subplot(1,3,1) draw_square(plt.gca(), rotations[i % 4]) # 模4表示 plt.subplot(1,3,2) plt.text(0.5, 0.5, f"[{i % 4}]", fontsize=30, ha='center', va='center') plt.xlim(0,1) plt.ylim(0,1) plt.axis('off') # 模2表示 plt.subplot(1,3,3) plt.text(0.5, 0.5, f"[{i % 2}]", fontsize=30, ha='center', va='center') plt.xlim(0,1) plt.ylim(0,1) plt.axis('off') plt.figure(figsize=(15,5)) ani = FuncAnimation(plt.gcf(), triple_animation, frames=8, interval=1000, repeat=True) plt.show()6. 进阶应用:魔方群中的同态
6.1 简化魔方群模型
考虑魔方的一个简化模型——只允许面旋转。我们可以定义六个基本旋转:
- F (前面顺时针)
- B (后面顺时针)
- U (上面顺时针)
- D (下面顺时针)
- L (左面顺时针)
- R (右面顺时针)
每个旋转操作都可以看作群元素,连续旋转就是群运算。
6.2 建立颜色同态
定义一个从魔方群到颜色置换群的同态:
- 每个面旋转会改变特定颜色块的位置
- 映射规则:跟踪中心块的颜色变化
class RubiksGroup: def __init__(self): self.faces = ['U', 'D', 'L', 'R', 'F', 'B'] self.colors = {'U':'yellow', 'D':'white', 'L':'red', 'R':'orange', 'F':'green', 'B':'blue'} def rotate(self, face): """执行面旋转并返回颜色变化""" # 简化的颜色变化规则(仅考虑中心块) color_changes = { 'U': {'F':'R', 'R':'B', 'B':'L', 'L':'F'}, 'D': {'F':'L', 'L':'B', 'B':'R', 'R':'F'}, # 其他面旋转规则类似... } new_colors = self.colors.copy() if face in color_changes: for src, dest in color_changes[face].items(): new_colors[dest] = self.colors[src] self.colors = new_colors return new_colors6.3 可视化魔方同态
虽然完整实现魔方可视化较复杂,但我们可以展示颜色映射的变化:
rubiks = RubiksGroup() print("初始颜色:", rubiks.colors) rubiks.rotate('U') print("U旋转后:", rubiks.colors)这个颜色映射就是一个从魔方旋转群到颜色置换群的同态——它保持群运算,但不是双射(因为多个旋转可能导致相同的颜色置换)。