# SINDy 与 SR 背景知识

## 文档作用

这份文档只负责一件事：**给正在工作的 coder 提供背景知识、已经确认的经验、已踩过的坑和当前结论强度。**

它不是任务清单，不直接安排“下一步做什么”。凡是执行顺序、阶段划分、最小交付物，统一写在 `sindy_sr_notes`。这份 knowledge 只保留：

- 已确认的技术事实
- 历史错误与纠正
- 结果该如何理解
- 哪些话可以说，哪些话现在还不能说
- 代码和实验上最容易踩的坑

---

## 一、这条线在项目里的位置

SINDy 与 SR 不是独立课题，而是 pinball 后处理主线中的一段工具链。项目真正要解释的是：

\[
\text{obs} \rightarrow \text{act} \rightarrow \text{flow structure} \rightarrow \text{signature}
\]

SINDy 与 SR 当前只直接处理其中的 `obs -> act` 白箱化，但它们的价值在于：

- 检验控制是否真的依赖少数物理量
- 识别不同 cloak 场景中是否复用了同一类反馈结构
- 为后续把控制律与 force、mean wake、observable-related structure 接起来提供接口

因此，任何 SINDy/SR 结果都不应脱离项目总体物理主线单独解读。

---

## 二、当前已经确认的技术事实

### 1. Kármán cloak 的跨 \(Re_D\) 统一骨架存在

这是目前最硬的一批证据之一。跨 Re 的 leave-one-Re-out，尤其 holdout_200，已经显示：

- 用 Re50 + Re100 拟合，可高精度预测 Re200
- 这说明统一骨架不是偶然的特征工程产物，而是真实存在于 PPO 策略中的共享结构

### 2. 对称性问题已经纠偏

最重要的 bug 是镜像变换 \(G\) 对动作的写法错误。

**错误版本**：

\[
[a_F,a_T,a_B] \mapsto [-a_F,a_B,a_T]
\]

**正确版本**：

\[
[a_F,a_T,a_B] \mapsto [-a_F,-a_B,-a_T]
\]

也就是说：

- top / bottom 不仅交换
- 三个动作都要变号

修正后，rear equivariance 误差从约 100% 降到约 10%，原来“PPO 不尊重交换对称性”的结论应正式撤回。

当前应保留的结构关系是：

\[
\alpha_F(Gx) \approx -\alpha_F(x)
\]

\[
\alpha_B(x) \approx -\alpha_T(Gx)
\]

### 3. front no-bias 被数据支持

front 通道不需要常偏置。去掉 bias 后：

- one-step 基本不变
- 关键闭环也基本不变

因此，front odd structure 现在可以作为默认先验，而不是可选修饰。

### 4. rear shared-head 不是纯粹美学约束，而是有效结构

`bottom(x) = -top(Gx)` 的结构不是只让模型更优雅，它在闭环里确实提供了稳健性。v23 的结果说明：

- 结构约束有助于防止 rear 两通道在闭环中各走各路
- 它比无结构的独立 rear 拟合更适合作为解释模型

### 5. 无量纲化不是问题根源

这件事已经确认，不应再反复争论。

- \(u \to u/U_0\)
- \(F \to C_D, C_L\)
- \(\Omega \to \alpha\)

这些都是可逆缩放，不会丢失信息。早期 v3 崩坏来自：

- 错误 \(G\)
- 多项改动一次性叠加

而不是无量纲化本身。

### 6. one-step 与闭环是两回事

这是这条线最重要的工作方法教训之一：

\[
\text{one-step R² 高} \not\Rightarrow \text{闭环好}
\]

早期 v3(old) 就是明确反例。因此：

- one-step 只能说明局部拟合能力
- 闭环验证是核心证据，不是附加项

### 7. PySR 现在可用

之前关于“PySR 不可用”的说法应删除。当前已知：

- `sr_env` 下 PySR 可用
- 后续 SR 主工具应优先考虑 PySR
- threshold Pareto 扫描仍有价值，但不能再混称为完整 SR

---

## 三、哪些结论现在还不能说得太满

### 1. “所有 cloak 已经共享同一骨架”

还不能这么说。当前最强证据只够支持：

- Kármán cloak 跨 \(Re_D\) 统一骨架成立
- steady 初步显示出明显简化版结构

但 all-cloak 统一骨架仍是当前主问题，不是已证结论。

### 2. “steady cloak 已经严格证明是 Kármán 的子模型”

这个说法也太满。更稳的表述是：

- 在当前 steady 数据定义下，steady 的 support 呈现出 Kármán support 的明显简化版
- 这支持 `shared backbone + scene-specific activation` 方向

但 steady 当前的证据强度仍弱于 Kármán，因为 steady 不是同类 DRL 闭环策略数据。

### 3. “高 Re 退化已经证明是采样率问题”

现在还不能这么写。更稳的说法是：

- 这是一个强工作假设
- 需要在时间尺度显式化后重新检验

### 4. “SR 已经做完一轮”

