yes fuking shit
This commit is contained in:
@@ -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"]
|
||||
|
||||
@@ -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]}
|
||||
Reference in New Issue
Block a user