fullseye

記事への反映待ち(2026-09-02、可視化ウィング作業から)

展示を作らせたら op のバグが次々出たので、記事に載っている主張と数字のうち 事実が変わったもの / 再現しないものをここに集約する。すべて実測で確認済み。 反映が終わった行は消さずに「済」を付ける(何を直したかが記録として要る)。

A. 記事の数字が再現しない(最優先)

A-1. 進化の結果表 4 行が現行コードで再現しない

docs/articles/fullseye_overview_qiita_{ja,en}.md の「locked holdout」の表。

課題 記事 恒等 / 手 いま測ると 恒等 / 手
photon_denoise 0.2664 / 0.5371 0.4174 / 0.5536
vibration_map 0.0000 / 0.6973 0.0000 / 0.7163
lf_slope 0.0000 / 0.5794 0.0000 / 0.5219
specular_removal 0.4115 / 0.8406 0.4905 / 0.8343

恒等写像(op を 1 つも適用しない)の値まで動いているので、原因は op でなく データ生成か採点の側。n 7 通り × size 6 通り × seed 3 通りを総当たりしても 0.2664 を出す組合せは存在しない

根本原因の証拠: out/rb_*/robust_*.jsonbaseline_hand = None / baseline_trivial = None / baseline_hand_locked = None基準線が成果物に記録されていない。 つまり記事の恒等・手の数字は保存された成果物から読んだものではなく、 その場で別に計算したもの。だから後から突き合わせられない。 記録された locked_holdout_spread.max = 0.7845 は記事の進化値 0.7760 とも違う。

やること: op の修正が落ち着いてから、基準線ごと記録する形で 4 課題を 測り直し、ja/en の表と docs/EVOLUTION_ENVIRONMENT.md を書き換える。 記事には再現コマンドを併記する。robust.py の実行は work-graph に積む。

A-2. 4.3e-16 は生の値ではない

記事(ja/en とも 1688 行付近)の「生スペクトルの同じ周波数は 4.3e-16」は dsp.spectrum(...)[1] * 2/N の値。生の値は 5.493328e-12 (搬送波 12800 / 側帯波 3200)。主張(欠陥周波数は生スペクトルに存在しない)は 比なので生きているが、書いてある呼び出しでは再現しない。 dsp.spectrum は呼び出し元が全件すでに ×2/N していたため実装は変えず、 規約を厳密に文書化する判断になった。→ 記事も × 2/N を明記して直す。

B. 記事の主張そのものが変わった

B-1. 「鏡面分離の破綻点は k=4」(ja/en とも 2109 行付近)

修正前: 8 灯のうち 4 灯が遮蔽されると素の最小二乗が崩れ、median も ransac も 雑音床に落ちる ―― と書いた。 判明したこと: 推定器が真っ黒に潰れた灯を inlier として信じていたのが原因で、 しかも一番外している k=4 で「8/8 全部正常」と報告していた。 根本は Woodham モデル I = a·max(n·L,0) で、測定値 0 は不等式 n·L≤0 なのに 線形解法が等式として読むこと。g=0 は潰れた全フレームを厳密に再現するので、 遮蔽灯の集合が無矛盾な仮説として真を上回れる。 修正後の実測: k=4 は両手法とも 70.52° → 0.000115°、 k=6(生きた灯 2 本 = 未知数 3・式 2)は全画素 NaN(答えず「解けない」と言う)。 本物の破綻点は正の外れ値(ハイライト汚染)で、+3.0 を 4/8 灯に足すと ransac 65.4164° / median 7.4190°(1–3 灯は 0.0001°)。 → 記事は「遮蔽が破綻点」から「遮蔽は解けるようになった。破綻するのは ハイライト汚染で、しかも診断が一番外している所で異常なしと言っていた」へ書き換える。

B-2. 周辺光量落ちの節(未執筆だが書く価値がある)

image_formation の cos⁴ が画角でなく配列の角で決まっていた(どんな系でも 角が 45° 扱い = 0.2500 固定)。修正後は全画面の角 0.967176 が system_feasibility の 0.9671480 と一致。既存テストが正しい理由で通って いなかった副産物つき(「ぼけると勾配の総量が減る」を通していたのは、 バグのある周辺光量落ちが画像を暗くしていたから。実測 16.000000000000032 対 16.0)。

