# 魔方里的数学：从贴纸到 Rubik 群（中学生可读版）

> 配合本地视频 `themathflow.mp4`（仅本地参考，未上传本仓库）与可运行 Python demo（`python/`）。  
> 网页交互：[index.html](index.html)；数学简报：[docs/math.md](docs/math.md)；Pages：https://weiwan-gmail.github.io/rubiks-cube-demo/teach.html  
> 本文用短段落、编号步骤、小例子，把每一个新词先讲清楚再使用。

### 如何运行 demo

网页上的 **Apply scramble / Apply inverse** 与 `python/demo.py` 是同一条路：拧乱再取逆，回到已解（单位元）。

```bash
python3 python/demo.py
python3 python/demo.py "F R U R' U' F'"
```

在仓库根目录执行（Python 3.10+，仅标准库）。完整样例见 [sample-output.txt](sample-output.txt)；步骤见 [N. 如何运行](#n-如何运行)。

---

## 目录

1. [A. 这页在讲什么](#a-这页在讲什么)
2. [B. 魔方零件](#b-魔方零件)
3. [C. 置换](#c-置换)
4. [D. 偶置换](#d-偶置换)
5. [E. 群](#e-群)
6. [F. 六个面转与 Rubik 群](#f-六个面转与-rubik-群)
7. [G. 积木群 P](#g-积木群-p)
8. [H. 同态 Φ](#h-同态-φ)
9. [I. 证明 G ⊆ ker Φ](#i-证明-g--ker-φ)
10. [J. 证明 ker Φ ⊆ G](#j-证明-ker-φ--g)
11. [K. 结论](#k-结论)
12. [L. 有限展示与路径 B](#l-有限展示与路径-b)
13. [M. 代码精讲](#m-代码精讲)
14. [N. 如何运行](#n-如何运行)
15. [O. 事实 / 假设 / 未证明清单](#o-事实--假设--未证明清单)

---

## A. 这页在讲什么

### 怎么读

请按 A→O 顺序读。遇到【事实】【约定】【证明】【代码】四种标签：

| 标签 | 含义 |
|------|------|
| 【事实】 | 标准魔方数学里可以核对的结论（与视频有没有写出公式无关） |
| 【约定】 | 我们为了解说方便做的记号选择（换记号结论不变） |
| 【证明】 | 用前面已讲的工具，一步一步推出的理由 |
| 【代码】 | 对真实文件 `python/cube.py`、`python/demo.py` 的对照说明 |

### 和视频的关系

【事实】本地短片约 15 秒，左侧是立体魔方，右侧是**三个交叠圆环**上的色点；面一转，某一环高亮，点同步滑动；还原后色点收成六个单色簇。

【事实】片内**没有文字、没有公式**。因此本文**不会发明「视频公式」**——所有公式都是标准群论写法，用来解释画面在示意什么。

【约定】把视频里的「点在环上走」理解成：一次面转把若干贴纸沿轨道轮换（见 F、M 节的 `rings_str`）。三环是投影示意，**不是**「六面各一环」。

### 「三环」只是画面，不是神秘公式

后面会用到三个**独立的**约束（奇偶、角扭转、棱翻转）。它们合起来决定「哪些乱拼状态其实拧不出来」。  
视频的三环是**可视化装饰**，与这三条约束的「数目碰巧都是 3」不要硬绑成同一个公式。

---

## B. 魔方零件

### 54 张贴纸

【事实】三阶魔方有 6 个面，每面 9 格，共

\[
6 \times 9 = 54
\]

个有色贴纸位置。Demo 里给每个位置一个编号 `0..53`。

### 三种积木

拆开看，除了贴纸，还有可动的**小块**：

| 名称 | 数量 | 每块有几色 | 直观自由度 |
|------|------|------------|------------|
| 角块 | 8 | 3 | 坐哪个角 + 扭转朝向 |
| 棱块 | 12 | 2 | 坐哪条棱 + 翻转朝向 |
| 中心块 | 6 | 1 | 定「哪面是什么颜色」的参考 |

【约定】**已解（目标）**：每个贴纸都在「出厂」位置，颜色成六个单色面。数学上把这个状态叫**单位元**（后面 E 节再正式定义）。

【事实】贴纸模型与块模型等价：贴纸跟着块走。数「有多少种可达状态」时，用块+朝向更省事；画「转一下动哪些贴纸」时，用 54 贴纸更直观。

---

## C. 置换

### 扑克例子：「重排」是什么

拿 4 张牌，按位置排成一行：位置 1、2、3、4 上分别是红桃 A、2、3、4。

现在做一次「洗牌规则」：把位置 1 的牌移到位置 2，2 移到 3，3 移到 4，4 移到 1。  
牌的**集合没变**，只是**位置换了**——这种「位置重排」就叫**置换**。

【约定】写 \(\sigma\)（读作「西格玛」）表示某一次重排规则。\(\sigma(i)=j\) 表示「原来在位置 \(i\) 的东西，被送到位置 \(j\)」。

### 轮换写法

上面那条规则可以写成一个**轮换**（cycle）：

\[
(1\ 2\ 3\ 4)
\]

读法：「1 去 2，2 去 3，3 去 4，4 回 1」。

小例子：

- \((1\ 2)\)：只交换 1 和 2，其余不动。这叫**对换**（两元轮换）。
- \((1\ 2\ 3)\)：1→2→3→1。这叫**3-轮换**。

### 复合（先做谁、后做谁）

【约定】本文写乘法 \(\sigma\tau\) 表示：**先做 \(\tau\)，再做 \(\sigma\)**（从右往左读，像函数复合 \(f(g(x))\)）。

例子：\(\tau=(1\ 2)\)，\(\sigma=(2\ 3)\)。  
对位置 1：先 \(\tau\) 得 2，再 \(\sigma\) 得 3，所以 \(\sigma\tau\) 把 1 送到 3……你可以自己把 1、2、3 各算一遍，得到 \(\sigma\tau=(1\ 3\ 2)\)。

### 逆与恒等

- **恒等置换** \(e\)：谁都不动，\(e(i)=i\)。对应「魔方已解」。
- **逆置换** \(\sigma^{-1}\)：把 \(\sigma\) 的每一步倒过来。若 \(\sigma=(1\ 2\ 3\ 4)\)，则 \(\sigma^{-1}=(4\ 3\ 2\ 1)=(1\ 4\ 3\ 2)\)。

【事实】\(\sigma\cdot\sigma^{-1}=e=\sigma^{-1}\cdot\sigma\)。

---

## D. 偶置换

### 对换与奇偶

【事实】任意置换都可以写成若干个**对换**的乘积（写法不唯一，但对换个数的**奇偶性**是唯一的）。

- 写成**偶数个**对换 → **偶置换**
- 写成**奇数个**对换 → **奇置换**

【约定】偶置换全体记作 \(A_n\)（作用在 \(n\) 个位置上时）。恒等是偶置换（0 个对换）。

### 把 4-轮换拆成对换——逐步算

【事实】任意 \(k\)-轮换都可以写成 \(k-1\) 个对换的乘积：

\[
(a_1\ a_2\ \cdots\ a_k) = (a_1\ a_k)\,(a_1\ a_{k-1})\,\cdots\,(a_1\ a_2).
\]

【证明·小例子】取 \((1\ 2\ 3\ 4)\)。按上面公式：

\[
(1\ 2\ 3\ 4) = (1\ 4)\,(1\ 3)\,(1\ 2).
\]

右边是 **3** 个对换。3 是奇数 ⇒ **4-轮换是奇置换**。

再核对一张表（务必记住）：

| 轮换长度 \(k\) | 对换个数 \(k-1\) | 奇偶 |
|----------------|------------------|------|
| 2（对换本身） | 1 | **奇** |
| 3 | 2 | **偶** |
| 4 | 3 | **奇** |

【约定】后面讲面转时会用到：一次 90° 面转在**角**上是一个 4-轮换（奇），在**棱**上也是一个 4-轮换（奇）。单独看角是奇、单独看棱也是奇，但二者奇偶**相同**——这正是不变量要保护的东西（见 I 节）。

先手头备好两件工具：

- 3-轮换 = 2 个对换 = **偶**（所以「只转三个角」这类动作在偶置换世界里是合法零件）
- 两个不相交对换 \((a\ b)(c\ d)\) = 偶（奇×奇）

---

## E. 群

### 集合 + 运算

【约定】**群**是一套「可以合在一起做、还能撤销」的规则，满足四条：

设 \(G\) 是一个集合，上面有运算 \(\cdot\)（把两个元素合成一个）：

1. **封闭**：\(a,b\in G\) ⇒ \(a\cdot b\in G\)
2. **结合律**：\((a\cdot b)\cdot c = a\cdot(b\cdot c)\)
3. **单位元**：存在 \(e\)，使 \(a\cdot e=e\cdot a=a\)
4. **逆元**：每个 \(a\) 有 \(a^{-1}\)，使 \(a\cdot a^{-1}=e\)

### 两个小例子

1. **整数加法** \((\mathbb{Z},+)\)：单位元是 0，\(5\) 的逆是 \(-5\)。结合律熟悉。
2. **置换的复合**：所有 \(\{1,\ldots,n\}\) 上的置换，在「复合」下成群，叫对称群 \(S_n\)。单位元 = 恒等；逆 = 倒着做。

【事实】偶置换全体 \(A_n\) 在复合下也成群（是 \(S_n\) 的子群）。

---

## F. 六个面转与 Rubik 群

### 面的名字

【约定】六个面（英文首字母，Singmaster 记号）：

| 字母 | 英文 | 中文 |
|------|------|------|
| U | Up | 上面 |
| D | Down | 下面 |
| L | Left | 左面 |
| R | Right | 右面 |
| F | Front | 前面 |
| B | Back | 后面 |

【约定】\(U\) 表示「上面顺时针转 90°」（从该面外侧看）。\(U'\) 或 \(U^{-1}\) = 逆时针 90°；\(U^2\) = 180°。

### 一次面转如何动贴纸

【事实】转某一个面 90° 时：

1. **本面** 8 张非中心贴纸：4 个角位置做一个 4-轮换，4 个棱位置做另一个 4-轮换；中心贴纸不动。
2. **侧面一圈**：与该面相邻的四条「边」上的贴纸，再做成若干个 4-轮换（代码里 `_U_side` 等）。

合计：一次 90° 面转通常动 **20** 张贴纸（8 本面 + 12 侧面），中心不动。

### 生成元与 Rubik 群

【约定】把六个面转看成六个置换，叫**生成元**。

【事实】**Rubik 群** \(G\) 是「所有能由面转一个接一个拧出来的动作」全体：

\[
G = \langle U, D, L, R, F, B \rangle
\]

也就是：所有形如「若干个面转（含逆、180°）乘在一起」的置换。

- 单位元 \(e\) = **已解**
- \(G\) 里的每个元素 = 一个**可达状态**（从已解拧出来）

【代码】`GENERATORS` 存六个顺时针 90°；`MOVES` 再补上 `U'`、`U2` 等。

---

## G. 积木群 P

若允许**拆开再任意装回去**（不要求能面转拧到），则自由度更大。

【事实】粗算「积木乱拼」空间大小：

- 8 个角任意排位置：\(8!\)
- 每个角 3 种扭转：\(3^8\)
- 12 条棱任意排位置：\(12!\)
- 每条棱 2 种翻转：\(2^{12}\)

于是定义**积木群**（更大的构型集合，运算是「先装成状态再复合」的抽象）

\[
|P| = 8! \cdot 3^8 \cdot 12! \cdot 2^{12}.
\]

【事实】面转能达到的 \(G\) **严格小于** \(P\)：有些乱拼状态永远拧不出来（例如只交换两块角）。下一节用同态把「差在哪里」说清楚。

数值上后面会得到 \(|G|=|P|/12\)。

---

## H. 同态 Φ

### 什么是同态

【约定】两个群之间的映射 \(\Phi:P\to H\) 叫**同态**，若对任意 \(x,y\in P\)：

\[
\Phi(xy)=\Phi(x)\,\Phi(y).
\]

白话：先在 \(P\) 里复合再映射 = 先映射再在 \(H\) 里复合。同态会「保留运算结构」，并自动把单位元送到单位元。

【约定】**核** \(\ker\Phi=\{x\in P:\Phi(x)=e_H\}\)。同态的核一定是子群；后面证明 \(G=\ker\Phi\)。

### 目标群 \(C_2\times C_3\times C_2\)

【约定】

- \(C_2=\{0,1\}\) 模 2 加法（奇偶）
- \(C_3=\{0,1,2\}\) 模 3 加法（扭转）
- 直积 \(C_2\times C_3\times C_2\)：三个分量各自运算、互不干扰

### 三个分量怎么从状态算

对积木状态 \(x\in P\)，定义 \(\Phi(x)=(\varepsilon(x),\,t(x),\,f(x))\)：

1. **\(\varepsilon(x)\)**（置换奇偶，取值在 \(C_2\)）  
   看角块位置置换的奇偶，与棱块位置置换的奇偶是否相同。  
   【约定】常见取法：\(\varepsilon=0\) 表示「角偶且棱偶」（或更一般：角与棱奇偶一致）；\(\varepsilon=1\) 表示不一致。  
   【事实】可达状态必须角与棱的奇偶**一致**（可以都偶，也可以像一次 90° 面转后那样都奇）。

2. **\(t(x)\)**（角扭转和，取值在 \(C_3\)）  
   每个角给扭转量 \(0,1,2\)（相对「正确朝向」转了多少个 120°），然后

   \[
   t(x)=\sum_{i=1}^{8} o_i \bmod 3.
   \]

3. **\(f(x)\)**（棱翻转和，取值在 \(C_2\)）  
   每条棱翻转 \(0\) 或 \(1\)，然后

   \[
   f(x)=\sum_{j=1}^{12} f_j \bmod 2.
   \]

### 为何 \(\Phi(xy)=\Phi(x)\Phi(y)\)

【证明思路】（直觉版，严格形式化属进阶）

- 先做 \(y\) 再做 \(x\)：角/棱的**位置置换**是复合，奇偶相加（模 2）→ \(\varepsilon\) 同态。  
- 扭转：后做的动作在「已被前一动作挪到新位置的角」上再扭；按标准朝向规则计数时，扭转量对模 3 **可加** → \(t\) 同态。  
- 翻转同理对模 2 可加 → \(f\) 同态。

因此三个分量合起来 \(\Phi\) 是同态。

【事实】\(\ker\Phi\) 正好是「奇偶正确、扭转和为 0、翻转和为 0」的那些积木状态，大小为 \(|P|/12\)（因为 \(|C_2\times C_3\times C_2|=2\cdot3\cdot2=12\)，且 \(\Phi\) 是满同态）。

---

## I. 证明 G ⊆ ker Φ

要证：每个**面转**（因而它们生成的整个 \(G\)）都落在核里，即 \(\Phi(\text{面转})= (0,0,0)\)。

只需检查六个生成元 \(U,D,L,R,F,B\)（逆与平方会自动继承）。

### 1）置换奇偶：90° 面转保持「角与棱奇偶一致」

【证明】固定转上面 \(U\) 90°（其它面同理）：

1. **角块**：上层四个角走一个 4-轮换，下层不动。  
   4-轮换 = 3 个对换 = **奇**置换。  
2. **棱块**：上层四条棱同样走一个 4-轮换 = **奇**置换。  

于是这次面转之后：角奇、棱奇——二者**仍然一致**。  
若 \(\varepsilon=0\) 表示「一致」、\(\varepsilon=1\) 表示「不一致」，则 \(\varepsilon(U)=0\)。

【事实·可用代码核对】对已解做一次 \(U\)，角置换奇偶与棱置换奇偶都变成 1（奇），但仍匹配；做 \(U^2\) 则二者都回到 0（偶）。见 `python/cube.py` 的不变量检查思路。

【直观】面转不可能「只交换两个角却动都不动棱」——那种会让 \(\varepsilon=1\)，落在核外面，也就不在 \(G\) 里。

（有些科普书写成「角、棱置换都必须是偶置换」。更精确的说法是：**二者奇偶必须相同**；90° 后面转可以同时为奇。计数 \(|P|/2\) 时，等价于「先任选棱排列，再只允许一半的角排列」。）

### 2）扭转和：90° 面转不改变 \(\sum o_i \bmod 3\)

【证明·直观计数】转 \(U\) 时，下层四角不动（扭转 0）。上层四角：每个角块被带走时，相对「上下颜色朝上/朝下」的参考，扭转量会变，但四个角的扭转变化之和是 \(0 \bmod 3\)。

直觉：整圈对称，不可能只「凭空扭出一个角的总量」；计算上四个角各贡献的扭转增量之和被 3 整除。  
故 \(t(U)=0\)。其它面同理（转哪一面，就看那一面周围四个角的扭转增量）。

### 3）翻转和：90° 面转不改变 \(\sum f_j \bmod 2\)

【证明·直观计数】转 \(U\) 时，四条上层棱走一圈：在标准「好翻转」定义下，这四条棱的翻转位要么都不变，要么成对改变，总和模 2 为 0。侧面竖直棱不动。故 \(f(U)=0\)。

【结论】每个生成元在 \(\ker\Phi\) 里 ⇒ 它们生成的 \(G\subseteq\ker\Phi\)。

---

## J. 证明 ker Φ ⊆ G

反过来：凡是满足三条不变量的积木状态，都**可以**用面转拧出来。证明策略是**构造性还原**：给出四步，说明如何把任意核里的状态拧回已解（从而该状态 = 某面转词的结果 ∈ \(G\)）。

### 四步还原大纲

| 步骤 | 目标 | 为何核条件够用 |
|------|------|----------------|
| 1 | 把 8 个角放到正确位置（暂不管朝向） | 角置换是偶的 ⇒ 可分解为 3-轮换乘积 |
| 2 | 把 12 条棱放到正确位置（暂不管翻转） | 棱置换是偶的；且与角奇偶已匹配 |
| 3 | 拧正所有角朝向 | 扭转和 ≡0 (mod 3) ⇒ 可成对/三元组修正 |
| 4 | 翻正所有棱朝向 | 翻转和 ≡0 (mod 2) ⇒ 可成对修正 |

下面解释「为什么需要偶置换」以及「交换子」思想。**不**在此列出每个算法的完整 20 步公式（那是进阶查表）；但讲清逻辑，并说明 demo **只验证生成元与逆，不实现求解器**。

### 交换子思想 \(ABA^{-1}B^{-1}\)

【约定】**交换子** \([A,B]=ABA^{-1}B^{-1}\)。

白话：

1. 做动作 \(A\)（弄乱一小块区域）  
2. 做 \(B\)（把「被弄乱的部分」换到别处，或换一组块进来）  
3. 做 \(A^{-1}\)：在**新位置**上把那套弄乱**撤销**——于是原来位置大多恢复，只在 \(A\) 与 \(B\) 「交叠」的地方留下小尾巴  
4. 做 \(B^{-1}\)：再把架子挪回去  

结果：大部分贴纸回到原处，只留下一个**小循环**（常见是角上的 3-轮换，或棱上的 3-轮换）。

【事实】魔方竞速里许多「只动三个角、其它看起来不动」的公式，本質上都是交换子（或交换子的变体）。因此：

> 「存在角 3-循环算法」不是魔法名字，而是：**用交换子可以把面转组合成只含一个 3-轮换（外加可能的朝向变化）的元素**；这类元素确实属于 \(G\)（因为由面转拼成）。

Demo 不实现这些长公式；它只确认：单步面转是置换、序列可逆、回到已解。

### 为何偶置换够用、奇置换不够

【事实】3-轮换是偶置换，且 \(A_n\)（\(n\ge 3\)）由 3-轮换生成。

- 若角的位置置换是**偶**的，就可写成若干角 3-轮换之积；每个 3-轮换原则上对应某种交换子型面转词 ⇒ 能还原位置。  
- 若只交换**两个**角（其余不动），这是奇置换，**不在** \(A_8\) 里，也无法写成 3-轮换之积——这正是「拆开对调两角再粘上」拧不回去的原因。

棱同理。又因 \(\varepsilon\) 要求角、棱奇偶一致，不会出现「角偶但棱奇」这种核外观。

### 扭两角 / 翻两棱生成核的朝向部分

【事实】

- 不能只扭**一个**角（\(t\neq 0\)）；但可以找到面转词，效果是「扭角 A +1、扭角 B −1（或等价地两个角同向配平到和为 0）」——这类元素生成扭转核。  
- 不能只翻**一条**棱；但可以「同时翻两条棱」，生成翻转核。

【约定】上文「这类动作确实可用面转写出」在完整群论证明里需要显式公式或引用已知生成结果；中学课标下把它标为【事实·可查证】，完整字面公式见进阶附录或标准教材（如「角扭转交换子」「棱翻转算法」）。本课路径强调：**核的条件恰好是这些生成过程能走通的充要障碍**。

### 与 demo 的分工

【代码】`demo.py` 流程：已解 → `R U R' U'` → 检查不变量 → 逆序列 → 已解。  
它验证「生成元作用 + 逆 = 单位」，**不是**完整四步求解器。断言函数 `assert_reachable_invariants` 只抽查核条件的一部分（见 M 节）。

---

## K. 结论

【证明】由 I：\(G\subseteq\ker\Phi\)。由 J：\(\ker\Phi\subseteq G\)。故

\[
G=\ker\Phi.
\]

【事实】\(\Phi:P\to C_2\times C_3\times C_2\) 满射时，

\[
|G|=|\ker\Phi|=\frac{|P|}{|C_2\times C_3\times C_2|}=\frac{|P|}{12}.
\]

代入 \(|P|=8!\cdot 3^8\cdot 12!\cdot 2^{12}\) 得

\[
|G|=43{,}252{,}003{,}274{,}489{,}856{,}000
\]

（约 \(4.3\times 10^{19}\)）。这是标准计数，**不是**视频里写出的数（视频没有数）。

---

## L. 有限展示与路径 B

【事实】把六个面转看成自由群 \(F\) 的生成元，则有满同态 \(F\to G\)，其核 \(N=\ker(F\to G)\) 是「所有乘起来等于已解（单位元）的面转词」组成的正规子群。

因 \(G\) 有限，存在**有限展示**：有限条关系 \(r_1=\cdots=r_m=1\)，使 \(N\) 等于它们的正规闭包（允许拿关系去共轭再相乘）。故「所有 =1 的词都能由这几条关系复合出来」在群论意义上成立。

【约定·路径 B】相对「用三条不变量刻画 \(G=\ker\Phi\)」（本文主路径），路径 B 强调：用生成元 + 关系表呈现同一个 \(G\)。实务上关系表很长；工程与中学演示更常用不变量路径。仅 \(U^4=1\) 与「对面可交换」等局部关系**不足以**穷尽 \(N\)。

【视频观察】短片不涉及展示或关系表；它只是生成元作用的示意。

---

## M. 代码精讲

对照真实文件：

- `python/cube.py`
- `python/demo.py`

### M1. 编号 facelet / FACES / SOLVED_COLORS

【代码】

```python
FACES = ("U", "D", "L", "R", "F", "B")
N_STICKERS = 54
SOLVED_COLORS = "".join(f * 9 for f in FACES)  # 54 个字符

def facelet(face: str, i: int) -> int:
    return FACE_INDEX[face] * 9 + i
```

白话：六个面按 U,D,L,R,F,B 顺序，每面本地格子 `0..8`（看该面时的行列）：

```
0 1 2
3 4 5
6 7 8
```

绝对编号 = `面序号×9 + 本地号`。已解时颜色就用面字母自己：上面九格全是 `"U"`，等等。

### M2. `_perm_from_cycles`：轮换 → 数组

【代码】

```python
def _perm_from_cycles(cycles):
    perm = list(range(54))          # 先做成恒等
    for cycle in cycles:
        for a, b in zip(cycle, cycle[1:]):
            perm[a] = b
        perm[cycle[-1]] = cycle[0]  # 最后回到开头
    return perm
```

白话：`perm[i] = σ(i)`。若轮换是 `(10, 11, 12, 13)`，则 `perm[10]=11`, `perm[11]=12`, `perm[12]=13`, `perm[13]=10`。

### M3. `_face_cw_cycles` 与 `_U_side` 等

【代码】本面两个 4-轮换（角与棱）：

```python
# 角：0→2→8→6→0 ；棱：1→5→7→3→1
```

侧面例如 `_U_side`：上面顺时针时，F/L/B/R 的顶行三条边各自做一个 4-轮换。  
`_build_generators` 把「本面轮换 + 侧面轮换」拼起来，得到 `GENERATORS["U"]` 等。

### M4. GENERATORS / MOVES / invert / U'

【代码】

```python
GENERATORS = _build_generators()   # 六个 90° 顺时针
MOVES = all_moves()                # 含 U, U', U2, …
# U' = invert_perm(U 的数组)
# U2 = U 复合两次
```

白话：`U'` 是把箭头全部反转；数组上：若 `p[i]=j`，则逆置换满足 `inv[j]=i`。

### M5. `apply`：`new[perm[i]] = old[i]` 的几何含义

【代码】

```python
def apply(state, move):
    perm = MOVES[move]
    new = [""] * 54
    for i, color in enumerate(state):
        new[perm[i]] = color
    return new
```

白话：原来在位置 `i` 的那张颜色贴纸，被搬到位置 `perm[i]`。  
所以新数组在下标 `perm[i]` 处应写上旧的 `state[i]`。这与「置换作用在位置上」的几何一致。

### M6. `apply_sequence` / `inverse_sequence`

【代码】序列从左到右依次 `apply`。  
逆序列：颠倒顺序，并对每个记号取逆（`R`↔`R'`，`R2` 仍是 `R2`）。

例：`R U R' U'` 的逆是 `U R U' R'`。

### M7. `is_solved` 与 demo 流程

【代码】`is_solved`：颜色数组是否等于 `SOLVED_COLORS`。

`demo.py` 五步：

1. 打印模型与六个生成元动了多少贴纸  
2. 已解状态 + 三环 ASCII  
3. 拧 `R U R' U'`，检查不变量，打印展开图与贴纸表  
4. 施加逆序列  
5. 断言回到已解  

### M8. `rings_str`：三环 ASCII 与视频对齐

【代码】取 U/R/F 三个生成元里各一条**棱 4-轮换**，打印当前颜色：

```text
Three interlocking rings (edge 4-cycles from U / R / F):
  U-ring: (… → …)
  R-ring: (… → …)
  F-ring: (… → …)
```

【约定】这是呼应视频「三环」的示意，不是六面六环，也不声称等于 Cayley 图。

### M9. `assert_reachable_invariants` 在查什么

【代码】根据角/棱贴纸颜色集合，恢复角置换与棱置换，然后检查：

1. 角置换奇偶 **等于** 棱置换奇偶  
2. 角扭转和 \(\equiv 0\pmod{3}\)  
3. 棱翻转和会计算但不作为硬失败条件（实现注释写明 facelet 规则较细、避免误杀）

合法面转序列后这些应成立；用手拆出「只换两角」的状态则会触发断言。

---

## N. 如何运行

网页与 Python 对照：在 [交互 demo](index.html) 上点 **Apply scramble** / **Apply inverse**，对应 `python/demo.py` 的「拧乱 → 取逆 → 已解」。默认拧法都是 `R U R' U'`。

在仓库根目录执行（Python 3.10+，仅标准库；有 `.venv` 也可用其中的解释器）：

```bash
python3 python/demo.py
python3 python/demo.py "F R U R' U' F'"
```

等价写法：`cd python && python3 demo.py`。完整样例输出（默认 scramble）见 [sample-output.txt](sample-output.txt)。摘录：

```
3. Scramble: R U R' U'
tokens: ['R', 'U', "R'", "U'"]
...
solved=False  stickers_off_home=12

4. Inverse sequence → expect solved
inverse tokens: ['U', 'R', "U'", "R'"]
...
solved=True  stickers_off_home=0

5. Result
scramble then inverse returns to solved: True
OK — face turns permute stickers; inverse restores identity.
```

`themathflow.mp4` 只作本地参考，不随本仓库上传；片内无文字、无公式，本文不发明「视频公式」。

---

## O. 事实 / 假设 / 未证明清单

### 【事实】清单

- 54 贴纸；8 角、12 棱、6 中心  
- 面转是置换；\(G=\langle U,D,L,R,F,B\rangle\)；单位元 = 已解  
- \(|P|=8!\cdot 3^8\cdot 12!\cdot 2^{12}\)；\(|G|=|P|/12\) 及精确大数  
- 三条不变量：角/棱置换奇偶一致、扭转和 ≡0 (mod 3)、翻转和 ≡0 (mod 2)  
- 视频：三交叠环、无文字公式（画面观察见 `docs/math.md` 的【视频观察】；本仓库未收录独立 `video-notes.md`）  
- demo 验证生成元与逆，不是完整求解器  

### 【假设 / 约定】清单

- 视频三环 = 生成元轮换轨道的投影示意（非官方定理）  
- 复合顺序、扭转符号（+1/−1）的具体标定  
- \(\varepsilon\) 分量「一致/不一致」的 0/1 编码细节  

### 【未在本文逐步写出公式】清单（进阶可查）

- 每个显式的角 3-循环 / 棱 3-循环面转词（交换子展开后的完整步骤表）  
- 扭两角、翻两棱的标准竞速公式全文  
- \(\Phi\) 作为同态的逐块代数验证  
- 用生成元逐一验算「角奇偶始终等于棱奇偶」的完整表格式细账（本文 I 节已给 90° 直观论证）  
- Rubik 群的显式有限展示关系表（路径 B 的全表）  

这些不影响主线：\(G=\ker\Phi\) 与 \(|G|=|P|/12\) 的逻辑骨架，以及代码与三环可视化。

---

## 路径索引

| 文件 | 路径 |
|------|------|
| 本文 Markdown | [teach.md](teach.md)（站点根目录） |
| 本文 HTML | [teach.html](teach.html) |
| 交互 demo | [index.html](index.html) |
| 数学简报 | [docs/math.md](docs/math.md) |
| Python 参考 | `python/cube.py`、`python/demo.py` |
| 样例输出 | [sample-output.txt](sample-output.txt) |
| 视频 | `themathflow.mp4` 仅本地参考（未上传） |
