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

总览 · ← 返回运行 20261003-004922-search-t2-heart-interp-g24

节点 n21

实现PLAN T2HI-04结构性修复:把型内b→a的1-NN贪心换成容量约束最优指派(LAP),实测local_spatial零响应、shape/expression小幅变差,提交态默认关闭(输出与节点19逐位一致)。

运行?一次完整的自动搜索或 Agent 会话,有自己的锁定配置和证据包。20261003-004922-search-t2-heart-interp-g24
父节点n19
子节点n23
操作?种子:人写的起点;改进:在父节点上改;草稿:从头写;修复:修父节点的报错。改进
状态已打分
分数搜索目标分 61.79(+0.0) · proxy 61.79(+0.0) · 3 次复测均分 61.40
审查通过 1 越界读取:未发现问题——run.py 仅通过 load_manifest/read_stage/panel_genes(args.data) 读取视图输入,无绝对路径、'..'、/mnt、/home、data/raw、评分器或 src/common/evaluation 引用,无联网;src.task2_spatial 为家族共用的视图 I/O 与几何工具库;METHOD.md 声明未读 external/ 与 prior/。; 2 硬编码目标统计量:未发现问题——所有量(t、类型均值差 delta、RMS、kNN、LAP 指派、分位数门控阈值、PCA 轴)均从 manifest 输入现…
用时?从运行开始到结束(或到现在)的挂钟时间。19 分
程序版本5e9b420bfb4ad5616e17968ff42bb3f6c11f7034 (programs.git)

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

来自 programs.git 5e9b420bfb:solution/METHOD.md

实现PLAN T2HI-04结构性修复:把型内b→a的1-NN贪心换成容量约束最优指派(LAP),实测local_spatial零响应、shape/expression小幅变差,提交态默认关闭(输出与节点19逐位一致)。

方法(family T2HI-04,improve 自节点 19)

底座与节点 19 完全一致:双 bracket 组成插值 → Procrustes 对齐 → 统一 log 插值 RMS → 型内 NN 坐标融合(α=1.0)→ chg_l2 分位数门控表达混合(γ=2.8, q=0.8)→ jitter → RMS → PCA canon。表达侧未改动。

新增(_capacity_assign,run.py):每个共有型内,b 侧细胞到 a 侧细胞的配对由「无约束 1-NN 贪心」改为容量约束指派——每个 a 细胞最多承接 capacity 个 b 细胞。两种模式:

  • T2HI_CAP=c:固定容量。指派用 a 侧复制 c 份后的最优 LAP(scipy.optimize.linear_sum_assignment,最小化总距离;行列式规模 n_b×(n_a·c) ≤ 6e7 时启用),超限则退回 kNN 贪心两轮(k=8→64,按距离升序稳定排序)。
  • T2HI_CAP_KAPPA=κ:逐型容量 cap=ceil(κ·n_b/n_a),κ=1 时 n_a·cap ≥ n_b,保证零未融合,只把占用摊平。
  • T2HI_CAP=0(默认,提交态):cap := n_b,走原 k=1 查询路径,逐位退化为节点 19。

未拿到槽位的 b 细胞保留 Procrustes 坐标(不融合),也不进入表达混合(nn_b/nn_a 只含已指派对)。

机制生效证据(PLAN mechanism_evidence 五项,proxy seed 0)

每型 n_b/n_a 实测(PLAN 风险 1 的反面:绝大多数型 n_b ≫ n_a,机制有大量操作空间):NCC 0.76、Peri 9.29、V-CM 4.97、aPHM 1.25、pPHM 4.31;均值 4.11。共有型 a 侧合计 7115、b 侧 17338。

配置型内 unique 坐标(融合前→后)occ_max 均值a 细胞被用比例未融合nn_dist_aftermean_disp
cap=0(off,=节点19)3467.6 → 124.6——00.0200.6
cap=13467.6 → 3467.61.00.95111062 (63.8%)124.6148.5
cap=23467.6 → 2709.62.00.8478480 (48.9%)87.1251.9
cap=33467.6 → 2171.43.00.8006263 (36.1%)59.6299.2
κ=1.0(cap_mean 4.60)3467.6 → 1167.24.60.8870——

即:机制确实消除了坐标坍缩(unique 位置 124.6 → 1167.2,κ=1 时零未融合;cap=1 时全部分开)。

机制关闭对照与查分(A半,seed 0;节点正式分用 B半)

off 对照 T2HI_CAP=0:与节点 19 输出 np.array_equal 验证 X 与坐标逐位一致,分数复现 61.346(=节点19 的 61.346),四组分 expr 67.82 / cell_state 66.13 / shape 53.62 / local 57.81。

配置榜分expression_changecell_statelocal_spatialshape_scale关键 metric
off(cap=0,提交态)61.34667.8266.1357.8153.62neighborhood_mmd 0.07001, occ_dice 0.8285, d2_shape 0.03545, variogram 0.02829
cap=159.78564.9966.0554.6953.41nb_mmd 0.07942↑, occ_dice 0.8398↑, d2_shape 0.03952↑, de_score 0.3696↓
κ=1.0(零未融合)61.06367.1966.0757.8353.17nb_mmd 0.06997, occ_dice 0.8364↑, d2_shape 0.03960↑
mutual=1(a 侧也向 b 位移,附带试验)61.36467.8266.1357.9453.57nb_mmd 0.06966, d2_shape 0.03581

四组分变化(κ=1 vs off):local_spatial +0.02(噪声内)、shape_scale −0.45、expression_change −0.63、cell_state −0.06。cap=1 vs off:local_spatial −3.12、expression −2.83。

