File size: 4,227 Bytes
13d6258
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np

# --- Data ---
phases = [
    "Naive ring\narrangement",
    "LP + simulated\nannealing",
    "Multi-start\noptimization",
    "SLSQP joint\noptimization",
    "Iterated\nperturbation",
]
scores = [0.96, 2.50, 2.555, 2.619, 2.63598844]
x = np.arange(len(phases))
SOTA = 2.63598308

# --- Style Config (matching blog CSS variables) ---
color_main = "#4a6fa5"      # --accent
color_sota = "#c0392b"      # warm red
color_text = "#1a1a2e"      # --bold-num
color_secondary = "#555"    # --text-secondary
color_bg = "#fafaf7"        # --bg
color_border = "#e0ddd8"    # --border
color_green = "#1a7f37"     # blog green for breakthrough

plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["font.sans-serif"] = ["Lato", "Helvetica", "Arial"]

# 更紧凑的画布比例
fig, ax = plt.subplots(figsize=(10, 5.5))
fig.patch.set_facecolor(color_bg)
ax.set_facecolor(color_bg)

# 1. Background & Area
ax.fill_between(x, scores, color=color_main, alpha=0.06, zorder=1)
ax.yaxis.set_major_locator(ticker.MultipleLocator(0.5))
ax.grid(axis="y", color=color_border, linestyle="-", linewidth=0.8, alpha=0.6, zorder=0)

# 2. SOTA Reference
ax.axhline(y=SOTA, color=color_sota, linestyle="--", linewidth=1.2, alpha=0.45, zorder=2)
ax.text(-0.35, SOTA + 0.015, f"PREVIOUS SOTA: {SOTA:.8f}",
        fontsize=11, color=color_sota, fontweight="bold", va="bottom")

# 3. The Line
ax.plot(x, scores, color=color_main, linewidth=3.5, zorder=3, alpha=0.85)

# 4. Points & Score Labels
for i, score in enumerate(scores):
    is_breakthrough = score > SOTA
    is_last = (i == len(scores) - 1)

    m_color = color_green if is_breakthrough else color_main
    ax.scatter(x[i], score, color=m_color, s=280, zorder=4, alpha=0.12)
    ax.scatter(x[i], score, color=m_color, s=90, zorder=5, edgecolors=color_bg, linewidths=1.5)

    label = f"{score:.8f}" if is_last else f"{score:.3f}"

    y_offset = 0.06 if is_last else 0.05
    ax.text(x[i], score + y_offset, label, ha="center", va="bottom",
            fontsize=14 if not is_last else 16,
            fontweight="bold", color=m_color, zorder=6)

# 5. Staggered Annotations
box_style_default = dict(boxstyle="round,pad=0.4", fc=color_bg, ec=color_border, alpha=0.95)
box_style_highlight = dict(boxstyle="round,pad=0.4", fc="#dafbe1", ec=color_green, alpha=1)

# 三个注释框都放在曲线下方,y 位置逐渐升高避免重叠
ax.annotate(
    "Agent reads ArXiv paper,\nswitches to LP formulation",
    xy=(x[1], scores[1]), xytext=(x[1], 1.35),
    fontsize=13, color=color_secondary, ha="center",
    arrowprops=dict(arrowstyle="->", color="#999", lw=1.2, connectionstyle="arc3,rad=0.1"),
    bbox=box_style_default, zorder=7
)

ax.annotate(
    "SLSQP breakthrough:\njoint radius + position opt.",
    xy=(x[3], scores[3]), xytext=(x[3], 1.65),
    fontsize=13, color=color_secondary, ha="center",
    arrowprops=dict(arrowstyle="->", color="#999", lw=1.2, connectionstyle="arc3,rad=0.1"),
    bbox=box_style_default, zorder=7
)

ax.annotate(
    "Parallel perturbation\nchains surpass SOTA",
    xy=(x[4], scores[4]), xytext=(x[4], 1.95),
    fontsize=13, color=color_green, ha="center", fontweight="bold",
    arrowprops=dict(arrowstyle="->", color=color_green, lw=1.5, connectionstyle="arc3,rad=0.1"),
    bbox=box_style_highlight, zorder=7
)

# --- Final Layout ---
ax.set_xticks(x)
ax.set_xticklabels(phases, fontsize=13, color=color_secondary, fontweight="medium")
ax.set_ylabel("Score (Sum of Radii)", fontsize=13, color=color_secondary, labelpad=10)

ax.set_title("Circle Packing Score Progression (26 circles in unit square)",
             fontsize=19, fontweight="bold", color=color_text, pad=16)

for spine in ["top", "right", "left"]:
    ax.spines[spine].set_visible(False)
ax.spines["bottom"].set_color(color_border)

# 收紧 Y 轴范围,减少空白
ax.set_ylim(0.75, 2.95)
ax.set_xlim(-0.4, len(phases) - 0.2)

plt.tight_layout()

# Save high-res to publish directory
output_path = "/home/tengxiao/pj/ShinkaEvolve/ccevolve/blog/publish/score_progression.png"
plt.savefig(output_path, dpi=300, bbox_inches="tight", facecolor=color_bg)
print(f"Saved to {output_path}")
plt.show()