This commit is contained in:
Horldsence
2026-09-13 11:45:01 +08:00
parent fb0325f67f
commit 257d1a9bd7
54 changed files with 11152 additions and 6772 deletions
+13 -51
View File
@@ -1,10 +1,11 @@
"""Build vector figure sources, comparison tables, source listings, and a support ZIP.
"""Build vector figure sources, comparison tables, the formal-data table, and a support ZIP.
Formal figures use the audited snapshot only. Geometric figures use declared
algorithm parameters, not fabricated observations or hidden simulator data.
The paired optimal-versus-baseline tables are generated from project/results/*.json
so that no number in the comparison section is hand copied.
The generated table rows are f-strings whose value equals the LaTeX line to be
written; wrapping them would obscure that one-to-one correspondence, so this module
is exempt from the line-length check (the only pylint exception in scripts/).
"""
# pylint: disable=line-too-long
from __future__ import annotations
import argparse
@@ -18,29 +19,6 @@ ROOT = Path(__file__).resolve().parents[1]
PAPER = ROOT / "docs/paper"
PROJECT_RESULTS = ROOT / "project/results"
# Display copies only: executable Python files remain byte-for-byte unchanged.
ESCAPE_OPEN = "(" + "*@"
ESCAPE_CLOSE = "@*" + ")"
LATEX_SYMBOLS = {
"\u03b1": r"\alpha", "\u03b4": r"\delta", "\u03b8": r"\theta",
"\u03bb": r"\lambda", "\u03c0": r"\pi", "\u03c1": r"\rho",
"\u03c6": r"\varphi", "\u2308": r"\lceil", "\u2309": r"\rceil",
"\u2200": r"\forall", "\u2203": r"\exists", "\u2205": r"\varnothing",
"\u2208": r"\in", "\u2227": r"\wedge", "\u2229": r"\cap",
"\u222a": r"\cup", "\u2248": r"\approx", "\u2264": r"\le",
"\u2265": r"\ge", "\u2286": r"\subseteq", "\u2287": r"\supseteq",
"\u27f9": r"\Longrightarrow",
}
def escaped_listing(source: str) -> str:
if ESCAPE_OPEN in source or ESCAPE_CLOSE in source:
raise ValueError("Source collides with the LaTeX escape delimiters")
return "".join(
ESCAPE_OPEN + r"\ensuremath{" + LATEX_SYMBOLS[c] + "}" + ESCAPE_CLOSE
if c in LATEX_SYMBOLS else c for c in source
)
def digest(data: bytes) -> str:
return hashlib.sha256(data).hexdigest()
@@ -49,7 +27,6 @@ def digest(data: bytes) -> str:
def figures(rows: list[dict]) -> None:
out = PAPER / "figures"
out.mkdir(parents=True, exist_ok=True)
<<<<<<< HEAD
plan = json.loads((ROOT / "src/mcm26b/guarantee/plans/q4_mincover_v2.json").read_text("utf-8"))
lines = [
r"\begin{figure}[htbp]\centering",
@@ -72,8 +49,6 @@ def figures(rows: list[dict]) -> None:
r"\label{fig:q4plan}\end{figure}",
]
(out / "q4-plan.tex").write_text("\n".join(lines) + "\n", "utf-8")
=======
>>>>>>> 78e4420a3e496c43db8e06556e539fd7d2aaf231
colors = ["inkblue", "inkblue!50", "warmgray!70", "black!18"]
bars = [
r"\begin{figure}[htbp]\centering",
@@ -266,27 +241,12 @@ def project_tables() -> None:
def listings(rows: list[dict]) -> None:
"""生成正式数据清单;核心函数源码清单由 build_code_appendix.py 单独生成。
论文附录只收录四问主线的核心函数(数据源为单文件核心代码 ipynb),
评测机、命令行外壳、采集/绘图脚本、测试与未采用方案不再逐字排版。
"""
data = PAPER / "data"
files = sorted((ROOT / "src/mcm26b").rglob("*.py"))
files += [ROOT / "scripts/audit_paper_formal.py",
ROOT / "scripts/build_paper_support.py"]
text = [
r"\begingroup",
r"\linespread{1.0}\selectfont",
r"\lstset{basicstyle=\ttfamily\fontsize{8}{10}\selectfont,numberstyle=\tiny,"
r"aboveskip=6pt,belowskip=8pt,xleftmargin=1.5em,frame=none}",
]
for path in files:
rel = path.relative_to(ROOT).as_posix()
display = data / "listing-source" / (rel + ".tex")
display.parent.mkdir(parents=True, exist_ok=True)
display.write_text(escaped_listing(path.read_text("utf-8")), "utf-8")
display_rel = display.relative_to(PAPER).as_posix()
escape_option = "escapeinside={" + ESCAPE_OPEN + "}{" + ESCAPE_CLOSE + "}"
text += [fr"\subsection*{{\pathtext{{{rel}}}}}",
fr"\lstinputlisting[{escape_option}]{{{display_rel}}}"]
text.append(r"\endgroup")
(data / "source-listings.tex").write_text("\n".join(text) + "\n", "utf-8")
table = [
r"\begin{longtable}{p{1.15cm}p{13.3cm}}",
r"\caption{所选正式导出文件与完整包哈希}\label{tab:packages}\\",
@@ -356,7 +316,9 @@ def package(rows: list[dict]) -> Path:
if path.is_file() and "__pycache__" not in path.parts)
selected.update([PAPER / "main.tex", PAPER / "mcm26b-paper.cls",
PAPER / "README.md", PAPER / "REWRITE_NOTES.md",
ROOT / "mcm26b-核心代码.ipynb",
ROOT / "scripts/audit_paper_formal.py",
ROOT / "scripts/build_code_appendix.py",
ROOT / "scripts/build_paper_support.py"])
for row in rows:
path = ROOT / "Jammers-simulator-full" / row["file"]