结论:PLAN 的机制假设被证伪。 坐标坍缩(124.6 unique)不是 local_spatial 的瓶颈——把它彻底消除(κ=1,零未融合、unique×9.4)后 neighborhood_mmd 只从 0.07001 → 0.06997、local_spatial 57.81 → 57.83(+0.02 ≪ 噪声 2)。反而 occupancy_dice 上升(0.8285→0.8364)而 d2_shape 明显变差(0.03545→0.03960),两者相抵后 shape_scale 净降 0.45;表达侧因为配对变了、chg_l2 门控选中的细胞集不同而掉 0.63。cap=1 更差:64% 的 b 细胞退回 Procrustes 位置,neighborhood_mmd 恶化到 0.07942——与节点 18「α_low<1 单调降分」同一方向:融合越彻底越好,任何削弱型内融合的改动都降分。

按 PLAN 风险 2/3(capacity=1 降分则试 2;提升 <0.5 判无效):cap=1/2/3 与 κ=1 全部 ≤ off,故提交态取 T2HI_CAP=0,即节点 19 的行为,改动分数中性偏保守。

下一步(数据支持的)

  1. local_spatial 的唯一正向信号是「更彻底的融合」:mutual=1(a 侧也向最近 b 位移)给出 local 57.94 / nb_mmd 0.06966,净 +0.02,仍在噪声内。若要继续攻该组分,应扫 mutual 的 α_a(a 侧位移系数)与「b→a 的 k-NN 质心融合」而不是配对拓扑。
  2. shape_scale 的 d2_shape 与 occupancy_dice 对坐标重分配的反应方向相反,说明它不是单一可优化目标;scale_log_ratio 恒为 0.4669(RMS 由 bracket log 插值决定,proxy 上够不到真值),该组分基本是 mix 家族的结构性天花板,建议停止投入(与节点 11–19 一致)。
  3. expression_change 对「哪些 b 细胞被融合」高度敏感(cap=1 时 de_score 0.4457→0.3696):门控量 chg_l2 依赖配对,配对一变选中集就变。若以后改配对,应把表达门控的 d 固定在原 1-NN 配对上以解耦。

验证过 / 未验证

  • 已验证:off 与节点 19 逐位一致(X + 坐标);off 分数复现 61.346;seed 1 两次运行逐位一致(确定性);vec-check ok;cap/κ 全部诊断量;~2–21 s(cap=3 最慢 21 s,off 1.6 s)、峰值 <0.75 GB,远低于 limits(28 GB / 30 min)。
  • 未验证:B半正式分(提交态输出与节点 19 逐位相同,预期 ≈61.79);真实括号(31 共有型、n_b/n_a 比值分布不同)上容量约束的效果——proxy 上机制方向已明确为负,未再花额度;κ<1 与 κ>1 的细网格(κ=1 已是零未融合的边界,κ>1 只会退回无约束)。

知识来源

未使用任何保留阶段/保留基因型信息、文献数值或外部数据(external/、prior/ 未读)。所有统计量(型内 n_b/n_a、kNN、指派、分位数、RMS、PCA 轴)均由当次视图输入现场计算,不依赖视图路径或绝对时间(只用时间差 t),满足视图无关要求。生物学知识仅沿用父节点:细胞类型标签(输入 obs 自带)用于型内配对。

调研员的计划

名称容量约束型内NN配对:消除多对一坐标坍缩,改善local_spatial
动机节点19 local_spatial=58.24为第二低组。当前α=1.0的1-NN融合中,多个b细胞可映射到同一a细胞位置,造成坐标重复/局部密度尖峰,破坏邻域连续性。shape_scale=54.15中occupancy_dice≈0.83也受此影响。节点10-19从未改动配对结构本身(只调α、弥散、表达γ),本方案首次将贪心1-NN替换为容量约束指派,属结构性修复而非参数调整。
做法在节点19的run.py _blend_within_type函数中,将每型b→a的1-NN贪心替换为容量约束贪心指派:
1. 对每个共有型,用cKDTree计算b侧每个细胞的k近邻(k=min(n_a, 10))候选a细胞及距离。
2. 按b细胞到最近a的距离升序排列;依次贪心指派:b_i取其最近的、当前占用数<capacity的a_j;占用满则尝试次近、再次近,直到用完k个候选。
3. 所有候选均满的b细胞保留Procrustes坐标(不融合),并打印未融合比例。
4. capacity默认=1,搜索{1,2,3};capacity≥n_b时退化为原始1-NN(off对照)。
5. 融合后的表达混合(chg_l2门控、γ=2.8、q=0.8)逻辑不变,只改坐标配对。
6. 单输入阶段退路:t=0时copy_last路径不经过融合,无影响。
7. vec-score快速筛选:先跑capacity=1 vs off(capacity=999)各一次(2次查分),确认local_spatial方向;再跑capacity=2(第3次);总查分≤5。预期:capacity=1时unique坐标数增加、local_spatial +0.5~1.5。
风险1. 若每型b细胞数≤a细胞数,capacity=1与原始1-NN结果相同,机制无操作空间——Engineer应先打印每型n_b/n_a比值,若多数型n_b≤n_a则提前终止。2. 未融合b细胞留在Procrustes位置可能引入空间不连续,反而降分——若capacity=1降分,尝试capacity=2。3. 30分钟时限:改动集中在_blend_within_type一个函数,用现有cKDTree,代码量小;先打印诊断再查分。

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

对比:父节点版本 7a54c1b282。改动的文件:solution/METHOD.md +42 −19、solution/run.py +114 −8

