yes fuking shit

This commit is contained in:
Horldsence
2026-09-12 14:48:43 +08:00
parent 61fd22598a
commit 45e48d4c91
64 changed files with 11540 additions and 57 deletions
+3 -2
View File
@@ -11,8 +11,9 @@
from .playback import PlaybackTransport
from .scenes import mixed_scene, random_omni_scene, referee_spec
from .simulator import LocalSimulator
from .suites import SceneSpec, suite, suite_manifest
from .transport import LocalSimTransport, ScriptedFaultTransport
__all__ = ["LocalSimTransport", "LocalSimulator", "PlaybackTransport",
"ScriptedFaultTransport", "mixed_scene", "random_omni_scene",
"referee_spec"]
"ScriptedFaultTransport", "SceneSpec", "mixed_scene",
"random_omni_scene", "referee_spec", "suite", "suite_manifest"]
+132
View File
@@ -0,0 +1,132 @@
"""冻结基准集:第三/四问的固定场景清单与真值构造(测试端专用)。
存在意义(docs/第三四问架构优化与运行提速方案.md §1.4 B6 / §P1-3):
历史评估集是 20 个**单源全向**场景,使 `avg_locate_clear_time_s` 恒等于
`virtual_time_s`,也无法支撑任何第四问结论。基准集必须覆盖题面声明的
源数区间与定向源存在性,并且**版本化、可复现、不可随意增删**——
任何"更快"的声明都要在同一份清单上做配对比较。
真值只在本模块与评测机之间流动;策略端只通过 Transport 看到响应。
"""
from __future__ import annotations
import math
from dataclasses import dataclass
from referee import Source
from ..config import ProblemConfig
from .scenes import mixed_scene, random_omni_scene
SUITE_VERSION = 1
# 第三问:沿用历史验证集的种子与源数(seeds 100–105 × 10/13/16)
Q3_SEEDS = (100, 101, 102, 103, 104, 105)
Q3_COUNTS = (10, 13, 16)
# 第四问:三种"定向占比"组成(少量 / 约半数 / 多数)
Q4_SEEDS = (200, 201, 202)
Q4_CONFIGS = ((10, 3), (13, 6), (16, 8))
# 误差场种子偏移:与 benchmark_q3_bayes.py 同口径,保证逐点固定误差可复现
ERROR_SEED_BASE = 20260910
@dataclass(frozen=True)
class SceneSpec:
"""一个冻结场景:标识、题号、源数、定向数与种子。"""
scene_id: str
problem: int
kind: str # "random" | "boundary"
seed: int
error_seed: int
count: int
directional: int = 0
def as_dict(self) -> dict:
return {"scene_id": self.scene_id, "problem": self.problem,
"kind": self.kind, "seed": self.seed,
"error_seed": self.error_seed, "count": self.count,
"directional": self.directional}
def sources(self, config: ProblemConfig | None = None) -> list[Source]:
"""构造真值(仅测试端调用)。"""
config = config or ProblemConfig()
if self.kind == "random" and self.problem == 3:
return random_omni_scene(seed=self.seed, count=self.count,
config=config)
if self.kind == "random":
return mixed_scene(seed=self.seed, count=self.count,
directional=self.directional, config=config)
return _boundary_sources(self, config)
def _boundary_sources(spec: SceneSpec, config: ProblemConfig) -> list[Source]:
"""圆周边界压力场景:源全部位于 Ω 边界、r_eff 取下界。
第三问:全向,扇区接缝角度,检验七站覆盖的边界情形;
第四问:全部定向且朝向**背离圆心**(最不利于发现),检验
"朝外发射的边界源不漏"。
"""
field = config.field
radius = field.omega_radius_m
sources: list[Source] = []
for index in range(spec.count):
angle = math.pi / 6 + 2 * math.pi * index / spec.count
x, y = radius * math.cos(angle), radius * math.sin(angle)
directional = index < spec.directional
sources.append(Source(
channel=index + 1, x=x, y=y, r_eff_m=field.r_eff_min_m,
directional=directional,
heading_deg=(math.degrees(angle) % 360.0) if directional else 0.0))
return sources
def core_scenes(problem: int) -> list[SceneSpec]:
"""主体场景:覆盖题面源数区间与定向占比组成。"""
scenes: list[SceneSpec] = []
if problem == 3:
for seed in Q3_SEEDS:
for count in Q3_COUNTS:
scenes.append(SceneSpec(
scene_id=f"q3-core-s{seed}-n{count}", problem=3,
kind="random", seed=seed, error_seed=ERROR_SEED_BASE + seed,
count=count))
else:
for seed in Q4_SEEDS:
for count, directional in Q4_CONFIGS:
scenes.append(SceneSpec(
scene_id=f"q4-core-s{seed}-n{count}-d{directional}",
problem=4, kind="random", seed=seed,
error_seed=ERROR_SEED_BASE + seed, count=count,
directional=directional))
return scenes
def boundary_scenes(problem: int) -> list[SceneSpec]:
"""圆周边界压力场景(每问 2 场:10 源与 16 源)。"""
if problem == 3:
return [SceneSpec(f"q3-boundary-n{count}", 3, "boundary", 0,
ERROR_SEED_BASE, count)
for count in (10, 16)]
return [SceneSpec(f"q4-boundary-n{count}-d{directional}", 4, "boundary", 0,
ERROR_SEED_BASE, count, directional)
for count, directional in ((10, 5), (16, 8))]
def suite(name: str, problem: int) -> list[SceneSpec]:
"""按名称取场景清单:core / boundary / all。"""
if name == "core":
return core_scenes(problem)
if name == "boundary":
return boundary_scenes(problem)
if name == "all":
return core_scenes(problem) + boundary_scenes(problem)
raise ValueError(f"未知基准集 {name!r}(可选 core/boundary/all)")
def suite_manifest(name: str, problem: int) -> dict:
"""清单头:版本、问题、场景表(写入 manifest.json)。"""
scenes = suite(name, problem)
return {"suite_version": SUITE_VERSION, "suite": name, "problem": problem,
"scenes": [scene.as_dict() for scene in scenes]}