C. 展示・生成物の追随

D. 未修正のまま残っている op 側の課題

D-1. 「推奨パラメータを兄弟 op が拒否する」の残り 5 件

全 307 モジュールを走査し producer op 16 個・54 連鎖を実行して確定した 6 件のうち、 ⑤(octave_bands → 44100 Hz で Nyquist 超え)は修正済み。残り:

# 連鎖 症状
csi_design(step_divisor=4.0)csi_height_map 他 3 op 最小の合法 divisor が recommended_z_step_um == max_z_step_um を生み消費側の >= が拒否。docstring は実装されていない挙動を記述
csi_design["n_planes"]csi_stack_simulate stack_within_cap が要素数上限だけ見て平面数上限を見ていない
lf_plenoptic_designlf_synthesize/lf_aperture_mask design 側にプレノプティック配列の上限が無い
lf_stats["max_slope_px"]lf_refocus 「正直な限界」と称する値が消費側の MAX_ABS_SLOPE=1024 を超える
sinogram_design(size=8192)ellipse_phantom design は 16384 まで許すが消費側の実上限は 4096

D-2. 昇格ゲートの 0 割り

promote_gate.counterfactual_utilitydenom = abs(best_existing) + 1e-12。 基準線 0 の課題で rel +724476067514.28 と跳ね、判定 PROMOTE。無言の誤昇格。

D-3. 連鎖ファザーが同一プロセス内の実行順に依存

まっさらなプロセス → 到達 445/515・発見 174。同じプロセスで evolve.run を 20 回回した後 → 433/515・発見 220(seed も引数も同一)。 「小さい入力から巨大な内部割当」の家系が空きメモリで成功したり例外になったりする。 測定は子プロセスに切り出すべき

D-4. archived champion が再生できない

out/loop_points_denoise/champion_points_denoise.json は記録 locked=0.1786 が いま再採点すると 0.1633out/big_points_denoise/...ops.decode_by_namesKeyError: 'tb_log_zero_crossings'(レジストリから消えた)。 name-pinned 記録の前提が崩れている。

D-5. ops.py::_vol_mip の docstring

表示用に [0,1] 正規化して返すので比率の分母に使えない(同梱の骨格 CT で 完全な投影が 122.6 % になる)。volops.py / volio.py には注記済みだが、 ops.py 本体は担当外だったため未記載。opscadmap.py:17-18 の 「render3d は画素中心が半整数」ももう逆(画素中心の統一で修正済み)。

F. 目視で見つかったもの(機械検査は 1 件も検出しなかった)

tools/check_exhibit_assets.py が「公開不可 0 / 要確認 0」を返した状態で、 人が全コマ見たら 6 件の不具合が出た(2D ウィング)。この非対称は記録に値する。

tools/exhibit_tile.py 側を直した: ラベルは折り返さず縮小して収める、 入り切らなければ黙って切らずに例外。表題は改行を含んでも落ちない。 それでも「真っ黒なパネル」や「色数落ち」は機械には見えないので、目視は外せない

判断待ち: 赤緑の使い分けが揃っていない

wing3d_anisotropic_voxel赤枠 = 誤り / 緑枠 = 正しいで描いている。一方 wingct は「赤緑インジケータ不使用(青-黒-橙の発散マップ)」を明示して作られた。 imgevolve 側に禁止規約は無い(raptor の CLAUDE.md にある規約で、出自が違う)ので 違反ではないが、ウィング間で流儀が割れている。当該図は色だけでなく 「spacing あり / なし」の文字も併記しているので色覚の面では致命的ではない。 揃えるなら青-橙へ寄せるのが安全側。

G. 残っている生成物の追随

E. 反映の順番

  1. 走行中の op 修正が全部終わるのを待つ(数字が動くため)
  2. robust.py で 4 課題を基準線ごと記録して測り直す(work-graph に積む)
  3. A / B を ja / en 両方に反映
  4. C の生成物を再生成し、tools/build_exhibits.py で章を組み直す
  5. tools/check_exhibit_assets.py --strict と目視
  6. フルスイート → commit → push と Qiita PATCH の可否をユーザーに確認