如果实际做的只是 threshold 网格 + Pareto 分析，就不能写成“完整 SR 已完成”。

要区分：

- `threshold Pareto scan`
- `true constrained SR`

---

## 四、统一变量与约束的背景知识

### 1. primitive variables 应统一

后续所有 cloak 场景都应基于同一批 primitive variables：

- \(\hat u, \hat v\)
- \(C_D, C_L\)
- \(\alpha\)
- lagged \(\alpha\)
- \(\Delta\alpha\)
- \(\mu = 1/Re_D\)
- scene metadata 与 \(\Delta t_c\)

### 2. \(G\) 算子必须在 primitive level 定义

不要再直接对压缩特征猜符号。统一规则为：

| 量 | 变换 |
|---|---|
| \((u_B,u_C,u_T)\) | \((u_T,u_C,u_B)\) |
| \((v_B,v_C,v_T)\) | \((-v_T,-v_C,-v_B)\) |
| \((C_{D,F},C_{D,T},C_{D,B})\) | \((C_{D,F},C_{D,B},C_{D,T})\) |
| \((C_{L,F},C_{L,T},C_{L,B})\) | \((-C_{L,F},-C_{L,B},-C_{L,T})\) |
| \((\alpha_F,\alpha_T,\alpha_B)\) | \((-\alpha_F,-\alpha_B,-\alpha_T)\) |
| lag / increment | 同动作规则 |
| \(\mu\) | 不变 |

并且：

\[
G(G(x)) = x
\]

必须作为基本测试。

### 3. 默认结构约束

当前最稳的默认结构是：

- front no-bias
- front odd structure
- rear shared-head

即：

\[
\alpha_T(x)=g_R(x),
\qquad
\alpha_B(x)=-g_R(Gx)
\]

不再把三通道完全独立当默认。

---

## 五、SINDy 与 SR 的正确分工

### SINDy 负责什么

SINDy 的主要价值是：

- 在受限物理库上识别主项
- 给出 support 证据
- 支持跨场景比较
- 给 SR 提供 whitelist

SINDy 是骨架识别器，不是最终公式生成器。

### SR 负责什么

SR 的价值不止是压短公式。它还可以：

- 吸收若干看似分散的 SINDy 项
- 暴露不同场景是否存在同形公式
- 给出比 threshold scan 更强的闭式线索

因此 SR 应该在受限物理库上做，而不是在 raw feature 上自由乱搜。

---

## 六、时间尺度问题的背景知识

### 1. 当前公式混有采样周期信息

lagged action 和 \(\Delta a\) 都隐式绑定了 control interval。也就是说，当前公式里混着：

- 物理骨架
- 离散实现方式
- 采样周期

因此时间尺度问题是结构问题，不是附带工程问题。

### 2. 控制频率测试的严格原则

不能把在 800-step cadence 下拟合出的系数，直接拿到 400-step 或 200-step cadence 下执行，并把结果当正式证据。因为此时：

- 输入分布变了
- memory 项的物理意义变了
- \(\Delta a\) 的尺度也变了

因此，如果要比较不同 control interval，必须：

1. 在目标 \(\Delta t_c\) 下重新采集特征
2. 重新拟合模型
3. 再比较 support、系数结构与闭环

之前的频率扫描结果最多只能当线索，不能当结论。

---

## 七、steady 结果应该怎样理解

当前 steady 的结果有启发性，但需要克制解释。

可以说：

- steady front 全零很合理
- steady rear 比 Kármán 更简单
- steady 当前 support 呈现出 Kármán 的明显简化版

不宜说：

- steady 已经严格证明是 Kármán 的子模型
- steady 与 Kármán 现在证据强度相同

因为 steady 当前的数据来源与 Kármán 不完全对等。

---

## 八、代码与工程层面的已知经验

### 1. 环境分工

- `pycuda_3_10`：CFD、DRL 模型加载、数据采集、SINDy
- `sr_env`：PySR 与 SR 相关工作

### 2. 常见坑

- feature names 与矩阵列顺序不一致
- JSON 保存时未统一处理 numpy 类型
- 不同脚本用不同 channel 命名规则
- 没有统一 validator，导致 \(G\) 与闭环输入错位难以及早发现

### 3. 推荐工程习惯

- 任何场景都先过 validator，再进拟合
- separate fit 的结果按场景 × 方法存储
- support、公式、闭环三类结果必须一起保存

---

## 九、当前最值得牢记的判断

这条线现在最稳的总结是：

\[
\boxed{
\text{Kármán cloak 的跨 }Re_D\text{ 统一骨架已确认，且满足明确的镜像等变结构；v23 是当前最可信的解释模型。}
}
\]

同时必须保留另一句：

\[
\boxed{
\text{all-cloak 的最终 shared backbone 还没有定论；steady、单涡、时间尺度显式化与真正的受限 SR 仍在探索中。}
}
\]

这两句话一起保留，能避免后续工作再次滑向“把局部结果写成全局结论”。