diff --git a/solution/METHOD.md b/solution/METHOD.mdindex 86f332b..3d03d4f 100644--- a/solution/METHOD.md+++ b/solution/METHOD.md@@ -1,36 +1,59 @@-实现PLAN T2HI-06:融合坐标云的PCA逐轴异速缩放(实测因子≈1、proxy上结构性退化、分数中性,默认关)与PCA手性canonicalization(det −1→+1、消除取向方差,默认开),关闭对照与节点18逐位一致。+实现PLAN T2HI-04结构性修复:把型内b→a的1-NN贪心换成容量约束最优指派(LAP),实测local_spatial零响应、shape/expression小幅变差,提交态默认关闭(输出与节点19逐位一致)。 -## 方法(family T2HI-06,improve 自节点 18)+## 方法(family T2HI-04,improve 自节点 19) -底座与节点 18 完全相同:双 bracket 组成插值 → Procrustes 对齐 → 统一缩放到 log 插值 RMS → 型内 NN 坐标融合(α=1.0)→ chg_l2 分位数门控表达混合(q=0.8, γ=2.8)。表达侧未做任何改动。+底座与节点 19 完全一致:双 bracket 组成插值 → Procrustes 对齐 → 统一 log 插值 RMS → 型内 NN 坐标融合(α=1.0)→ chg_l2 分位数门控表达混合(γ=2.8, q=0.8)→ jitter → RMS → PCA canon。表达侧未改动。 -在最终坐标云(jitter + 统一 RMS 缩放之后、写出之前)新增两步,均在 `run.py`:+新增(`_capacity_assign`,`run.py`):每个共有型内,b 侧细胞到 a 侧细胞的配对由「无约束 1-NN 贪心」改为**容量约束指派**——每个 a 细胞最多承接 `capacity` 个 b 细胞。两种模式: -1. **步骤2 PCA canonicalization(`T2HI_CANON`,默认 1,提交态开)**:减质心 → SVD 取 PCA 轴旋转 → 若 det<0 翻转最后一轴强制 det=+1 → 每轴按第三矩(偏度)符号定向。`_canonicalize()`。-2. **步骤1 per-axis anisotropic scaling(`T2HI_ANISO`,默认 0,提交态关)**:对输出云 PCA,分别计算 lower-bracket 子云(前 n_a 个细胞)与 upper-bracket 子云在每轴上的 σ_lo[k]、σ_hi[k],目标 σ_target[k]=exp((1−t)·lnσ_lo[k]+t·lnσ_hi[k]),每轴乘 σ_target[k]/σ_current[k];σ<1e-6 的轴跳过。单 bracket 退化时因子恒为 1。`_aniso_scale()`。+- `T2HI_CAP=c`:固定容量。指派用 a 侧复制 c 份后的**最优 LAP**(`scipy.optimize.linear_sum_assignment`,最小化总距离;行列式规模 n_b×(n_a·c) ≤ 6e7 时启用),超限则退回 kNN 贪心两轮(k=8→64,按距离升序稳定排序)。+- `T2HI_CAP_KAPPA=κ`:逐型容量 `cap=ceil(κ·n_b/n_a)`,κ=1 时 n_a·cap ≥ n_b,**保证零未融合**,只把占用摊平。+- `T2HI_CAP=0`(默认,提交态):cap := n_b,走原 k=1 查询路径,**逐位退化为节点 19**。 -两步只依赖数据与 t(时间差),不依赖视图路径/绝对时间,满足视图无关要求;t≤0 fallback(copy_last 路径)不施加任何旋转,保持"原样输出"语义。+未拿到槽位的 b 细胞保留 Procrustes 坐标(不融合),也不进入表达混合(`nn_b/nn_a` 只含已指派对)。 -## 机制生效证据(PLAN mechanism_evidence 四项)+## 机制生效证据(PLAN mechanism_evidence 五项,proxy seed 0) -1. **三轴缩放因子**(proxy, seed 0):factors=[0.9996, 0.9878, 0.9984],σ_lo=[243.6, 209.4, 151.3]、σ_hi=[237.0, 166.3, 163.9]、σ_cur=[241.0, 193.3, 156.5]、σ_target=[240.9, 191.0, 156.2]。因子确实逐轴不同(≠均匀),机制在代码层面生效;但幅度 ≤1.2%——**(1−t)/t 混合云本身的逐轴 σ 已自动接近对数插值目标,该机制对 mix 家族结构性近退化**,这是本节点的主要负结果。-2. **canonicalization det**:det_before=−1.000 → 强制 +1,偏度定向 flips=[−1,+1,−1](净 det 仍 +1)。原坐标云确实处于反射手性,canon 实际改变了输出坐标(旋转/反射,非恒等)。-3. **四组分逐项变化**(A半,seed 0,vs 父节点 61.35):canon-only 61.346:expr_change 67.82(+0.00)、cell_state 66.13(+0.00)、shape_scale 53.62(+0.00)、local_spatial 57.81(+0.00);aniso+canon 61.344:shape_scale 53.61(−0.01)、local_spatial 57.82(+0.01),d2_shape 0.03545→0.03582、scale_log_ratio 0.4669→0.4626(有响应但在噪声内)。**评分器对整体旋转/反射不变**(canon 改变坐标却不改变任何 metric 到 3 位小数),PLAN 假设的"取向方差"在固定输入下不存在(管线本身确定)。-4. **两种子 shape_scale 方差**:canon 版 seed0 shape_scale=53.62、seed1=54.00,与父节点(61.35/61.55 及同组分值)逐位一致,方差无变化(本就为确定性零方差)。+每型 n_b/n_a 实测(PLAN 风险 1 的反面:绝大多数型 n_b ≫ n_a,机制**有大量操作空间**):NCC 0.76、Peri 9.29、V-CM 4.97、aPHM 1.25、pPHM 4.31;均值 4.11。共有型 a 侧合计 7115、b 侧 17338。 -## 机制关闭对照(PLAN mechanism_off_control)+| 配置 | 型内 unique 坐标(融合前→后) | occ_max 均值 | a 细胞被用比例 | 未融合 | nn_dist_after | mean_disp |+|---|---|---:|---:|---:|---:|---:|+| cap=0(off,=节点19) | 3467.6 → **124.6** | — | — | 0 | 0.0 | 200.6 |+| cap=1 | 3467.6 → 3467.6 | 1.0 | 0.951 | 11062 (63.8%) | 124.6 | 148.5 |+| cap=2 | 3467.6 → 2709.6 | 2.0 | 0.847 | 8480 (48.9%) | 87.1 | 251.9 |+| cap=3 | 3467.6 → 2171.4 | 3.0 | 0.800 | 6263 (36.1%) | 59.6 | 299.2 |+| κ=1.0(cap_mean 4.60) | 3467.6 → **1167.2** | 4.6 | 0.887 | **0** | — | — | -`T2HI_ANISO=0 T2HI_CANON=0`:输出与节点 18 默认输出 **np.array_equal 验证 X 与坐标逐位一致**(未查分,因逐位相同分数必然相同 = A半 61.35 / 正式 61.87)。开启后(提交态):A半 seed0 61.346 / seed1 61.5518,vs 父 61.35 / 61.55——差别 <0.01,远小于噪声。+即:机制确实消除了坐标坍缩(unique 位置 124.6 → 1167.2,κ=1 时零未融合;cap=1 时全部分开)。 -## 结论与处置(PLAN 风险 3 兑现)+## 机制关闭对照与查分(A半,seed 0;节点正式分用 B半) -aniso+canon 合计 shape_scale 提升 = −0.01~0.00 < 0.5,按 PLAN 步骤 3/风险 3 判机制在 proxy 上无效,提交仅 canonicalization 版本(保守消除手性歧义,代价为零)。aniso 代码保留、开关可复现全部测量。shape_scale 54.46(正式)对逐轴尺度微扰完全无响应,与节点 10–18 的表达侧、弥散、径向尺度实验一致:**该组分的瓶颈不在输出云的二阶形状统计**,而在 scale_log_ratio≈0.47(RMS 目标与真值的 log 比)与 occupancy 一侧;proxy 上任何由 bracket 内插得到的 RMS 都够不到真值(方法卡已注明该非单调性),在不触碰保留信息的前提下 proxy 无法验证 RMS 方向的改动。+off 对照 `T2HI_CAP=0`:与节点 19 输出 **np.array_equal 验证 X 与坐标逐位一致**,分数复现 61.346(=节点19 的 61.346),四组分 expr 67.82 / cell_state 66.13 / shape 53.62 / local 57.81。++| 配置 | 榜分 | expression_change | cell_state | local_spatial | shape_scale | 关键 metric |+|---|---:|---:|---:|---:|---:|---|+| off(cap=0,提交态) | **61.346** | 67.82 | 66.13 | 57.81 | 53.62 | neighborhood_mmd 0.07001, occ_dice 0.8285, d2_shape 0.03545, variogram 0.02829 |+| cap=1 | 59.785 | 64.99 | 66.05 | 54.69 | 53.41 | nb_mmd 0.07942↑, occ_dice 0.8398↑, d2_shape 0.03952↑, de_score 0.3696↓ |+| κ=1.0(零未融合) | 61.063 | 67.19 | 66.07 | **57.83** | 53.17 | nb_mmd 0.06997, occ_dice 0.8364↑, d2_shape 0.03960↑ |+| mutual=1(a 侧也向 b 位移,附带试验) | 61.364 | 67.82 | 66.13 | 57.94 | 53.57 | nb_mmd 0.06966, d2_shape 0.03581 |++四组分变化(κ=1 vs off):local_spatial **+0.02(噪声内)**、shape_scale −0.45、expression_change −0.63、cell_state −0.06。cap=1 vs off:local_spatial **−3.12**、expression −2.83。++**结论:PLAN 的机制假设被证伪。** 坐标坍缩(124.6 unique)不是 local_spatial 的瓶颈——把它彻底消除(κ=1,零未融合、unique×9.4)后 neighborhood_mmd 只从 0.07001 → 0.06997、local_spatial 57.81 → 57.83(+0.02 ≪ 噪声 2)。反而 occupancy_dice 上升(0.8285→0.8364)而 d2_shape 明显变差(0.03545→0.03960),两者相抵后 shape_scale 净降 0.45;表达侧因为配对变了、chg_l2 门控选中的细胞集不同而掉 0.63。cap=1 更差:64% 的 b 细胞退回 Procrustes 位置,neighborhood_mmd 恶化到 0.07942——**与节点 18「α_low<1 单调降分」同一方向:融合越彻底越好,任何削弱型内融合的改动都降分**。++按 PLAN 风险 2/3(capacity=1 降分则试 2;提升 <0.5 判无效):cap=1/2/3 与 κ=1 全部 ≤ off,故提交态取 `T2HI_CAP=0`,即节点 19 的行为,改动分数中性偏保守。++## 下一步(数据支持的)++1. local_spatial 的唯一正向信号是「更彻底的融合」:mutual=1(a 侧也向最近 b 位移)给出 local 57.94 / nb_mmd 0.06966,净 +0.02,仍在噪声内。若要继续攻该组分,应扫 mutual 的 α_a(a 侧位移系数)与「b→a 的 k-NN 质心融合」而不是配对拓扑。+2. shape_scale 的 d2_shape 与 occupancy_dice 对坐标重分配的反应**方向相反**,说明它不是单一可优化目标;scale_log_ratio 恒为 0.4669(RMS 由 bracket log 插值决定,proxy 上够不到真值),该组分基本是 mix 家族的结构性天花板,建议停止投入(与节点 11–19 一致)。+3. expression_change 对「哪些 b 细胞被融合」高度敏感(cap=1 时 de_score 0.4457→0.3696):门控量 chg_l2 依赖配对,配对一变选中集就变。若以后改配对,应把表达门控的 d 固定在原 1-NN 配对上以解耦。  ## 验证过 / 未验证 -- 已验证:默认输出=canon_s0(逐位);同 seed 两次运行逐位一致(确定性);off 对照与节点 18 逐位一致;vec-check ok;A半 seed0 61.346、seed1 61.552;~2s、<1GB。-- 未验证:正式分 B 半(预期与父节点 61.87 几乎相同,改动分数中性);真实括号(31 共有型、E8.25→E8.75 形状差异更大)上 aniso 因子是否仍 ≈1——若真实两 bracket 逐轴 σ 差异大,aniso 会有实质形变,但方向无任何评测可验证,故提交态关闭;canon 在无反射手性的真实云上是近恒等(仅偏度定向),无风险。+- 已验证:off 与节点 19 逐位一致(X + 坐标);off 分数复现 61.346;seed 1 两次运行逐位一致(确定性);vec-check `ok`;cap/κ 全部诊断量;~2–21 s(cap=3 最慢 21 s,off 1.6 s)、峰值 <0.75 GB,远低于 limits(28 GB / 30 min)。+- 未验证:B半正式分(提交态输出与节点 19 逐位相同,预期 ≈61.79);真实括号(31 共有型、n_b/n_a 比值分布不同)上容量约束的效果——proxy 上机制方向已明确为负,未再花额度;κ<1 与 κ>1 的细网格(κ=1 已是零未融合的边界,κ>1 只会退回无约束)。  ## 知识来源 -未使用任何保留阶段/基因型信息、文献数值或外部数据(external/、prior/ 未读)。所有统计量(PCA 轴、逐轴 σ、det、偏度符号、分位数、NN 配对)均由当次视图输入现场计算。生物学知识仅沿用父节点:细胞类型标签用于型内 NN 配对(来自输入 obs)。+未使用任何保留阶段/保留基因型信息、文献数值或外部数据(`external/`、`prior/` 未读)。所有统计量(型内 n_b/n_a、kNN、指派、分位数、RMS、PCA 轴)均由当次视图输入现场计算,不依赖视图路径或绝对时间(只用时间差 t),满足视图无关要求。生物学知识仅沿用父节点:细胞类型标签(输入 obs 自带)用于型内配对。diff --git a/solution/run.py b/solution/run.pyindex 0b3f10e..d0fa7a2 100644--- a/solution/run.py+++ b/solution/run.py@@ -55,7 +55,9 @@ import argparse import os  import numpy as np+from scipy.optimize import linear_sum_assignment from scipy.spatial import cKDTree+from scipy.spatial.distance import cdist  from src.task2_spatial.frame import align_pair, log_interp, rms_radius, scale_to_rms from src.task2_spatial.methods import _jitter@@ -95,6 +97,65 @@ def _borrow(means_src: dict, delta: dict, common: list[str], decay: float = 0.0)     return out  +def _capacity_assign(+    pa: np.ndarray,+    pb: np.ndarray,+    sl: slice,+    capacity: int,+    k_base: int = 8,+) -> tuple[np.ndarray, np.ndarray, int]:+    """Capacity-constrained greedy assignment of b cells to a cells.++    Each a cell may host at most `capacity` b cells. Candidate pairs come from+    the k nearest a neighbours of every b cell (k = min(n_a, max(k_base,+    4*capacity))); all candidate pairs are visited in ascending distance order+    (stable sort -> deterministic) and accepted when both the b cell is still+    free and the a cell still has free capacity. A second round with 8x more+    candidates is run for the b cells left over after round one.+    Returns (assign, occupancy, n_rounds_used); assign[i] = -1 means the b cell+    could not be placed and keeps its Procrustes coordinate.+    """+    n_a, n_b = pa.shape[0], pb.shape[0]+    occ = np.zeros(n_a, dtype=np.int32)+    assign = np.full(n_b, -1, dtype=np.int64)+    cap = max(1, int(capacity))+    n_slots = n_a * cap+    if n_slots >= 1 and float(n_b) * float(n_slots) <= 6.0e7:+        # Optimal (min total distance) capacity-constrained assignment: the+        # a side is replicated `cap` times and solved with the Jonker-Volgenant+        # LAP, so every b cell gets a slot whenever n_a*cap >= n_b.+        PA = np.tile(pa[:, sl], (cap, 1)) if cap > 1 else pa[:, sl]+        C = cdist(pb[:, sl], PA)+        r, c = linear_sum_assignment(C)+        assign[r] = c // cap+        occ[:] = 0+        np.add.at(occ, assign[r], 1)+        return assign, occ, n_b+    # Fallback for very large types: greedy on kNN candidate pairs, ascending+    # distance, two rounds with a widening candidate list.+    tree = cKDTree(pa[:, sl])+    k = int(min(n_a, max(k_base, 4 * cap)))+    for _ in range(2):+        free = np.flatnonzero(assign < 0)+        if free.size == 0:+            break+        dist, idx = tree.query(pb[free][:, sl], k=k)+        if dist.ndim == 1:+            dist = dist[:, None]+            idx = idx[:, None]+        rows = free[np.repeat(np.arange(free.size), dist.shape[1])]+        cols = idx.ravel()+        order = np.argsort(dist.ravel(), kind="stable")+        for o in order:+            bi = rows[o]+            ai = cols[o]+            if assign[bi] < 0 and occ[ai] < cap:+                assign[bi] = ai+                occ[ai] += 1+        k = int(min(n_a, k * 8))+    return assign, occ, n_b++ def _blend_within_type(     ca: np.ndarray,     cb: np.ndarray,@@ -107,6 +168,8 @@ def _blend_within_type(     mutual: bool = False,     disp_beta: float = 0.0,     rng: np.random.Generator | None = None,+    capacity: int = 0,+    cap_kappa: float = 0.0, ) -> tuple[np.ndarray, np.ndarray, dict]:     """Per-type NN coordinate fusion (family T2HI-04 blend) + optional     within-type calibrated dispersion (T2HI_DISP).@@ -130,6 +193,8 @@ def _blend_within_type(     stats = {         "types_fused": 0, "cells_fused": 0, "dist_before": [], "disp": [],         "d_med": [], "disp_mag": [], "disp_nn_after": [],+        "cap": [], "n_over_a": [], "occ_max": [], "occ_frac_used": [],+        "unfused": [], "uniq_before": [], "uniq_after": [],     }     nn_b_list: list[np.ndarray] = []     nn_a_list: list[np.ndarray] = []@@ -139,11 +204,34 @@ def _blend_within_type(         if idx_a.size < min_count or idx_b.size < min_count:             continue         pa, pb = ca[idx_a], cb[idx_b]-        dist, j = cKDTree(pa[:, sl]).query(pb[:, sl], k=1)-        nn_b_list.append(idx_b)-        nn_a_list.append(idx_a[j])+        n_a_t, n_b_t = idx_a.size, idx_b.size+        if capacity > 0:+            cap = int(capacity)+        elif cap_kappa > 0.0:+            cap = max(1, int(np.ceil(cap_kappa * n_b_t / max(n_a_t, 1))))+        else:+            cap = n_b_t+        if cap >= n_b_t:+            # Mechanism-off path: unconstrained 1-NN (identical to node 19).+            dist, j = cKDTree(pa[:, sl]).query(pb[:, sl], k=1)+            placed = np.ones(n_b_t, dtype=bool)+        else:+            assign, occ_t, _ = _capacity_assign(pa, pb, sl, cap)+            placed = assign >= 0+            j = np.where(placed, assign, 0)+            dist = np.linalg.norm(pa[j][:, sl] - pb[:, sl], axis=1)+            dist = np.where(placed, dist, 0.0)+            stats["cap"].append(cap)+            stats["n_over_a"].append(n_b_t / max(n_a_t, 1))+            stats["occ_max"].append(int(occ_t.max()) if occ_t.size else 0)+            stats["occ_frac_used"].append(float((occ_t > 0).mean()) if occ_t.size else 0.0)+            stats["unfused"].append(int((~placed).sum()))+        sel_b = idx_b[placed]+        nn_b_list.append(sel_b)+        nn_a_list.append(idx_a[j[placed]])         disp_b = np.zeros_like(pb)-        disp_b[:, sl] = alpha * (pa[j][:, sl] - pb[:, sl])+        disp_b[placed] = 0.0+        disp_b[placed, sl] = alpha * (pa[j[placed]][:, sl] - pb[placed][:, sl])         pb_new = pb + disp_b         if mutual:             dist2, j2 = cKDTree(pb[:, sl]).query(pa[:, sl], k=1)@@ -169,11 +257,17 @@ def _blend_within_type(         out_b[idx_b] = pb_new         stats["types_fused"] += 1         stats["cells_fused"] += int(idx_b.size)-        stats["dist_before"].append(float(np.mean(dist)))+        stats["dist_before"].append(float(np.mean(dist[placed])) if placed.any() else 0.0)         stats["disp"].append(float(np.linalg.norm(disp_b, axis=1).mean()))-    for k in ("dist_before", "disp", "d_med", "disp_mag", "disp_nn_after"):+        stats["uniq_before"].append(int(np.unique(np.round(pb[:, sl], 4), axis=0).shape[0]))+        stats["uniq_after"].append(int(np.unique(np.round(pb_new[:, sl], 4), axis=0).shape[0]))+    for k in ("dist_before", "disp", "d_med", "disp_mag", "disp_nn_after",+              "cap", "n_over_a", "occ_max", "occ_frac_used", "uniq_before",+              "uniq_after"):         v = stats[k]         stats[k] = float(np.mean(v)) if v else 0.0+    stats["unfused"] = int(np.sum(stats["unfused"])) if stats["unfused"] else 0+    stats["unfused_frac"] = float(stats["unfused"]) / max(stats["cells_fused"], 1)     stats["nn_b"] = np.concatenate(nn_b_list) if nn_b_list else np.empty(0, dtype=int)     stats["nn_a"] = np.concatenate(nn_a_list) if nn_a_list else np.empty(0, dtype=int)     return out_a, out_b, stats@@ -324,6 +418,12 @@ def main() -> None:     cb = scale_to_rms(aligned_b, target_rms)      blend_alpha = float(os.environ.get("T2HI_BLEND", "1.0"))+    # Capacity-constrained within-type pairing (family T2HI-04 structural fix):+    # each a-side cell may host at most T2HI_CAP b-side cells (0 = off, i.e.+    # the original unconstrained 1-NN greedy of node 19). T2HI_CAP_KAPPA > 0+    # sets a per-type capacity of ceil(kappa * n_b / n_a) instead.+    cap_fixed = int(os.environ.get("T2HI_CAP", "0"))+    cap_kappa = float(os.environ.get("T2HI_CAP_KAPPA", "0.0"))     disp_beta = float(os.environ.get("T2HI_BETA", "0.5"))     # Dispersion default OFF: on the proxy the full beta grid gave no net gain     # (shape_scale flat, local_spatial monotonically worse; see METHOD.md).@@ -337,7 +437,7 @@ def main() -> None:         blend_min = int(os.environ.get("T2HI_BLEND_MIN", "5"))         ca_s, cb_s, blend_info = _blend_within_type(             ca[ia], cb[ib], a.labels[ia], b.labels[ib], common, blend_alpha, blend_min, "3d",-            False, disp_beta, rng_disp,+            False, disp_beta, rng_disp, cap_fixed, cap_kappa,         )         ca = ca.astype(np.float64, copy=True)         cb = cb.astype(np.float64, copy=True)@@ -350,7 +450,7 @@ def main() -> None:         cb_pre = cb.copy()         ca, cb, blend_info = _blend_within_type(             ca, cb, a.labels, b.labels, common, blend_alpha, blend_min, blend_axes, blend_mutual,-            disp_beta, rng_disp,+            disp_beta, rng_disp, cap_fixed, cap_kappa,         )     if blend_info is not None:         blend_min = int(os.environ.get("T2HI_BLEND_MIN", "5"))@@ -505,6 +605,12 @@ def main() -> None:               f"nn_dist_before={blend_info['dist_before']:.1f} "               f"nn_dist_after={blend_info['dist_after']:.1f} "               f"mean_disp={blend_info['disp']:.1f}", flush=True)+        print(f"[cap] fixed={cap_fixed} kappa={cap_kappa:.2f} cap_mean={blend_info['cap']:.2f} "+              f"nb_over_na_mean={blend_info['n_over_a']:.2f} occ_max_mean={blend_info['occ_max']:.1f} "+              f"a_cells_used_frac={blend_info['occ_frac_used']:.3f} "+              f"unfused={blend_info['unfused']} ({blend_info['unfused_frac']:.3f}) "+              f"uniq_pos_before={blend_info['uniq_before']:.1f} "+              f"uniq_pos_after={blend_info['uniq_after']:.1f}", flush=True)         if disp_beta > 0.0:             print(f"[disp] beta={disp_beta:.2f} d_med={blend_info['d_med']:.1f} "                   f"mean_offset={blend_info['disp_mag']:.1f} "

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

