This commit is contained in:
Horldsence
2026-09-12 16:58:25 +08:00
parent 1fa2264a17
commit 892451dca9
36 changed files with 8767 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
"""统一入口:一次跑完 1-4 问的"最优 vs 基线"对比并生成 results/。
用法(仓库根目录)::
uv run python -m project.run # 四问全部
uv run python -m project.run --question 3 # 只跑第三问
uv run python -m project.run --quick # 缩小算例/基准集规模
"""
from __future__ import annotations
import argparse
import time
from project.common import RESULTS_DIR, markdown_table, write_text
from project.q1 import compare as q1_compare
from project.q2 import compare as q2_compare
from project.q3 import compare as q3_compare
from project.q4 import compare as q4_compare
RUNNERS = {
1: q1_compare.run,
2: q2_compare.run,
3: q3_compare.run,
4: q4_compare.run,
}
STRUCTURE = """\
project/
├── common.py 公共层:方法描述/指标聚合/结果落盘/闭环装配
├── q1/ 问题一:直径与直径圆覆盖
│ ├── optimal.py 生产实现:半平面交 + 顶点对直径 + MEC
│ ├── baseline.py 基线:网格采样 + bbox 对角线代理
│ ├── reference.py 参考:大框半平面裁剪 + 精确直径/MEC
│ ├── cases.py 固定示例(examples/q1)+ 随机交会算例
│ └── compare.py 同案配对对比
├── q2/ 问题二:第二检测点选择
│ ├── optimal.py 生产实现:保证接收盘内最小最坏后验半径
│ ├── baseline.py 基线:垂直 1000 m / MEC 圆心
│ ├── reference.py 参考:保证接收盘内网格枚举
│ ├── region.py K1 统一构造
│ ├── cases.py 随机首次示向度算例
│ └── compare.py
├── q3/ 问题三:全向闭环
│ ├── optimal.py bayes(生产默认策略)
│ ├── baseline.py grid(49 点网格)/ seven(七点批量)
│ └── compare.py
├── q4/ 问题四:混合源闭环
│ ├── optimal.py directional(定向扩展)
│ ├── baseline.py bayes / grid 直接搬用
│ └── compare.py
├── run.py 统一入口(本文件)
└── results/ 自动生成:q1.md/json … q4.md/json + summary.md
"""
def _q1_headline(payload: dict) -> list[str]:
agg = payload["aggregate_random"]
return ["1", "直径平均误差 / 覆盖准确率",
f"{agg['diameter_mae_optimal_m']:.2f} m / "
f"{agg['coverage_accuracy_optimal']*100:.0f}%",
f"{agg['diameter_mae_baseline_m']:.2f} m / "
f"{agg['coverage_accuracy_baseline']*100:.0f}%"]
def _q2_headline(payload: dict) -> list[str]:
agg = payload["aggregate"]
opt = agg["optimal"]
base = agg["baseline_mec"]
return ["2", "保证接收率 / 最坏后验均值",
f"{opt['guaranteed_rate']*100:.0f}% / "
f"{opt['worst_posterior_mean_m']:.1f} m",
f"{base['guaranteed_rate']*100:.0f}% / "
f"{base['worst_posterior_mean_m']:.1f} m"]
def _q3_headline(payload: dict) -> list[str]:
agg = payload["aggregate"]["variants"]
opt, base = agg["optimal"], agg["baseline"]
paired = payload["aggregate"]["paired"].get("optimal_vs_baseline", {})
return ["3", "全清率 / T 均值(相对基线)",
f"{opt['cleared_ratio_mean']*100:.0f}% / "
f"{opt['virtual_time_mean_s']:.0f} s "
f"({paired.get('mean_relative_change', 0)*100:+.0f}%)",
f"{base['cleared_ratio_mean']*100:.0f}% / "
f"{base['virtual_time_mean_s']:.0f} s"]
def _q4_headline(payload: dict) -> list[str]:
agg = payload["aggregate"]["variants"]
opt, base = agg["optimal"], agg["baseline"]
return ["4", "全清率 / 缺席误判(问题三策略搬用)",
f"{opt['cleared_ratio_mean']*100:.0f}% / "
f"{opt['absent_misjudged_total']}",
f"{base['cleared_ratio_mean']*100:.0f}% / "
f"{base['absent_misjudged_total']}"]
def _write_summary(payloads: dict[int, dict]) -> None:
lines = ["# 1-4 问最优 vs 基线:对比总览", "",
"本节所有数字由 `uv run python -m project.run` 在同机同口径下生成,",
"逐问明细见 `q1.md` … `q4.md`。", ""]
rows = []
if 1 in payloads:
rows.append(_q1_headline(payloads[1]))
if 2 in payloads:
rows.append(_q2_headline(payloads[2]))
if 3 in payloads:
rows.append(_q3_headline(payloads[3]))
if 4 in payloads:
rows.append(_q4_headline(payloads[4]))
lines.append(markdown_table(["问", "核心指标", "最优实现", "基线实现"], rows))
lines += ["", "## 方法映射", "",
"| 问 | 最优实现 | 基线实现 | 独立参考 |",
"| --- | --- | --- | --- |",
"| 1 | 半平面交 + 顶点对直径 + MEC | 网格采样 + bbox 对角线代理 | 大框半平面裁剪 + 精确直径/MEC |",
"| 2 | 保证接收盘内最小最坏后验半径 | 垂直 1000 m / MEC 圆心 | 保证接收盘内网格枚举 |",
"| 3 | bayes(粒子滤波 + 信息增益 + 滚动调度) | grid(49 点网格)/ seven(七点批量) | 冻结基准集 + 逐微秒计时复算 |",
"| 4 | directional(联合信念 + 后备清除) | bayes / grid 直接搬用 | 冻结基准集 + 真值全清校验 |",
"", "## 目录结构", "", "```text", STRUCTURE.rstrip(), "```", ""]
write_text(RESULTS_DIR / "summary.md", "\n".join(lines))
def main(argv=None) -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("--question", choices=("1", "2", "3", "4", "all"),
default="all")
parser.add_argument("--quick", action="store_true",
help="缩小随机算例数/冻结基准集规模")
args = parser.parse_args(argv)
selected = [1, 2, 3, 4] if args.question == "all" else [int(args.question)]
payloads: dict[int, dict] = {}
for question in selected:
start = time.perf_counter()
print(f"[Q{question}] 运行对比 …", flush=True)
payloads[question] = RUNNERS[question](quick=args.quick)
print(f"[Q{question}] 完成,用时 {time.perf_counter() - start:.1f}s",
flush=True)
if selected == [1, 2, 3, 4]:
_write_summary(payloads)
print(f"总览已写入 {RESULTS_DIR / 'summary.md'}")
print(f"结果目录:{RESULTS_DIR}")
return 0
if __name__ == "__main__":
raise SystemExit(main())