File size: 2,828 Bytes
dc9a7f8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
"""Export a publication-ready figure of the measured selected milestones."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

ROOT = Path(__file__).resolve().parents[1]
plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 12,
                     "figure.facecolor": "#0a1523", "axes.facecolor": "#0a1523",
                     "text.color": "#f2f6fa", "axes.labelcolor": "#a9bacc",
                     "xtick.color": "#a9bacc", "ytick.color": "#f2f6fa"})
groups = [
    ("2 m sprint", "Licensed actor → race adaptation", "#69e2ce",
     ["Hannes baseline", "2B / 750", "B3 / 800", "D1 / 900"], [1.192, 1.096, 1.092, 1.084]),
    ("1.5 m hill / 8°", "Reference benchmark → selected policy", "#ffb36b",
     ["Pollen benchmark", "H1b / 500"], [5.880, 1.360]),
    ("2 m passive rollers", "Transfer adaptation → PPO polish", "#9bbcff",
     ["Pollen benchmark", "R1 / 300", "R1 / 400", "R1 / 900", "R2 / 1100"],
     [3.136, 1.864, 1.648, 1.576, 1.516]),
]
fig, axes = plt.subplots(1, 3, figsize=(17, 7), gridspec_kw={"wspace": .46})
fig.suptitle("Selected checkpoints. Exact Arena score.", x=.07, y=.94, ha="left", fontsize=23, fontweight="bold")
fig.text(.07, .875, "Timed finish mean over five seeds · every shown policy finished 5/5 · lower is better",
         color="#a9bacc", fontsize=12)
for ax, (title, subtitle, color, labels, scores) in zip(axes, groups):
    ax.barh(range(len(scores)), scores, color=color, height=.58, alpha=.82)
    ax.invert_yaxis()
    ax.set_yticks(range(len(labels)), labels, fontsize=11)
    ax.set_xlim(0, max(scores) * 1.29)
    ax.set_xlabel("Timed finish / seconds", fontsize=10, labelpad=12)
    ax.set_title(title + "\n" + subtitle, loc="left", fontsize=12, pad=22, color=color)
    ax.xaxis.grid(True, color="#263d4f", linewidth=.7)
    ax.set_axisbelow(True)
    for index, score in enumerate(scores):
        ax.text(score + max(scores) * .025, index, f"{score:.3f} s", va="center",
                fontsize=11, fontweight="bold" if index == len(scores) - 1 else "normal")
    for spine in ax.spines.values():
        spine.set_visible(False)
    ax.tick_params(axis="y", length=0)
fig.subplots_adjust(left=.13, right=.97, top=.72, bottom=.20)
fig.text(.07, .08, "References were benchmarks, not reused weight parents. All trained policies descend from the licensed Hannes actor.",
         color="#a9bacc", fontsize=10)
fig.text(.07, .035, "Snapshot: October 2026. Local best policies and published Arena entries can differ; see models/manifest.json.",
         color="#a9bacc", fontsize=9)
fig.savefig(ROOT / "media/experiment-progress.png", dpi=140, facecolor=fig.get_facecolor())
fig.savefig(ROOT / "media/experiment-progress.svg", facecolor=fig.get_facecolor())
print("Exported PNG and SVG progress figures.")