用到的知识库条目

编号标题出处
k026Canonicalise predicted 3D coordinates before submissionnotes/pitfalls/04_scorer_invariance.md
k007Interval staging and held-out-window filtering of external datanotes/official/来件/virtualembryo.ai/rules.md
k003Fused Gromov-Wasserstein mapping for spatial snapshots10.1038/s41586-024-08453-2

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

改了什么在 run.py 新增 _capacity_assign(scipy linear_sum_assignment 的容量约束最优指派,超限退回 kNN 两轮贪心),并给 _blend_within_type 加 T2HI_CAP / T2HI_CAP_KAPPA 开关与配对诊断量(unique 坐标、occ_max、未融合数);提交态取 T2HI_CAP=0,即 cap>=n_b 的原 1-NN 路径,输出与节点19逐位一致,故榜分与四组分全部 +0.00(Engineer 报的 61.346/59.785/61.063 是 A 半 proxy 查分,不是榜分,两者不冲突)。
各组分数的变化cell_state:不变 66.87(+0.00);proxy 上 cap=1 −0.08、κ=1 −0.06,均在噪声内
expression_change:不变 67.90(+0.00);提交态即父节点行为,proxy 上开启机制反而变差(cap=1 −2.83、κ=1 −0.63)
local_spatial:不变 58.24(+0.00);proxy 上 κ=1(零未融合、unique 124.6→1167.2)仅 +0.02,在 T2 约 1 分噪声内;cap=1 −3.12
shape_scale:不变 54.15(+0.00);proxy 上 κ=1 −0.45、cap=1 −0.21(occ_dice 升 0.8285→0.8364 但 d2_shape 恶化 0.03545→0.03960)
family_idT2HI-04
假设是否成立否
经验
  1. 在 mix 家族(bracket 插值 + Procrustes + 型内 NN 融合 α=1.0)底座上,型内坐标坍缩不是 local_spatial 的瓶颈:把 unique 坐标从每型 124.6 提到 1167.2 且零未融合后,neighborhood_mmd 只从 0.07001→0.06997、local_spatial +0.02(噪声内)。
  2. 任何削弱型内融合完整度的改动都降分:容量=1 使 63.8% 的 b 细胞退回 Procrustes 位置,local_spatial −3.12、expression_change −2.83,与节点18「α 越小越差」同方向——融合越彻底越好。
  3. 改配对拓扑会连带改 chg_l2 门控选中的细胞集,坐标实验与表达分不正交(cap=1 时 de_score 0.4457→0.3696);若必须改配对,应把表达门控的距离固定在原 1-NN 配对上解耦。
  4. shape_scale 的 d2_shape 与 occupancy_dice 对坐标重分配反应方向相反、scale_log_ratio 恒为 0.4669,它不是单一可优化目标;该组分的瓶颈在 RMS 目标与真值的 log 比,proxy 上由 bracket 内插得到的任何 RMS 都够不到,节点11–21 已反复证实,应停止投入。
  5. 机制被证伪后提交 off 态虽然零风险(逐位=父节点、榜分不变),但也把一次节点额度换成了 0.00 增益;off 对照逐位一致 + proxy 查分筛除是正确做法,代价可接受,前提是 proxy 上至少扫到方向为正的配置才提交开启态。
  6. 容量指派的最优 LAP(n_b×n_a·cap ≤ 6e7)在 cap=3 时耗时 21 s、峰值 <0.75 GB,远低于 28 GB / 30 min 限额,算力不是本任务的约束,不必为省时而退回贪心近似。
