Virtual Embryo Challenge更新于 10-03 19:58(北京时间) / 每 5 分钟更新

总览 · ← 返回运行 20261003-171955-search-t2-embryo-interp-chain-12h

节点 n31 在终选来历上

在父节点27位移管线上,把逐类型Δ改为范数保持、支持集受限的基因相关扩散方向校正 Δ'=renorm(Δ+η·C·Δ)(仅|Δ|≥0.15基因,η=1,C=括号两阶段全细胞的基因-基因Pearson相关),使位移方向对齐组织内协同变化程序;PLAN字面的通路投影因位移在伪批量中精确对消而被证否,改交此备选解码。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261003-171955-search-t2-embryo-interp-chain-12h
父节点n27
子节点n34、n36
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 63.07(+0.5) · proxy 63.07(+0.5) · 3 次复测均分 62.87
审查通过 检查1(越界读取):未发现问题。run.py 仅经 load_manifest/read_stage/panel_genes 从 --data 视图读取;prior 文件读取(run.py:244 tf_regulons、run.py:357/362 prior/*.gmt)均用 os.path.join(view, rel),全在视图内;无绝对路径、.. 、/mnt、/home、data/raw、downloads、打分器路径,无网络下载(grep 无 requests/urllib/http/socket/subprocess)。; 检查2(硬编码目标统计量):未发现问题。提交的 COR…
用时?从运行开始到结束(或到现在)的挂钟时间。1 小时 17 分
程序版本bfb3e3fe864409da30abbc4b52e1ae814efda104 (programs.git)

方法说明?节点程序自带的 METHOD.md:这个程序做了什么、为什么。

来自 programs.git bfb3e3fe86:solution/METHOD.md

在父节点27位移管线上,把逐类型Δ改为范数保持、支持集受限的基因相关扩散方向校正 Δ'=renorm(Δ+η·C·Δ)(仅|Δ|≥0.15基因,η=1,C=括号两阶段全细胞的基因-基因Pearson相关),使位移方向对齐组织内协同变化程序;PLAN字面的通路投影因位移在伪批量中精确对消而被证否,改交此备选解码。

  • family_id: T2EI-01
  • parent: node 27(A 半 seed0 = 61.48,B 半 62.55)
  • mechanism_off_control: --ablate mechanism(等价 T2_PROJ_ETA=0)→ Δ'=Δ,输出与父节点 27 逐位一致(已验证,含 seed 0/1)

1. 提交机制(CORRPROJ,默认打开)

位置:mix_converge 的逐类型位移步之前(软权重、α=5、λ=6、β=0.2、nnz-only、clip≥0 全部保留不变)。

对每个共有类型(两侧各 ≥10 细胞)的 Δ = μ_b − μ_a:

  1. C = 括号两阶段全部细胞合并后的基因-基因 Pearson 相关矩阵(498×498,对角置 0),只依赖视图输入数据,现场计算;
  2. Δ_diff = Δ + η·C·Δ(一步扩散,η=1);
  3. 支持集限制:只有 |Δ_g| ≥ 0.15(T2_PROJ_SUPPORT)的基因取 Δ_diff,其余基因保持测得的 Δ_g——不招募新基因、不翻转弱基因符号;
  4. 范数保持:Δ' = Δ_diff·‖Δ‖/‖Δ_diff‖——只改方向不改幅度(不加此步时扩散把幅度放大 ~10 倍,表达值爆到 147(父节点 max 32.6),mmd_u 从 0.0117 崩到 0.0210)。

参数(run.py 默认值,环境变量可覆写):T2_PROJ_MODE=corr、T2_PROJ_ETA=1.0、T2_PROJ_SUPPORT=0.15、T2_PROJ_NORM=1、T2_PROJ_CORR_KERNEL=all。无新增随机源,seed 确定(已验证 seed 0 重跑逐位一致)。

2. PLAN 被证否的过程(结构原因 + 离线筛选)

PLAN 的字面机制(通路 boost 进 Δ)实现后离线筛选发现结构性对消:分层混抽的 (1−t, t) 权重使逐细胞位移在输出伪批量中精确抵消,而 de_score / de_direction 只看 dp = pb(pred) − pb(ref)。因此任何只改 Δ 方向(不改幅度、不改 nnz/clip 非线性)的校正对 dp 几乎不可见:

  • 通路版(Reactome top-k 二元 boost,k∈{20,30,50},η∈{1,2};GO-BP k∈{30,100},η∈{1,2,4},graded/graded_max 两种解码)共 8 个离线配置:|dp| top-50 集合变化 ≤2 个基因(PLAN 自己的放弃线 <2),cos(Δ,Δ')≥0.90,boost 均值 0.005–0.085——方向无效;
  • 其中 1 个配置送查分存档:reactome η=2 k=20 → 60.86(劣于父节点,见 §5 表 #17);
  • 相关版字面实现(Δ'=Δ+ηCΔ,无范数保持):η=0.1 → 60.09(de_score 0.2857 但 mmd_u 崩),说明其 dp 变化全部来自幅度爆炸的 clip 整流,不是方向。

按任务书规则(≥3 种解码/幅度组合、≥6 次查分)判定 PLAN 字面方向无效后,改交针对同一弱项(expression_change / de_score 排序错位)的备选解码:把"相关先验校正位移方向"从幅度爆炸中剥离(范数保持 + 支持集限制),这是同一机制家族的合法解码变体。

3. 机制生效证据

  • 实际改变了什么:每个共有类型的 Δ 方向被转动(cos(Δ,Δ') 均值 0.86、最小 0.82,>0.5 且 <1,符合 PLAN 的预期区间);受影响细胞 = 全部 10 个共有类型的输出细胞(a 侧 3000 + b 侧 2000,位移量随 Δ' 方向变);坐标、细胞抽取、nnz 结构不变(nnz 0.0590→0.0567,来自 Δ' 方向改变后 clip 位置的微小变化)。
  • dp 层:|dp| top-50 变化 2–3 个基因(过了 PLAN 的 ≥2 筛选线),de_score raw 0.25→0.2857(seed 0)、0.2143→0.25(seed 1)。
  • 四组分(A 半,seed 0,本节点 vs 父节点):expression_change 62.16→62.31(de_score +0.17,de_direction −0.07);cell_state 50.36→50.29(variogram +0.12,mmd_u −0.08);local_spatial 60.37→60.61(neighborhood_mmd raw 0.05505→0.05158,+0.40 points);shape_scale 77.31→77.31(坐标未动,符合设计)。总分 61.48→62.06。
  • 跨 seed 一致性:seed 1 配对比较 61.55 vs 父节点 60.93(+0.63);seed 0 +0.58。收益主要来自 neighborhood_mmd(+0.34~0.40)、de_score(+0.17)、variogram(+0.12~0.19),代价是 mmd_u(−0.06~0.08)与 de_direction(−0.04~0.07)——两次查分模式一致,非单 seed 尖峰。

4. 调参轨迹(support / η / 核)

配置A 半总分
support 0.25, η=161.89
support 0.25, η=261.86
support 0.15, η=1(提交)62.06
support 0.1, η=162.04
support 0.15, within-type 核61.85

support 0.1–0.15 是平台(差 0.03,噪声内),取 0.15;η 在 1→2 已饱和(范数保持下方向变化封顶);within-type 残差核(去掉类型间组成结构)略差于全细胞核,说明组成间共变结构本身有用。

5. 全部查分记录(A 半 proxy,seed 0 除注明外;共 18 次,余 2)

#配置总分de_score rawde_dir rawmmd_u rawvariogram rawnbhd raw
1父节点/off(逐位一致验证)61.480.25000.38790.011670.014320.05505
2corr 字面 η=0.1(爆幅度)60.090.28570.37160.021040.012060.05663
3corrnorm η=1(无 support 限制)61.410.21430.37570.012580.014060.05211
4pbproj 通路 graded_max η=159.390.21430.38100.015080.017650.05969
5TF 重排(CollecTRI)上调 η=0.661.360.17860.39130.011650.015270.05185
6TF 重排 下调 η=−0.660.600.21430.35960.012180.013910.05988
7tshift 斜率时序 κ=0.559.340.25000.37420.016350.016350.06100
8leakfix(f≡t 去位移泄漏)58.310.21430.37210.017660.020650.06075
9corr η=0.1 + bracket clamp1.361.230.25000.37290.014300.011980.05588
10corrnorm sup0.25 η=161.890.28570.37600.011990.013750.05279
11corrnorm sup0.25 η=261.860.28570.37600.012100.013790.05273
12corrnorm sup0.15 η=1(提交)62.060.28570.38130.012220.013470.05158
13corrnorm sup0.1 η=162.040.28570.38090.012350.013390.05168
14corrnorm sup0.15 within 核61.850.28570.38450.012800.013520.05225
15提交配置 seed 161.550.25000.38200.011730.013800.05201
16父节点 seed 1(配对基线)60.930.21430.38880.011480.014710.05527
17通路版 reactome η=2 k=20(PLAN 字面存档)60.860.21430.37930.013200.014180.05567

(#1 的另一次重复查分与 floor/max 探针占去其余额度,共用 19 次、余 1;shape 三项在所有表达侧变体中不变,坐标未动。#17 说明 PLAN 字面通路 boost 即使可测也劣于父节点,与离线筛选的"结构对消"结论一致。)

6. 知识来源

  • 提交机制不用任何外部生物学知识:C 完全由视图输入细胞现场计算(数据驱动的相关平滑),无硬编码统计量、无保留阶段信息、无文献数值。
  • 已试但放弃的变体用到的资源(如实记录):视图 prior/ 的 Reactome gene_sets.gmt、GO-BP gene_sets_bp.gmt(通路 boost,#4/#17,放弃);视图 prior/ 的 CollecTRI collectri_mouse.tsv.gz + 教科书级 GRN 层级顺序知识(调控因子先于其靶基因变化;Davidson & Erwin 2006, Science, doi:10.1126/science.1121590)——仅用作 #5/#6 的方向依据,两个方向均劣于父节点,放弃。
  • tshift(#7)的"阶段内异步性=伪时间"假设与 leakfix(#8)均为纯数据驱动,无外部知识。

7. 验证过 / 未验证

验证过:off 对照逐位一致(seed 0/1);seed 0 重跑逐位一致(确定性);伪装视图(全时间 +1 天、manifest 键序打乱、随机路径)输出与真实视图逐位一致(view-independent);vec-check 通过(seed 0/1/2 及 ablate);单输入阶段退路不经过本机制(bracket 为 None 时走 copy_last 分支);prior/ 缺失时 corr 模式不依赖 prior(提交配置完全不读 prior/);纯 CPU,峰值内存 0.61 GB,proxy 视图 1.6 s。

未验证:B 半分数(正式分);真实 final 视图(括号两端与细胞数不同,C 与 Δ 都会变,机制无阶段特异性参数,预期可迁移但幅度未测);final 视图更大细胞数下的 corr_kernel 稠密化内存(~每 10 万细胞 400 MB,28 GB 限内,但未实测);support/η 平台在 final 括号上是否同位置。

8. 下一步建议

  1. neighborhood_mmd 是本次收益最大的项(+0.4):相关扩散让型内收敛后的细胞更像真实中间态;可试把扩散核换成"位移后残差"的相关(迭代一步),或只对 b 侧细胞扩散(a/b 不对称解码)。
  2. mmd_u 的微损(−0.08)来自 Δ' 转动后个别基因 clip 位置变化;可试 clip 感知的扩散(对接近 0 的基因减弱校正)。
  3. de_score 0.2857 疑似其局部上限(8 种独立重排里只有相关扩散族达到);继续在 dp 重排上投入期望值低。

调研员的计划

名称通路/相关先验投影校正逐类型位移方向攻 de_score top-N 排序
动机父节点 27 的 ANALYSIS 明确指出 de_score(raw 0.3103,skill 0.600)缺口不在幅度而在位移方向的基因级错位:α·Δ_type 与真值 dt 的基因排序不一致,导致 |dp| top-N 集合与 |dt| top-N 重合率低。软阈值(节点 27)把参与基因从 166 扩到 478 但 de_score 纹丝不动,证实问题在方向而非阈值。expression_change 组 62.16 是仅次于 cell_state(50.36)的第二弱组,de_score 是该组内最弱指标(7.50/12.5)。
做法步骤:1) Engineer 先检查视图 prior/ 目录是否有通路/基因集文件(Reactome、CollecTRI、GO 等);若有,构建通路×基因二元矩阵 M;若无,用括号两阶段全部细胞计算基因-基因 Pearson 相关矩阵 C(~498×498)作为平滑核。2) 对每个共有类型的 Δ=μ_b−μ_a:(a) 通路版:计算通路活性分 s_p=mean(|Δ_g|, g∈p),取 top-k(k=30)活性通路,对每个基因 g 计算 boost_g = (g 所属活性通路数)/(g 所属总通路数),Δ'_g = Δ_g·(1+η·boost_g);(b) 相关版(fallback):Δ' = Δ + η·C·Δ(一步扩散),然后对 Δ' 做 clip 保持 nnz-only 语义(只移已表达项)。3) 用 Δ' 替换原 Δ 进入既有位移步(α=5、λ=6、β=0.2、软权重均保留不变)。4) η 初值 1.0,搜索 {0.5, 1.0, 2.0};通路版 k 搜索 {20, 30, 50}。5) 快速筛选:先在 seed 0 上比较 off/on 的 |dp| top-50 基因集合重合率变化(若重合率变化 <2 个基因则方向无效,尽早放弃);再 vec-score 查分确认。6) 单输入阶段(无括号)走既有 copy_last 退路,校正代码不执行。7) 不新增随机源,确定性输出。
风险1) prior/ 为空或无可用通路文件 → Engineer 第一步检查,立即切换到相关矩阵 fallback;2) 通路/相关校正改变不了 top-N 集合(Δ 的排序本身已接近最优)→ 用 top-50 重合率快速判断,若 <2 个基因变化则停止;3) η 过大导致位移方向过度偏离 Δ、mmd_u 恶化 → 否决线 mmd_u raw 增幅 <0.001,η=2 时若破线则放弃;4) 相关矩阵在小样本类型上噪声大 → 只用 ≥10 细胞的类型,相关矩阵用全类型合并计算;5) 效应量在噪声(~1 分)内 → 若 A 半提升 <0.5 分且 top-N 重合率无变化,如实报告失败。

代码改动?这个节点的程序和父节点程序的逐行差别:绿色是新增,红色是删除。

对比:父节点版本 5af70edcb8。改动的文件:solution/METHOD.md +78 −30、solution/run.py +444 −4

diff --git a/solution/METHOD.md b/solution/METHOD.mdindex e8a5573..fe976a3 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,41 +1,89 @@-实现软阈值基因加权位移(PLAN T2EI-01):表达位移的基因参与从硬阈值 1{|Δ|≥0.25} 改为连续幂次权重 w_g=clip(|Δ_g|/τ,0,1)^p(τ=0.25、p=1.0 提交),off/on 对照显示 de_direction 微升、de_score 不动,净效应 +0.03~0.04 榜分,在噪声(~1 分)内;提交保持机制打开。+在父节点27位移管线上,把逐类型Δ改为范数保持、支持集受限的基因相关扩散方向校正 Δ'=renorm(Δ+η·C·Δ)(仅|Δ|≥0.15基因,η=1,C=括号两阶段全细胞的基因-基因Pearson相关),使位移方向对齐组织内协同变化程序;PLAN字面的通路投影因位移在伪批量中精确对消而被证否,改交此备选解码。 -## 方法(family T2EI-01,PLAN:软阈值基因加权位移攻 DE 排序)+- family_id: T2EI-01+- parent: node 27(A 半 seed0 = 61.48,B 半 62.55)+- mechanism_off_control: `--ablate mechanism`(等价 T2_PROJ_ETA=0)→ Δ'=Δ,输出与父节点 27 逐位一致(已验证,含 seed 0/1) -保留父节点 13/19/22 全部管线(mix 分层混抽、procrustes3d、scale_damp=0.5、α=5 类型级收敛位移、λ=6 投影加权、β=0.2 型内 NN 配对收缩、全局 aniso damp=1.25、jitter、RMS 回缩;VARISO / TYPE_ANISO 关闭)。唯一改动在 mix_converge 的 Δ 构造处(run.py):+## 1. 提交机制(CORRPROJ,默认打开) -- 硬阈值(off):`d = where(|d|≥0.25, d, 0)` —— |Δ|<0.25 的基因位移为零,dp 中被压平,破坏 de_direction 秩偏相关;阈值附近全有/全无。-- 软权重(on,提交默认):`d = d · clip(|d|/τ, 0, 1)^p`,环境变量 T2_SOFT_ENABLE(默认 1)、T2_SOFT_TAU(默认 0.25)、T2_SOFT_P(默认 1.0)。位移仍是 x ← x ± α·(t 或 1−t)·w·d,nnz-only 与 clip≥0 保留,稀疏结构不变(nnz 比例 0.059 → 0.059,逐位验证)。λ 投影加权与 β 配对的 DE 掩码逻辑未改(β 的 de 掩码仍用硬阈值,只作用于配对距离与收缩维度选择)。-- off 对照:T2_SOFT_ENABLE=0(或 T2_SOFT_P=0)走原硬阈值分支,seed 0 输出与父节点逐位一致(off 榜分 61.4533 = 父节点 A 半 61.45,验证通过)。-- 单输入阶段(无括号)走上层既有 copy_last 退路,软权重代码不执行。确定性:无新增随机源。+位置:`mix_converge` 的逐类型位移步之前(软权重、α=5、λ=6、β=0.2、nnz-only、clip≥0 全部保留不变)。 -## 机制生效证据(seed 0,proxy E6.75+E8.0→E7.25,t=0.4)+对每个共有类型(两侧各 ≥10 细胞)的 Δ = μ_b − μ_a: -- 参与位移基因数(sum(w_g>0.01),10 个共有类型均值):硬阈值 166.4 → 软权重 478.2;位移幅度按 |Δ| 幂次递减(maxAbsD 1.93,meanAbsD 0.0028)。-- 四组分(A 半查分):expression_change 60.97→61.03(de_direction raw 0.3853→0.3879、skill 0.638→0.639;de_score raw 0.25 完全不动);cell_state 48.93→48.92(mmd_u +0.00003 微劣、variogram 0.01442→0.01432 微升,均在否决线内);local_spatial / shape_scale 逐位不变(坐标未动,nbr raw 0.05506→0.05505 来自表达经邻域平均的间接影响,<0.002 阈值)。+1. C = 括号两阶段全部细胞合并后的基因-基因 Pearson 相关矩阵(498×498,对角置 0),只依赖视图输入数据,现场计算;+2. Δ_diff = Δ + η·C·Δ(一步扩散,η=1);+3. 支持集限制:只有 |Δ_g| ≥ 0.15(T2_PROJ_SUPPORT)的基因取 Δ_diff,其余基因保持测得的 Δ_g——不招募新基因、不翻转弱基因符号;+4. 范数保持:Δ' = Δ_diff·‖Δ‖/‖Δ_diff‖——只改方向不改幅度(不加此步时扩散把幅度放大 ~10 倍,表达值爆到 147(父节点 max 32.6),mmd_u 从 0.0117 崩到 0.0210)。 -## 网格结果(A 半,共 10 次查分)+参数(run.py 默认值,环境变量可覆写):T2_PROJ_MODE=corr、T2_PROJ_ETA=1.0、T2_PROJ_SUPPORT=0.15、T2_PROJ_NORM=1、T2_PROJ_CORR_KERNEL=all。无新增随机源,seed 确定(已验证 seed 0 重跑逐位一致)。 -| 配置 | 榜分 | de_score | de_dir | mmd_u | variogram | nbr |-|---|---:|---:|---:|---:|---:|---:|-| off(=父13/19/22) | 61.453 | 0.2500 | 0.3853 | 0.01164 | 0.01442 | 0.05506 |-| p=0.5, τ=0.25 | 61.483 | 0.2500 | 0.3878 | 0.01168 | 0.01430 | 0.05505 |-| **p=1.0, τ=0.25(提交)** | **61.483** | 0.2500 | 0.3879 | 0.01167 | 0.01432 | 0.05505 |-| p=2.0, τ=0.25 | 61.474 | 0.2500 | 0.3874 | 0.01167 | 0.01435 | 0.05505 |-| p=1.0, τ=0.15 | 61.490 | 0.2500 | 0.3883 | 0.01168 | 0.01428 | 0.05505 |-| p=1.0, τ=0.50 | 61.411 | 0.2500 | 0.3858 | 0.01170 | 0.01450 | 0.05518 |-| p=1.0, α=8 | 60.808 | 0.2500 | 0.3796 | 0.01532 | 0.01352 | 0.05477 |-| p=1.0, α=3 | 60.430 | 0.2143 | 0.3843 | 0.01221 | 0.01594 | 0.05886 |+## 2. PLAN 被证否的过程(结构原因 + 离线筛选) -## 结论(诚实评估)+PLAN 的字面机制(通路 boost 进 Δ)实现后离线筛选发现**结构性对消**:分层混抽的 (1−t, t) 权重使逐细胞位移在输出伪批量中精确抵消,而 de_score / de_direction 只看 dp = pb(pred) − pb(ref)。因此任何只改 Δ 方向(不改幅度、不改 nnz/clip 非线性)的校正对 dp 几乎不可见: -- 机制方向正确但效应量远低于预期:de_direction raw +0.0026(PLAN 继续阈值 0.02 未达到),de_score 在所有软权重配置下纹丝不动——de_score 只看 |dp| 排序取 top-N 的命中率,小 |Δ| 基因的软位移量太小(α·t·Δ·(|Δ|/τ)^p,|Δ|≪τ 时近乎零),改变不了 top-N 集合,说明 de_score 缺口不在阈值压平而在位移方向本身(α·Δ_type 与真值 dt 的基因级错位)。-- α 网格证实 α=5 仍是局部最优(α=3 de_score 崩到 0.214,α=8 mmd_u 崩到 0.0153)。-- τ=0.5(对大 Δ 基因也衰减)净负:位移整体变弱等价于 α 减小。-- 净榜分 +0.03(61.453→61.483),T2 噪声 ~1 分,A/B 半之间不保证重现;所有否决线(mmd_u < +0.001、variogram、nbr < +0.002)均满足且 variogram/nbr 微改善,故按 PLAN"提交时保持打开"提交 p=1.0、τ=0.25。若 B 半回归,教训是:DE 两项对幅度不敏感、只对排序敏感,任何不改变 dp 排序的幅度级微调都无效。+- 通路版(Reactome top-k 二元 boost,k∈{20,30,50},η∈{1,2};GO-BP k∈{30,100},η∈{1,2,4},graded/graded_max 两种解码)共 8 个离线配置:|dp| top-50 集合变化 ≤2 个基因(PLAN 自己的放弃线 <2),cos(Δ,Δ')≥0.90,boost 均值 0.005–0.085——方向无效;+- 其中 1 个配置送查分存档:reactome η=2 k=20 → 60.86(劣于父节点,见 §5 表 #17);+- 相关版字面实现(Δ'=Δ+ηCΔ,无范数保持):η=0.1 → 60.09(de_score 0.2857 但 mmd_u 崩),说明其 dp 变化全部来自幅度爆炸的 clip 整流,不是方向。 -## 验证过 / 没验证+按任务书规则(≥3 种解码/幅度组合、≥6 次查分)判定 PLAN 字面方向无效后,改交针对同一弱项(expression_change / de_score 排序错位)的备选解码:把"相关先验校正位移方向"从幅度爆炸中剥离(范数保持 + 支持集限制),这是同一机制家族的合法解码变体。 -- 验证:off 与父逐位一致;on 的稀疏结构保持;p/τ/α 网格 8 配置;vec-check ok;默认配置输出与 p1.0 网格文件逐位一致。-- 没验证:seed 1/2 复跑(时间预算内查分优先给了网格);τ<0.15(PLAN 风险 4 的密集位移区);β 配对掩码同步改软权重(预期同样在噪声内)。-- 知识来源:无外部生物学知识;全部为评分指标性质推理(DE 只看排序/符号)与代理网格实测。+## 3. 机制生效证据++- **实际改变了什么**:每个共有类型的 Δ 方向被转动(cos(Δ,Δ') 均值 0.86、最小 0.82,>0.5 且 <1,符合 PLAN 的预期区间);受影响细胞 = 全部 10 个共有类型的输出细胞(a 侧 3000 + b 侧 2000,位移量随 Δ' 方向变);坐标、细胞抽取、nnz 结构不变(nnz 0.0590→0.0567,来自 Δ' 方向改变后 clip 位置的微小变化)。+- **dp 层**:|dp| top-50 变化 2–3 个基因(过了 PLAN 的 ≥2 筛选线),de_score raw 0.25→0.2857(seed 0)、0.2143→0.25(seed 1)。+- **四组分(A 半,seed 0,本节点 vs 父节点)**:expression_change 62.16→62.31(de_score +0.17,de_direction −0.07);cell_state 50.36→50.29(variogram +0.12,mmd_u −0.08);local_spatial 60.37→60.61(neighborhood_mmd raw 0.05505→0.05158,+0.40 points);shape_scale 77.31→77.31(坐标未动,符合设计)。总分 61.48→62.06。+- **跨 seed 一致性**:seed 1 配对比较 61.55 vs 父节点 60.93(+0.63);seed 0 +0.58。收益主要来自 neighborhood_mmd(+0.34~0.40)、de_score(+0.17)、variogram(+0.12~0.19),代价是 mmd_u(−0.06~0.08)与 de_direction(−0.04~0.07)——两次查分模式一致,非单 seed 尖峰。++## 4. 调参轨迹(support / η / 核)++| 配置 | A 半总分 |+|---|---|+| support 0.25, η=1 | 61.89 |+| support 0.25, η=2 | 61.86 |+| **support 0.15, η=1(提交)** | **62.06** |+| support 0.1, η=1 | 62.04 |+| support 0.15, within-type 核 | 61.85 |++support 0.1–0.15 是平台(差 0.03,噪声内),取 0.15;η 在 1→2 已饱和(范数保持下方向变化封顶);within-type 残差核(去掉类型间组成结构)略差于全细胞核,说明组成间共变结构本身有用。++## 5. 全部查分记录(A 半 proxy,seed 0 除注明外;共 18 次,余 2)++| # | 配置 | 总分 | de_score raw | de_dir raw | mmd_u raw | variogram raw | nbhd raw |+|---|---|---|---|---|---|---|---|+| 1 | 父节点/off(逐位一致验证) | 61.48 | 0.2500 | 0.3879 | 0.01167 | 0.01432 | 0.05505 |+| 2 | corr 字面 η=0.1(爆幅度) | 60.09 | 0.2857 | 0.3716 | 0.02104 | 0.01206 | 0.05663 |+| 3 | corrnorm η=1(无 support 限制) | 61.41 | 0.2143 | 0.3757 | 0.01258 | 0.01406 | 0.05211 |+| 4 | pbproj 通路 graded_max η=1 | 59.39 | 0.2143 | 0.3810 | 0.01508 | 0.01765 | 0.05969 |+| 5 | TF 重排(CollecTRI)上调 η=0.6 | 61.36 | 0.1786 | 0.3913 | 0.01165 | 0.01527 | 0.05185 |+| 6 | TF 重排 下调 η=−0.6 | 60.60 | 0.2143 | 0.3596 | 0.01218 | 0.01391 | 0.05988 |+| 7 | tshift 斜率时序 κ=0.5 | 59.34 | 0.2500 | 0.3742 | 0.01635 | 0.01635 | 0.06100 |+| 8 | leakfix(f≡t 去位移泄漏) | 58.31 | 0.2143 | 0.3721 | 0.01766 | 0.02065 | 0.06075 |+| 9 | corr η=0.1 + bracket clamp1.3 | 61.23 | 0.2500 | 0.3729 | 0.01430 | 0.01198 | 0.05588 |+| 10 | corrnorm sup0.25 η=1 | 61.89 | 0.2857 | 0.3760 | 0.01199 | 0.01375 | 0.05279 |+| 11 | corrnorm sup0.25 η=2 | 61.86 | 0.2857 | 0.3760 | 0.01210 | 0.01379 | 0.05273 |+| 12 | **corrnorm sup0.15 η=1(提交)** | **62.06** | 0.2857 | 0.3813 | 0.01222 | 0.01347 | 0.05158 |+| 13 | corrnorm sup0.1 η=1 | 62.04 | 0.2857 | 0.3809 | 0.01235 | 0.01339 | 0.05168 |+| 14 | corrnorm sup0.15 within 核 | 61.85 | 0.2857 | 0.3845 | 0.01280 | 0.01352 | 0.05225 |+| 15 | 提交配置 seed 1 | 61.55 | 0.2500 | 0.3820 | 0.01173 | 0.01380 | 0.05201 |+| 16 | 父节点 seed 1(配对基线) | 60.93 | 0.2143 | 0.3888 | 0.01148 | 0.01471 | 0.05527 |+| 17 | 通路版 reactome η=2 k=20(PLAN 字面存档) | 60.86 | 0.2143 | 0.3793 | 0.01320 | 0.01418 | 0.05567 |++(#1 的另一次重复查分与 floor/max 探针占去其余额度,共用 19 次、余 1;shape 三项在所有表达侧变体中不变,坐标未动。#17 说明 PLAN 字面通路 boost 即使可测也劣于父节点,与离线筛选的"结构对消"结论一致。)++## 6. 知识来源++- **提交机制不用任何外部生物学知识**:C 完全由视图输入细胞现场计算(数据驱动的相关平滑),无硬编码统计量、无保留阶段信息、无文献数值。+- 已试但放弃的变体用到的资源(如实记录):视图 prior/ 的 Reactome `gene_sets.gmt`、GO-BP `gene_sets_bp.gmt`(通路 boost,#4/#17,放弃);视图 prior/ 的 CollecTRI `collectri_mouse.tsv.gz` + 教科书级 GRN 层级顺序知识(调控因子先于其靶基因变化;Davidson & Erwin 2006, Science, doi:10.1126/science.1121590)——仅用作 #5/#6 的方向依据,两个方向均劣于父节点,放弃。+- tshift(#7)的"阶段内异步性=伪时间"假设与 leakfix(#8)均为纯数据驱动,无外部知识。++## 7. 验证过 / 未验证++验证过:off 对照逐位一致(seed 0/1);seed 0 重跑逐位一致(确定性);伪装视图(全时间 +1 天、manifest 键序打乱、随机路径)输出与真实视图逐位一致(view-independent);vec-check 通过(seed 0/1/2 及 ablate);单输入阶段退路不经过本机制(bracket 为 None 时走 copy_last 分支);prior/ 缺失时 corr 模式不依赖 prior(提交配置完全不读 prior/);纯 CPU,峰值内存 0.61 GB,proxy 视图 1.6 s。++未验证:B 半分数(正式分);真实 final 视图(括号两端与细胞数不同,C 与 Δ 都会变,机制无阶段特异性参数,预期可迁移但幅度未测);final 视图更大细胞数下的 corr_kernel 稠密化内存(~每 10 万细胞 400 MB,28 GB 限内,但未实测);support/η 平台在 final 括号上是否同位置。++## 8. 下一步建议++1. neighborhood_mmd 是本次收益最大的项(+0.4):相关扩散让型内收敛后的细胞更像真实中间态;可试把扩散核换成"位移后残差"的相关(迭代一步),或只对 b 侧细胞扩散(a/b 不对称解码)。+2. mmd_u 的微损(−0.08)来自 Δ' 转动后个别基因 clip 位置变化;可试 clip 感知的扩散(对接近 0 的基因减弱校正)。+3. de_score 0.2857 疑似其局部上限(8 种独立重排里只有相关扩散族达到);继续在 dp 重排上投入期望值低。diff --git a/solution/run.py b/solution/run.pyindex cf4216b..a951b54 100644--- a/solution/run.py+++ b/solution/run.py@@ -8,6 +8,16 @@ exp(log r_a + SCALE_DAMP·t·Δlog r), and draws cells stratified by type: round(t·n) from the later stage, the rest from the earlier one. Coordinates travel with the cells. n is log-linear in t, clipped to the board range. +This node (31, CORRPROJ, family T2EI-01): before the soft weights, each shared+type's Δ is direction-corrected by one-step gene-gene correlation diffusion+Δ' = renormalize(Δ + η·C·Δ) restricted to genes with |Δ| ≥ PROJ_SUPPORT, where+C is the Pearson correlation of all bracket-stage cells (zero diagonal) and the+renormalization restores ||Δ||. C encodes which genes co-vary within the+tissue, so the displacement direction aligns with coordinated gene programs+instead of per-gene measured differences. η = 0 (or --ablate mechanism)+reproduces the parent node 27 bit-for-bit. See METHOD.md for the falsified+pathway-boost decodes and the pb-level variants.+ New mechanism (CONVERGE_ALPHA, family T2EI-01): for every cell type present in both bracketing stages (≥10 cells per side), compute its temporal change vector Δ = μ_b − μ_a from the stage pseudobulk means, keeping only genes with@@ -95,6 +105,156 @@ CONVERGE_NNZ_ONLY = os.environ.get("T2_CONVERGE_NNZ_ONLY", "1") == "1" SOFT_ENABLE = os.environ.get("T2_SOFT_ENABLE", "1") == "1" SOFT_TAU = float(os.environ.get("T2_SOFT_TAU", "0.25")) SOFT_P = float(os.environ.get("T2_SOFT_P", "1.0"))+# Pathway/correlation prior projection (family T2EI-01, this node): the per-type+# temporal change Δ = μ_b − μ_a is direction-corrected with a biological prior+# before entering the displacement step. SUBMITTED DEFAULT: mode "corr" with+# norm-preservation and support restriction (see module docstring / METHOD.md).+# Mode "pathway": read Reactome gene sets+# from the view's prior/ directory, build the pathway×gene membership matrix M+# on panel genes; per type, pathway activity s_p = mean(|Δ_g|, g∈p); take the+# top-k active pathways; boost_g = (# active pathways containing g) /+# (# all pathways containing g); Δ'_g = Δ_g·(1 + η·boost_g). Genes in no+# pathway keep Δ_g. Mode "corr" (fallback when prior/ is unusable): gene-gene+# Pearson correlation C of all bracket cells, Δ' = Δ + η·C·Δ (one-step+# diffusion). η = 0 disables the mechanism and reproduces the parent bit-for-+# bit. Everything downstream (soft weights, α, λ, β, nnz-only, clip≥0) is+# unchanged and receives Δ' in place of Δ.+PROJ_ETA = float(os.environ.get("T2_PROJ_ETA", "1.0"))+PROJ_MODE = os.environ.get("T2_PROJ_MODE", "corr")+PROJ_K = int(os.environ.get("T2_PROJ_K", "30"))+PROJ_MIN_PATHWAY_GENES = int(os.environ.get("T2_PROJ_MIN_PATHWAY_GENES", "3"))+# Which prior gene-set family to read (pathway mode): reactome | go_bp | msigdb.+# go_bp covers ~98% of the panel genes vs ~52% for reactome on this 498-gene+# panel, giving the boost much more reach.+PROJ_SRC = os.environ.get("T2_PROJ_SRC", "go_bp")+# Renormalize Δ' to the original ||Δ|| after projection (direction-only change).+PROJ_NORM = os.environ.get("T2_PROJ_NORM", "1") == "1"+# Support restriction for corr diffusion: only genes with |Δ| >= PROJ_SUPPORT+# receive the diffused value; others keep their measured Δ (0 = off).+PROJ_SUPPORT = float(os.environ.get("T2_PROJ_SUPPORT", "0.15"))+# Correlation kernel for corr mode: "all" pools every bracket cell (program ++# composition structure); "within" centers cells by their own type mean first,+# keeping only within-state co-variation.+PROJ_CORR_KERNEL = os.environ.get("T2_PROJ_CORR_KERNEL", "all")+# Bracket-range clamp: after the displacement/pair steps, clip every gene's+# cell values at BRACKET_CLIP × max(value observed for that gene in either+# bracket stage). Prevents the corr-diffusion magnitude explosion (values up+# to 5× the biological range, which is what collapses mmd_u) while keeping the+# correlation structure the diffusion imprints. 0 = off (parent behavior).+BRACKET_CLIP = float(os.environ.get("T2_BRACKET_CLIP", "0"))+# Pseudobulk-level prior projection (PBPROJ, this node's submitted mechanism).+# Motivation: the stratified (1−t, t) draw weights make the per-cell+# displacement cancel EXACTLY in the output pseudobulk, so de_score /+# de_direction (which only see dp = pb(pred) − pb(ref)) are structurally blind+# to any correction applied to Δ inside the displacement step (verified+# offline: top-50 |dp| set moves ≤ 2 genes for every pathway configuration).+# PBPROJ therefore applies the same pathway-prior boost where the DE metrics+# can see it: after the full expression pipeline, compute the pooled bracket+# change Δ_pb = pb(b) − pb(a) and the pathway-boosted Δ'_pb (same boost_g as+# the pathway mode: top-k active prior gene sets per Δ_pb, boost_g = active/+# total membership), then rescale each gene's output column by+# s_g = 1 + η·boost_g·t·Δ_pb_g/max(pb_out_g, floor), clipped to [0, 1+cap].+# Multiplicative nnz scaling keeps the zero structure, the within-gene relative+# distribution and coordinates untouched; pb_out moves by ≈ η·boost_g·dp_g,+# i.e. genes inside coherently-changing prior sets get their (already+# correctly-signed) change magnitude amplified, isolated genes keep theirs.+# η = 0 disables and reproduces the parent bit-for-bit.+PBPROJ_ENABLE = os.environ.get("T2_PBPROJ_ENABLE", "0") == "1"+PBPROJ_ETA = float(os.environ.get("T2_PBPROJ_ETA", "0.5"))+PBPROJ_K = int(os.environ.get("T2_PBPROJ_K", "30"))+PBPROJ_SRC = os.environ.get("T2_PBPROJ_SRC", "reactome")+PBPROJ_FLOOR = float(os.environ.get("T2_PBPROJ_FLOOR", "0.05"))+PBPROJ_CAP = float(os.environ.get("T2_PBPROJ_CAP", "1.5"))+PBPROJ_BOOST_MODE = os.environ.get("T2_PBPROJ_BOOST_MODE", "graded")+# Weight source for PBPROJ (which genes' dp gets amplified):+#   pathway  — prior gene-set coherence boost (PLAN literal, at pb level)+#   tf       — regulatory-hierarchy re-ranking: genes that are transcription+#              factors (regulators in the view's CollecTRI prior) get w=1,+#              all other genes w=0. Rationale (textbook GRN hierarchy, e.g.+#              Davidson & Erwin 2006, doi:10.1126/science.1121590): in a+#              developmental transition, upstream regulators change before+#              their downstream targets, so at an intermediate target time the+#              regulators have already covered a larger fraction of their+#              bracket change than terminal/downstream genes. Amplifying the+#              regulator dp (and only its sign-consistent magnitude) re-ranks+#              the top-N toward genes that are further along their trajectory.+PBPROJ_W_MODE = os.environ.get("T2_PBPROJ_W_MODE", "pathway")+# TSHIFT (backup mechanism, expression_change): per-gene trajectory-timing+# correction from within-stage progression slopes. Assumption: cells inside one+# stage are asynchronous — a cell's projection q onto the type's Δ = μ_b − μ_a+# direction is a pseudotemporal progression coordinate (cells with high q are+# further along the a→b transition). A gene whose full a→b rise already happens+# WITHIN stage a (slope within a covers ~Δ over a's q-spread) is an early mover+# (f_g > t: it has covered more than a t-fraction of its change by the target+# time); a gene still rising WITHIN stage b is a late mover (f_g < t). The+# target pseudobulk is then pb_a + f_g·Δ_pb instead of pb_a + t·Δ_pb, realized+# as a per-gene column rescale of the output (nnz-only, sparse structure and+# coordinates untouched). Uses only bracket-stage data (no external knowledge,+# no target information). KAPPA=0 disables and reproduces the parent bit-for-bit.+TSHIFT_ENABLE = os.environ.get("T2_TSHIFT_ENABLE", "0") == "1"+TSHIFT_KAPPA = float(os.environ.get("T2_TSHIFT_KAPPA", "0.5"))+TSHIFT_MIN_CELLS = int(os.environ.get("T2_TSHIFT_MIN_CELLS", "30"))+TSHIFT_MIN_DELTA = float(os.environ.get("T2_TSHIFT_MIN_DELTA", "0.25"))+TSHIFT_FLO = float(os.environ.get("T2_TSHIFT_FLO", "0.5"))   # f >= FLO·t+TSHIFT_FHI = float(os.environ.get("T2_TSHIFT_FHI", "2.0"))   # f <= FHI·t (and <= 0.9)+TSHIFT_CAP = float(os.environ.get("T2_TSHIFT_CAP", "1.0"))+# TSHIFT_MODE: "timing" (slope-asymmetry f_g) or "leakfix" (f_g ≡ t: undo the+# displacement pipeline's nnz/clip leakage so dp equals the clean linear+# estimate t·Δ_pb on reliable genes).+TSHIFT_MODE = os.environ.get("T2_TSHIFT_MODE", "timing")+++def timing_fraction(stage_a, stage_b, shared_labels, kappa: float):+    """Per-gene f_g in [FLO·t, min(FHI·t, 0.9)] from within-stage slope asymmetry."""+    genes_n = len(stage_a.genes)+    num = np.zeros(genes_n)+    den = np.zeros(genes_n)+    for lab in shared_labels:+        A = np.asarray(stage_a.X[stage_a.labels == lab].toarray(), dtype=np.float64)+        B = np.asarray(stage_b.X[stage_b.labels == lab].toarray(), dtype=np.float64)+        if A.shape[0] < TSHIFT_MIN_CELLS or B.shape[0] < TSHIFT_MIN_CELLS:+            continue+        d = B.mean(axis=0) - A.mean(axis=0)+        reliable = np.abs(d) >= TSHIFT_MIN_DELTA+        if reliable.sum() < 5 or np.linalg.norm(d) < 1e-9:+            continue+        slopes = []+        for Xs in (A, B):+            mu = Xs.mean(axis=0)+            q = (Xs - mu) @ d+            sq = q.std()+            if sq < 1e-12:+                slopes.append(np.zeros(genes_n))+                continue+            s = ((Xs - mu) * (q - q.mean())[:, None]).mean(axis=0) / (sq * sq)+            # rise over a ±1 sd progression window, in units of the full change d+            slopes.append(2.0 * sq * s / np.where(np.abs(d) < 1e-9, np.nan, d))+        r_a, r_b = slopes+        timing = 0.5 * (r_a - r_b)  # +: early (done by a), −: late (still going at b)+        timing = np.where(reliable & np.isfinite(timing), np.clip(timing, -1.0, 1.0), 0.0)+        wt = float(min(A.shape[0], B.shape[0])) * np.abs(d)  # reliability weight+        num += wt * timing+        den += wt+    timing = np.where(den > 0, num / np.maximum(den, 1e-12), 0.0)+    return timing+++def tf_indicator(view: str, genes: list[str]) -> np.ndarray | None:+    """1.0 for panel genes that appear as a regulator (tf) in CollecTRI."""+    path = os.path.join(view, "prior", "tf_regulons", "collectri_mouse.tsv.gz")+    if not os.path.exists(path):+        return None+    import gzip+    gidx = {g: i for i, g in enumerate(genes)}+    out = np.zeros(len(genes))+    with gzip.open(path, "rt") as fh:+        fh.readline()+        for line in fh:+            p = line.split("\t")+            j = gidx.get(p[0])+            if j is not None:+                out[j] = 1.0+    return out # Per-cell heterogeneous displacement (family T2EI-01 refine): each cell's shift # is scaled by w = clip(1 -/+ λ·p, 0.2, 2.5), where p is the cell's deviation # from its type mean projected onto Δ (only genes with Δ≠0). Cells already@@ -178,6 +338,151 @@ VARISO_MIN_CELLS = int(os.environ.get("T2_VARISO_MIN_CELLS", "10")) VARISO_MIN_DE = int(os.environ.get("T2_VARISO_MIN_DE", "10"))  +def load_pathway_sets(view: str, genes: list[str], src: str | None = None):+    """Reactome pathway×gene membership on panel genes, from the view's prior/.++    Returns (M, names): M is a boolean (n_pathways, n_genes) matrix, names the+    pathway ids (sorted, deterministic). Pathways with fewer than+    PROJ_MIN_PATHWAY_GENES panel genes are dropped. Returns (None, None) when+    the prior directory or file is missing/unreadable.+    """+    src_files = {+        "reactome": os.path.join("prior", "reactome", "gene_sets.gmt"),+        "go_bp": os.path.join("prior", "go", "gene_sets_bp.gmt"),+        "msigdb": os.path.join("prior", "msigdb", "hallmark_mouse.gmt"),+    }+    rel = src_files.get(src if src is not None else PROJ_SRC)+    if rel is None:+        return None, None+    gmt = os.path.join(view, rel)+    if not os.path.exists(gmt):+        return None, None+    gene_idx = {g: i for i, g in enumerate(genes)}+    rows, names = [], []+    with open(gmt, "r") as fh:+        for line in fh:+            parts = line.rstrip("\n").split("\t")+            if len(parts) < 3:+                continue+            pid = parts[0]+            member = np.zeros(len(genes), dtype=bool)+            for sym in parts[2:]:+                j = gene_idx.get(sym)+                if j is not None:+                    member[j] = True+            if int(member.sum()) < PROJ_MIN_PATHWAY_GENES:+                continue+            rows.append(member)+            names.append(pid)+    if not rows:+        return None, None+    order = np.argsort(names)+    M = np.vstack(rows)[order]+    names = [names[i] for i in order]+    return M, names+++def corr_kernel(stage_a, stage_b, genes_n: int) -> np.ndarray:+    """Gene-gene Pearson correlation of all bracket-stage cells (dense, panel-sized)."""+    from scipy import sparse as sp+    X = sp.vstack([sp.csr_matrix(stage_a.X), sp.csr_matrix(stage_b.X)]).toarray().astype(np.float64)+    X = X - X.mean(axis=0, keepdims=True)+    sd = X.std(axis=0)+    sd[sd < 1e-12] = np.inf+    C = (X.T @ X) / X.shape[0]+    C = C / np.outer(sd, sd)+    np.fill_diagonal(C, 0.0)+    return C.astype(np.float32)+++def corr_kernel_within(stage_a, stage_b) -> np.ndarray:+    """Gene-gene Pearson correlation of within-type residuals (both stages pooled).++    Centering each cell by its own type mean removes between-type composition+    structure, leaving the within-state gene-gene co-variation — the coordinate+    programs (shared regulation) that the diffusion should align Δ with.+    """+    parts = []+    for st in (stage_a, stage_b):+        X = np.asarray(st.X.toarray(), dtype=np.float64)+        labs = np.asarray(st.labels).astype(str)+        for lab in np.unique(labs):+            m = labs == lab+            if m.sum() >= 10:+                parts.append(X[m] - X[m].mean(axis=0, keepdims=True))+    if not parts:+        return None+    X = np.vstack(parts)+    sd = X.std(axis=0)+    sd[sd < 1e-12] = np.inf+    C = (X.T @ X) / X.shape[0]+    C = C / np.outer(sd, sd)+    np.fill_diagonal(C, 0.0)+    return C.astype(np.float32)+++def pathway_boost(abs_d: np.ndarray, M, k: int):+    """boost_g = (# top-k active sets containing g) / (# all sets containing g)."""+    s = (M.astype(np.float64) @ abs_d) / np.maximum(M.sum(axis=1), 1)+    k = min(int(k), M.shape[0])+    act = np.argsort(-s, kind="stable")[:k]+    A = M[act]  # active set membership+    n_active = A.astype(np.float64).sum(axis=0)+    n_total = M.astype(np.float64).sum(axis=0)+    boost = np.where(n_total > 0, n_active / np.maximum(n_total, 1.0), 0.0)+    return boost, act+++def pathway_boost_graded(abs_d: np.ndarray, M, k: int):+    """Graded set-activity boost in [0, 1] with full dynamic range.++    Set activity s_p = mean(|Δ_g|, g∈p). Sets are soft-weighted by the rank of+    s_p: the top-k sets get weight linearly decreasing from 1 (rank 0) to 0+    (rank k), the rest 0. boost_g = Σ_p w_p·M_pg / Σ_p M_pg — the mean active+    weight of the sets gene g belongs to. Genes in no set get 0.+    """+    s = (M.astype(np.float64) @ abs_d) / np.maximum(M.sum(axis=1), 1)+    k = min(int(k), M.shape[0])+    order = np.argsort(-s, kind="stable")+    w = np.zeros(M.shape[0])+    w[order[:k]] = np.linspace(1.0, 0.0, k, endpoint=False)+    Mf = M.astype(np.float64)+    if PBPROJ_BOOST_MODE == "graded_max":+        # best-set attribution: boost_g = max weight among sets containing g+        boost = np.where(Mf > 0, w[:, None], 0.0).max(axis=0)+    else:+        num = Mf.T @ w+        den = Mf.sum(axis=0)+        boost = np.where(den > 0, num / np.maximum(den, 1.0), 0.0)+    return boost, order[:k]+++def project_delta(d: np.ndarray, M, names, k: int, eta: float, corr: np.ndarray | None):+    """Direction-correct one type's Δ with the prior. Returns (Δ', info)."""+    ad_ = np.abs(d).astype(np.float64)+    if M is not None:+        boost, _ = pathway_boost(ad_, M, k)+        dp = (d.astype(np.float64) * (1.0 + eta * boost)).astype(np.float32)+        cos = float(d @ dp / max(np.linalg.norm(d.astype(np.float64)) * np.linalg.norm(dp.astype(np.float64)), 1e-12))+        info = {"boost_mean": float(boost.mean()), "boost_max": float(boost.max()),+                "cos": cos, "mode": "pathway"}+        return dp, info+    if corr is not None:+        d64 = d.astype(np.float64)+        dp = d64 + eta * (corr.astype(np.float64) @ d64)+        if PROJ_SUPPORT > 0:+            # keep the diffused value only on reliable DE genes; genes with+            # |Δ| < support keep their measured Δ (no recruited noise genes,+            # no support/sign changes outside the DE set)+            dp = np.where(np.abs(d64) >= PROJ_SUPPORT, dp, d64)+        if PROJ_NORM:+            dp = dp * (np.linalg.norm(d64) / max(np.linalg.norm(dp), 1e-12))+        dp = dp.astype(np.float32)+        cos = float(d @ dp / max(np.linalg.norm(d.astype(np.float64)) * np.linalg.norm(dp.astype(np.float64)), 1e-12))+        return dp, {"cos": cos, "mode": "corr"}+    return d, {"mode": "none"}++ def aniso_reshape(coords, aligned_a, aligned_b, t: float, damp: float):     """Rescale per-axis spreads of `coords` toward the log-interpolated bracket spreads."""     a = np.asarray(aligned_a, dtype=np.float64)@@ -265,7 +570,8 @@ def type_aniso_reshape(coords, labs_out, ca, cb, la_all, lb_all, t: float):     return c, info  -def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float):+def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float, view: str | None = None,+                 proj_eta: float | None = None):     t = float(t)     damp = float(params.get("scale_damp", 1.0))     align = str(params.get("align", "procrustes"))@@ -297,8 +603,33 @@ def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float):         shared = sorted(k for k in set(means_a) & set(means_b) if cnt_a[k] >= 10 and cnt_b[k] >= 10)         delta = {}         n_part, n_hard = [], []+        # Prior-projection setup (family T2EI-01, this node): direction-correct+        # each type's raw Δ with Reactome pathway membership (or gene-gene+        # correlation fallback) before the soft weights and displacement.+        eta = PROJ_ETA if proj_eta is None else float(proj_eta)+        proj_M, proj_names, proj_corr = None, None, None+        proj_cos, proj_boost = [], []+        if eta != 0.0 and shared and view is not None:+            def _kernel():+                if PROJ_CORR_KERNEL == "within":+                    k = corr_kernel_within(stage_a, stage_b)+                    if k is not None:+                        return k+                return corr_kernel(stage_a, stage_b, len(stage_a.genes))+            if PROJ_MODE == "pathway":+                proj_M, proj_names = load_pathway_sets(view, list(stage_a.genes))+                if proj_M is None:+                    proj_corr = _kernel()+            elif PROJ_MODE == "corr":+                proj_corr = _kernel()         for lab in shared:             d = (means_b[lab] - means_a[lab]).astype(np.float32)+            if eta != 0.0 and (proj_M is not None or proj_corr is not None):+                d, pinfo = project_delta(d, proj_M, proj_names, PROJ_K, eta, proj_corr)+                if "cos" in pinfo:+                    proj_cos.append(pinfo["cos"])+                if "boost_mean" in pinfo:+                    proj_boost.append(pinfo["boost_mean"])             if SOFT_ENABLE and SOFT_P > 0:                 w = np.clip(np.abs(d) / max(SOFT_TAU, 1e-12), 0.0, 1.0) ** SOFT_P                 n_part.append(int((w > 0.01).sum()))@@ -307,6 +638,14 @@ def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float):             elif CONVERGE_MIN_DELTA > 0:                 d = np.where(np.abs(d) >= CONVERGE_MIN_DELTA, d, np.float32(0.0)).astype(np.float32)             delta[lab] = d+        if eta != 0.0 and (proj_M is not None or proj_corr is not None):+            conv["proj_eta"] = eta+            conv["proj_mode"] = "pathway" if proj_M is not None else "corr"+            conv["proj_k"] = PROJ_K if proj_M is not None else None+            conv["proj_n_pathways"] = int(proj_M.shape[0]) if proj_M is not None else None+            conv["proj_cos_mean"] = float(np.mean(proj_cos)) if proj_cos else None+            conv["proj_cos_min"] = float(np.min(proj_cos)) if proj_cos else None+            conv["proj_boost_mean"] = float(np.mean(proj_boost)) if proj_boost else None         if n_part:             conv["soft_enable"] = True             conv["soft_tau"] = SOFT_TAU@@ -538,6 +877,89 @@ def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float):             )      expr = np.clip(np.vstack([xa, xb]), 0.0, None).astype(np.float32) if (ia.size or ib.size) else np.zeros((0, len(stage_a.genes)), np.float32)+    clamp_info = {"bracket_clip": BRACKET_CLIP, "n_clamped_cells": 0}+    if BRACKET_CLIP > 0 and expr.shape[0]:+        mx_a = np.asarray(stage_a.X.max(axis=0).todense()).ravel().astype(np.float64)+        mx_b = np.asarray(stage_b.X.max(axis=0).todense()).ravel().astype(np.float64)+        cap = (BRACKET_CLIP * np.maximum(mx_a, mx_b)).astype(np.float32)+        n_over = int((expr > cap[None, :]).any(axis=1).sum())+        expr = np.minimum(expr, cap[None, :]).astype(np.float32)+        clamp_info["n_clamped_cells"] = n_over+    tshift_info = {"tshift_enable": bool(TSHIFT_ENABLE), "tshift_kappa": TSHIFT_KAPPA,+                   "tshift_f_mean": None, "tshift_f_min": None, "tshift_f_max": None,+                   "tshift_n_moved": 0, "tshift_dp_top50_changed": None,+                   "tshift_timing_absmean": None}+    if TSHIFT_ENABLE and expr.shape[0] and ia.size and ib.size:+        if TSHIFT_MODE == "leakfix":+            # No timing model: f_g = t for every reliable gene — removes the+            # nnz-mask/clip leakage of the displacement pipeline so that dp+            # equals the clean linear-interpolation estimate t·Δ_pb.+            f_g = np.full(len(stage_a.genes), float(t))+        else:+            la_all = np.asarray(stage_a.labels).astype(str)+            lb_all = np.asarray(stage_b.labels).astype(str)+            shared_lab = sorted(set(la_all.tolist()) & set(lb_all.tolist()))+            timing = timing_fraction(stage_a, stage_b, shared_lab, TSHIFT_KAPPA)+            f_g = np.clip(t + TSHIFT_KAPPA * timing, TSHIFT_FLO * t, min(TSHIFT_FHI * t, 0.9))+        pb_a = np.asarray(stage_a.X.mean(axis=0)).ravel().astype(np.float64)+        pb_b = np.asarray(stage_b.X.mean(axis=0)).ravel().astype(np.float64)+        dpb = pb_b - pb_a+        pb_out = expr.mean(axis=0).astype(np.float64)+        top_before = set(np.argsort(-np.abs(pb_out - pb_a))[:50].tolist())+        target_pb = pb_a + f_g * dpb+        s = np.clip(target_pb / np.maximum(pb_out, PBPROJ_FLOOR), 1.0 - TSHIFT_CAP, 1.0 + TSHIFT_CAP)+        s = np.where(np.abs(dpb) >= TSHIFT_MIN_DELTA, s, 1.0)+        expr = (expr * s.astype(np.float32)[None, :]).astype(np.float32)+        dp_after = expr.mean(axis=0).astype(np.float64) - pb_a+        top_after = set(np.argsort(-np.abs(dp_after))[:50].tolist())+        moved = np.abs(dpb) >= TSHIFT_MIN_DELTA+        tshift_info.update(+            tshift_f_mean=float(f_g[moved].mean()) if moved.any() else None,+            tshift_f_min=float(f_g[moved].min()) if moved.any() else None,+            tshift_f_max=float(f_g[moved].max()) if moved.any() else None,+            tshift_n_moved=int(moved.sum()),+            tshift_mode=TSHIFT_MODE,+            tshift_timing_absmean=(float(np.abs(timing[moved]).mean())+                                   if (moved.any() and TSHIFT_MODE != "leakfix") else None),+            tshift_dp_top50_changed=int(50 - len(top_before & top_after)),+        )+    pbproj_info = {"pbproj_enable": bool(PBPROJ_ENABLE), "pbproj_eta": PBPROJ_ETA,+                   "pbproj_k": PBPROJ_K, "pbproj_src": PBPROJ_SRC,+                   "pbproj_n_boosted": 0, "pbproj_s_min": None, "pbproj_s_max": None,+                   "pbproj_s_mean": None, "pbproj_dp_top50_changed": None}+    if PBPROJ_ENABLE and PBPROJ_ETA != 0.0 and expr.shape[0] and view is not None:+        pb_a = np.asarray(stage_a.X.mean(axis=0)).ravel().astype(np.float64)+        pb_out = expr.mean(axis=0).astype(np.float64)+        dpb_out = pb_out - pb_a+        top_before = set(np.argsort(-np.abs(dpb_out))[:50].tolist())+        w = None+        if PBPROJ_W_MODE == "tf":+            w = tf_indicator(view, list(stage_a.genes))+            if w is not None:+                pbproj_info["pbproj_w_mode"] = "tf"+        else:+            M, names = load_pathway_sets(view, list(stage_a.genes), PBPROJ_SRC)+            if M is not None:+                pb_b = np.asarray(stage_b.X.mean(axis=0)).ravel().astype(np.float64)+                dpb = pb_b - pb_a+                if PBPROJ_BOOST_MODE in ("graded", "graded_max"):+                    w, _ = pathway_boost_graded(np.abs(dpb), M, PBPROJ_K)+                else:+                    w, _ = pathway_boost(np.abs(dpb), M, PBPROJ_K)+                pbproj_info["pbproj_w_mode"] = "pathway"+                pbproj_info["pbproj_n_pathways"] = int(M.shape[0])+        if w is not None:+            corr = PBPROJ_ETA * w * dpb_out / np.maximum(pb_out, PBPROJ_FLOOR)+            s = np.clip(1.0 + corr, 0.0, 1.0 + PBPROJ_CAP)+            expr = (expr * s.astype(np.float32)[None, :]).astype(np.float32)+            top_after = set(np.argsort(-np.abs(expr.mean(axis=0).astype(np.float64) - pb_a))[:50].tolist())+            pbproj_info.update(+                pbproj_n_boosted=int((w > 0).sum()),+                pbproj_boost_max=float(w.max()),+                pbproj_s_min=float(s.min()), pbproj_s_max=float(s.max()),+                pbproj_s_mean=float(s.mean()),+                pbproj_dp_top50_changed=int(50 - len(top_before & top_after)),+            )     coord_parts = []     if ia.size:         coord_parts.append(np.asarray(ca[ia], dtype=np.float64))@@ -562,6 +984,9 @@ def mix_converge(stage_a, stage_b, t: float, params: dict, alpha: float):     info.update(aniso_info)     info.update(ta_info)     info.update(variso_info)+    info.update(pbproj_info)+    info.update(tshift_info)+    info.update(clamp_info)     info.update(         t=t, n=int(expr.shape[0]), rms_a=rms_a, rms_b=rms_b, target_rms=target_rms,         out_rms=rms_radius(coords), n_from_a=int(ia.size), n_from_b=int(ib.size), **conv, **pair_info,@@ -574,7 +999,11 @@ def main() -> None:     parser.add_argument("--data", required=True)     parser.add_argument("--out", required=True)     parser.add_argument("--seed", type=int, default=0)+    parser.add_argument("--ablate", default=None,+                        help="mechanism-off control: 'mechanism' (or any name) sets PROJ_ETA=0, "+                             "reproducing the parent node bit-for-bit")     args = parser.parse_args()+    proj_eta = 0.0 if args.ablate else None      manifest = load_manifest(args.data)     genes = panel_genes(args.data, manifest)@@ -588,13 +1017,24 @@ def main() -> None:     stage_a = read_stage(args.data, a, genes)     stage_b = read_stage(args.data, b, genes)     params = board_params(manifest, "mix", PARAMS, args.seed)-    expr, coords, info = mix_converge(stage_a, stage_b, t, params, CONVERGE_ALPHA)+    expr, coords, info = mix_converge(stage_a, stage_b, t, params, CONVERGE_ALPHA,+                                      view=args.data, proj_eta=proj_eta)     keep = {k: info.get(k) for k in ("t", "n", "rms_a", "rms_b", "out_rms", "n_shared_types", "z_dot", "z_flipped",                                      "align", "alpha", "n_shared_types_converged", "within_type_std_rel",                                      "between_type_mean_dist_rel", "n_from_a", "n_from_b",                                        "lambda", "weight_mean", "weight_std",-                                        "soft_enable", "soft_tau", "soft_p",-                                        "soft_n_participating_mean", "soft_n_hard_mean",+                                         "soft_enable", "soft_tau", "soft_p",+                                         "soft_n_participating_mean", "soft_n_hard_mean",+                                        "proj_eta", "proj_mode", "proj_k", "proj_n_pathways",+                                        "proj_cos_mean", "proj_cos_min", "proj_boost_mean",+                                        "pbproj_enable", "pbproj_eta", "pbproj_k", "pbproj_src",+                                        "pbproj_n_pathways", "pbproj_n_boosted", "pbproj_boost_max",+                                        "pbproj_s_min", "pbproj_s_max", "pbproj_s_mean",+                                        "pbproj_dp_top50_changed",+                                        "tshift_enable", "tshift_kappa", "tshift_f_mean",+                                        "tshift_f_min", "tshift_f_max", "tshift_n_moved",+                                        "tshift_mode", "tshift_timing_absmean", "tshift_dp_top50_changed",+                                        "bracket_clip", "n_clamped_cells",                                        "pair_beta", "n_paired_types", "n_pairs", "pair_within_std_rel",                                        "pair_orth_var_rel", "pair_dist_over_diam",                                        "aniso_enable", "aniso_damp", "aniso_gamma", "aniso_spread_a",

调研来源?调研员查到并用到的知识条目和文献检索结果(只列标题和编号)。

用到的知识库条目

编号标题出处
k007Interval staging and held-out-window filtering of external datanotes/official/来件/virtualembryo.ai/rules.md
k026Canonicalise predicted 3D coordinates before submissionnotes/pitfalls/04_scorer_invariance.md
k024World-model evaluation dimensions for state-transition predictorsnotes/competition/07_biomedical_world_models.md

分析结果?分析员写的 ANALYSIS.json:改了什么、各组分数怎么变、假设是否成立、经验和下一步建议。

改了什么PLAN 字面的通路 boost 被 Engineer 证否(分层混抽 (1−t,t) 权重使位移在伪批量中精确对消,top-50 |dp| 变化 ≤2 基因,存档查分 60.86 劣于父),改交同族备选解码:对逐类型 Δ 做范数保持 + 支持集限制(|Δ|≥0.15)的基因相关扩散 Δ'=renorm(Δ+η·C·Δ),η=1,C 为括号两阶段全细胞的基因-基因 Pearson 相关;η=0 时与父节点 27 逐位一致。
各组分数的变化cell_state:变好(部分噪声内):+0.54(50.36→50.90)。variogram raw 0.01382→0.01300,skill 0.391→0.406,得分 +0.19;mmd_u raw 0.01126→0.01146 微劣,得分 −0.05。
expression_change:变坏(噪声内):−0.15(62.16→62.01)。目标指标 de_score raw 0.3103 完全不动(得分 7.50→7.50),de_direction raw 0.4009→0.3943,得分 −0.04。注意:Engineer 声称的 de_score 0.25→0.2857 是 A 半 proxy seed0 上的结果,在本次计分板上未兑现。
local_spatial:变好:+1.70(60.37→62.07)。neighborhood_mmd raw 0.05106→0.04758,skill 0.604→0.621,得分 +0.42。是本次收益最大项,且 ablation 关闭机制后榜分 −0.52,说明收益确来自该机制。
shape_scale:噪声内/不变:+0.00(77.31→77.31),坐标未动,三项 raw 逐位相同,符合设计。
family_idT2EI-01
假设是否成立否
经验
  1. 在分层混抽 (1−t,t) 的输出管线上,任何只作用于逐细胞位移步内部、不改幅度/非线性的 Δ 方向校正都会在伪批量中精确对消,DE 两项(只看 dp)结构性不可见——通路 boost 8 个离线配置 top-50 |dp| 变化 ≤2 基因即此因。
  2. 对 Δ 做相关扩散时不加范数保持会把幅度放大 ~10 倍(表达值爆到 147),mmd_u 从 0.0117 崩到 0.0210;renorm(Δ+ηCΔ) + 支持集限制(|Δ|≥0.15)剥离幅度后才是可用的方向校正。
  3. A 半 proxy 上 de_score 0.25→0.2857 的提升未在计分板兑现(raw 0.3103 逐位不动):小样本 proxy 上 de_score 的档位跳变(1/N 粒度)不可外推,不能当作真实收益。
  4. 相关扩散的实际收益通道不是 PLAN 预期的 DE 排序,而是 neighborhood_mmd(+0.42 分)和 variogram(+0.19 分)——方向对齐协同变化程序改善了表达-位置配对和共变结构;净 +0.52 榜分接近 T2 噪声(~1 分),但 ablation −0.52 且跨 seed 一致,机制真实。
  5. within-type 残差核(62.06 对比 61.85)劣于全细胞核:类型间组成共变结构本身对扩散有用,不要过早去除。
mechanism_active是
下一步建议
  1. 针对 local_spatial(本次最大收益源):试不对称/迭代扩散——只对 b 侧细胞扩散,或用位移后残差重新计算相关核再迭代一步(η 保持 1,support 保持 0.15),目标是把 neighborhood_mmd raw 从 0.0476 再压低。
  2. 针对 cell_state 的 mmd_u 微损(−0.05 分):试 clip 感知扩散,对位移后接近 0(会被 clip≥0 整流)的基因减弱校正权重,验证 mmd_u raw 能否回到 ≤0.01126。
  3. 停止在 dp 重排/de_score 上投入(计分板 raw 0.3103 纹丝不动,8 种独立重排均未突破);若要攻 expression_change,应绕过位移步、直接作用于输出表达矩阵,但预期值低,优先级排在 neighborhood_mmd 之后。

对话摘要?每个角色和大模型对话的统计:轮数、工具调用、用时、token 数和最后的回答摘录;原始记录只给路径。

只给统计和最后回答的摘录;完整对话请到原始记录位置里列出的文件看。

分析员

角色?调研员写计划、工程师改代码、分析员解读分数、审查员检查作弊。分析员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数?大模型一共回复了几轮(每轮可以调用多个工具)。3
工具调用?大模型调用读文件、执行命令等工具的次数,按工具名统计。共 3 次:bash 1、read 1、write 1
用时不到 1 分
token 数?输入 / 输出(含思考)的 token 数,来自接口返回的用量。输入 23,110 · 输出 1,397 · 思考 1,281
任务(第一行)分析节点 n31 的打分结果,写 ANALYSIS.json
最后的回答(摘录)
ANALYSIS.json written
原始记录位置?完整对话记录在 Spark 上的文件路径;看板不复制原始内容。/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/analyst.jsonl 17 KB
/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/analyst.stderr

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数119
工具调用共 130 次:bash 81、edit 44、read 3、write 2
用时1 小时 13 分
token 数输入 238,799 · 输出 43,414 · 思考 71,896
任务(第一行)按计划修改程序:通路/相关先验投影校正逐类型位移方向攻 de_score top-N 排序
最后的回答(摘录)
Done. Final state verified: defaults reproduce the scored 62.06 config, `--ablate mechanism` reproduces parent bit-for-bit, deterministic, view-independent (disguised-view test passed), vec-check ok on seeds 0/1/2.

**做了什么**:实现 PLAN 的通路/相关先验投影后发现结构性对消——分层混抽的 (1−t,t) 权重使 Δ 位移在伪批量中精确抵消,de_score/de_direction 只看 dp,故通路 boost(8 个离线配置,top-50 |dp| 变化 ≤2 基因)按 PLAN 自己的筛选线无效(存档查分 60.86,劣于父节点)。改交同族备选解码:范数保持 + 支持集限制(|Δ|≥0.15)的基因相关扩散 Δ'=renorm(Δ+C·Δ),只转方向、不爆幅度、不招募噪声基因。

**查分结果**(A 半 proxy,19/20 次):提交配置 seed 0 = **62.06**(父 61.48,+0.58),seed 1 配对 = 61.55 vs 60.93(+0.63)。收益:neighborhood_mmd +0.40、de_score raw 0.25→0.2857、variogram +0.12~0.19;微损 mmd_u −0.08、de_dir −0.07。中间共证否 7 个变体(TF 重排两向、tshift 时序、leakfix、pb 级通路放大、无范数 corr、clamp 组合),全部记录在 METHOD.md §5。

**下一步最值得试**:(1) 相关扩散的不对称解码(只对 b 侧或用位移后残差核迭代一步),neighborhood 是最大收益来源;(2) clip 感知扩散以挽回 mmd_u 微损;(3) de_score 0.2857 疑似局部上限,勿再投 dp 重排。
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/engineer.jsonl 648 KB
/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/engineer.stderr

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数1
工具调用共 0 次:—
用时2 分
token 数输入 18,899 · 输出 1,133 · 思考 5,429
任务(第一行)为节点 n31(改进,父节点 n27)写改进计划 PLAN.json
最后的回答(摘录)
```json
{
  "name": "通路/相关先验投影校正逐类型位移方向攻 de_score top-N 排序",
  "motivation": "父节点 27 的 ANALYSIS 明确指出 de_score(raw 0.3103,skill 0.600)缺口不在幅度而在位移方向的基因级错位:α·Δ_type 与真值 dt 的基因排序不一致,导致 |dp| top-N 集合与 |dt| top-N 重合率低。软阈值(节点 27)把参与基因从 166 扩到 478 但 de_score 纹丝不动,证实问题在方向而非阈值。expression_change 组 62.16 是仅次于 cell_state(50.36)的第二弱组,de_score 是该组内最弱指标(7.50/12.5)。",
  "approach": "步骤:1) Engineer 先检查视图 prior/ 目录是否有通路/基因集文件(Reactome、CollecTRI、GO 等);若有,构建通路×基因二元矩阵 M;若无,用括号两阶段全部细胞计算基因-基因 Pearson 相关矩阵 C(~498×498)作为平滑核。2) 对每个共有类型的 Δ=μ_b−μ_a:(a) 通路版:计算通路活性分 s_p=mean(|Δ_g|, g∈p),取 top-k(k=30)活性通路,对每个基因 g 计算 boost_g = (g 所属活性通路数)/(g 所属总通路数),Δ'_g = Δ_g·(1+η·boost_g);(b) 相关版(fallback):Δ' = Δ + η·C·Δ(一步扩散),然后对 Δ' 做 clip 保持 nnz-only 语义(只移已表达项)。3) 用 Δ' 替换原 Δ 进入既有位移步(α=5、λ=6、β=0.2、软权重均保留不变)。4) η 初值 1.0,搜索 {0.5, 1.0, 2.0};通路版 k 搜索 {20, 30, 50}。5) 快速筛选:先在 seed 0 上比较 off/on 的 |dp| top-50 基因集合重合率变化(若重合率变化 <2 个基因则方向无效,尽早放弃);再 vec-score 查分确认。6) 单输入阶段(无括号)走既有 copy_last 退路,校正代码不执行。7) 不新增随机源,确定性输出。",
  "expected_groups": ["expression_change"],
  "risks": "1) prior/ 为空或无可用通路文件 → Engineer 第一步检查,立即切换到相关矩阵 fallback;2) 通路/相关校正改变不了 top-N 集合(Δ 的排序本身已接近最优)→ 用 top-50 重合率快速判断,若 <2 个基因变化则停止;3) η 过大导致位移方向过度偏离 Δ、mmd_u 恶化 → 否决线 mmd_u raw 增幅 <0.001,η=2 时若破线则放弃;4) 相关矩阵在小样本类型上噪声大 → 只用 ≥10 细胞的类型,相关矩阵用全类型合并计算;5) 效应量在噪声(~1 分)内 → 若 A 半提升 <0.5 分且 top-N 重合率无变化,如实报告失败。",
  "family_id": "T2EI-01",
  "mechanism": "用通路成员关系(或基因-基因相关矩阵)对逐类型伪时间差 Δ 做方向投影/平滑,使位移方向与生物学上协调变化的基因簇对齐,从而改变 |dp| 的 top-N 排序集合。",
  "vs_constant_shift": "常数位移对所有基因施加同一方向同一幅度;本机制按通路/相关结构对每个基因施加不同的方向校正权重(boost_g 因基因而异),且校正方向取决于该基因所属通路的集体活性,不是全局均匀缩放或组成重加权。",
  "mechanism_evidence": "1) 比较 off/on 下 |dp| top-50 基因集合:报告进入/退出 top-50 的基因数及身份;2) de_score raw 变化(目标 ≥+0.02);3) 逐类型 Δ 与 Δ' 的余弦相似度分布(应 <1 但 >0.5,证明方向改变但不过度);4) 四组分各自变化,确认 cell_state/local_spatial/shape_scale 无恶化。",
  "mechanism_off_control": "η=0(环境变量 T2_PROJ_ETA=0)时 Δ'=Δ,输出与父节点 27 逐位一致。Engineer 用 seed 0 验证 off 输出与父节点 A 半分数(62.55 或 A 半 61.48)完全匹配。",
  "sources": []
}
```
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/researcher.jsonl 5 KB
/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/researcher.stderr

审查员

角色审查员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数13
工具调用共 12 次:read 6、bash 4、grep 1、write 1
用时2 分
token 数输入 44,147 · 输出 2,007 · 思考 2,542
任务(第一行)审查节点 n31 的程序是否越界读取、写死目标、钻评分器漏洞
最后的回答(摘录)
REVIEW.json written
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/reviewer.jsonl 204 KB
/home/spark-longxinyang/vec/runs/formal/20261003-171955-search-t2-embryo-interp-chain-12h/nodes/31/reviewer.stderr