mechanism_active否
下一步建议
  1. 针对 local_spatial:沿「更彻底融合」方向扫 mutual 配对的 a 侧位移系数 α_a∈{0.25,0.5,0.75,1.0}(mutual=1 在 proxy 上给出 local 57.94 / nb_mmd 0.06966,是唯一正向信号),并把 b→a 的点配对换成 b 的 k-NN 质心融合(k=3、5),保证零未融合。
  2. 针对 expression_change:在保持原 1-NN 坐标配对不变的前提下只调表达侧(γ、q 门控分位数、或按 chg_l2 排序的软加权混合),避免坐标改动串扰门控选中集。
  3. 针对 shape_scale:不再做输出云二阶形状统计(各向异性缩放、配对重分配、occupancy 微调)类实验;若要动,只能改 RMS 目标的构造(如用 a、b 两端 RMS 之外可从输入估计的量),且需先确认 proxy 上 scale_log_ratio 有响应,否则直接跳过。

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

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

分析员

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

工程师

角色工程师 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数34
工具调用共 34 次:bash 26、edit 7、write 1
用时17 分
token 数输入 73,145 · 输出 11,514 · 思考 13,779
任务(第一行)按计划修改程序:容量约束型内NN配对:消除多对一坐标坍缩,改善local_spatial
最后的回答(摘录)
做了什么:实现 PLAN 的容量约束型内指派(LAP 最优 + `T2HI_CAP` / `T2HI_CAP_KAPPA`),并附带试了 mutual 配对;off 对照(cap=0)与节点 19 逐位一致。

查分(A半,seed 0,额度用 4/20):off 61.346 | cap=1 59.785(local_spatial −3.12,64% b 细胞未融合)| κ=1.0 零未融合、unique 坐标 124.6→1167.2,61.063(local_spatial +0.02 噪声内,shape −0.45、expression −0.63)| mutual=1 61.364(+0.02,噪声)。机制被证伪:坐标坍缩不是 local_spatial 瓶颈,任何削弱型内融合的改动都降分。提交态 = cap=0,vec-check ok,确定性已验。

下一步最值得试:local_spatial 唯一正向信号是"更彻底融合"(mutual 的 a 侧位移系数 α_a、或 b→a 的 k-NN 质心融合);shape_scale 的 d2_shape 与 occupancy_dice 反应方向相反、scale_log_ratio 恒 0.4669,建议判为 mix 家族天花板停止投入。
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/21/engineer.jsonl 207 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/21/engineer.stderr

调研员

角色调研员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数1
工具调用共 0 次:—
用时1 分
token 数输入 13,095 · 输出 973 · 思考 3,614
任务(第一行)为节点 n21(改进,父节点 n19)写改进计划 PLAN.json
最后的回答(摘录)
```json
{
  "name": "容量约束型内NN配对:消除多对一坐标坍缩,改善local_spatial",
  "motivation": "节点19 local_spatial=58.24为第二低组。当前α=1.0的1-NN融合中,多个b细胞可映射到同一a细胞位置,造成坐标重复/局部密度尖峰,破坏邻域连续性。shape_scale=54.15中occupancy_dice≈0.83也受此影响。节点10-19从未改动配对结构本身(只调α、弥散、表达γ),本方案首次将贪心1-NN替换为容量约束指派,属结构性修复而非参数调整。",
  "approach": "在节点19的run.py _blend_within_type函数中,将每型b→a的1-NN贪心替换为容量约束贪心指派:\n1. 对每个共有型,用cKDTree计算b侧每个细胞的k近邻(k=min(n_a, 10))候选a细胞及距离。\n2. 按b细胞到最近a的距离升序排列;依次贪心指派:b_i取其最近的、当前占用数<capacity的a_j;占用满则尝试次近、再次近,直到用完k个候选。\n3. 所有候选均满的b细胞保留Procrustes坐标(不融合),并打印未融合比例。\n4. capacity默认=1,搜索{1,2,3};capacity≥n_b时退化为原始1-NN(off对照)。\n5. 融合后的表达混合(chg_l2门控、γ=2.8、q=0.8)逻辑不变,只改坐标配对。\n6. 单输入阶段退路:t=0时copy_last路径不经过融合,无影响。\n7. vec-score快速筛选:先跑capacity=1 vs off(capacity=999)各一次(2次查分),确认local_spatial方向;再跑capacity=2(第3次);总查分≤5。预期:capacity=1时unique坐标数增加、local_spatial +0.5~1.5。",
  "expected_groups": ["local_spatial", "shape_scale"],
  "risks": "1. 若每型b细胞数≤a细胞数,capacity=1与原始1-NN结果相同,机制无操作空间——Engineer应先打印每型n_b/n_a比值,若多数型n_b≤n_a则提前终止。2. 未融合b细胞留在Procrustes位置可能引入空间不连续,反而降分——若capacity=1降分,尝试capacity=2。3. 30分钟时限:改动集中在_blend_within_type一个函数,用现有cKDTree,代码量小;先打印诊断再查分。",
  "family_id": "T2HI-04",
  "mechanism": "将型内b→a坐标融合从多对一贪心1-NN改为容量约束指派(每个a细胞最多承接capacity个b细胞),消除坐标重复/坍缩,使输出云的局部邻域结构更连续、空间占据更均匀。",
  "vs_constant_shift": "常数位移对同型所有细胞施加相同向量,不改变细胞间相对位置;本机制改变的是配对拓扑(哪个b配哪个a),使原来重叠到同一坐标的多个b细胞分散到不同a位置,是逐细胞异质的坐标重分配。",
  "mechanism_evidence": "Engineer应打印:(1) 每型融合前后unique坐标位置数(融合后应≥融合前,容量约束下不应出现完全重叠);(2) 每型a细胞被指派的b细胞数分布(capacity=1时应全≤1);(3) 未融合b细胞比例;(4) local_spatial和shape_scale四组分各自变化;(5) 与off对照(capacity=999)的坐标差异非零。",
  "mechanism_off_control": "设capacity=999(或n_b),此时每个a细胞可承接所有b细胞,退化为原始1-NN贪心,输出应与节点19逐位一致(np.array_equal验证)。预期差别:off对照与节点19分数相同,开启后local_spatial有≥0.5的变化。",
  "sources": []
}
```
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/21/researcher.jsonl 4 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/21/researcher.stderr

审查员

角色审查员 alibaba-token-plan-cn/qwen3.8-max
调用次数1 次
轮数6
工具调用共 7 次:bash 4、read 2、write 1
用时不到 1 分
token 数输入 25,020 · 输出 1,120 · 思考 1,548
任务(第一行)审查节点 n21 的程序是否越界读取、写死目标、钻评分器漏洞
最后的回答(摘录)
REVIEW.json written
原始记录位置/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/21/reviewer.jsonl 119 KB
/home/spark-longxinyang/vec/runs/formal/20261003-004922-search-t2-heart-interp-g24/nodes/21/reviewer.stderr