{
  "id": 693784,
  "title": "Inference-Time Engineering for IMO-Level Mathematical Reasoning",
  "content": "<p><strong>Author:</strong> Lê Bảo<br>\n<strong>Competition:</strong> AI Mathematical Olympiad — Progress Prize 3 (AIMO3)<br>\n<strong>Notebook versions:</strong> 7 experimental configurations, 5 leaderboard submissions  </p>\n<hr>\n<h2>Reproducibility</h2>\n<table>\n<thead>\n<tr>\n<th>Resource</th>\n<th>Link</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Kaggle Notebook (submitted)</strong></td>\n<td><a href=\"https://www.kaggle.com/code/heon29/aimoooooooooooooooooo?scriptVersionId=310606235\" target=\"_blank\">notebook</a></td>\n</tr>\n<tr>\n<td><strong>Colab Notebook (simplified)</strong></td>\n<td><a href=\"&lt;code&gt;https://colab.research.google.com/drive/1ih71S7eRTzDqC5RjY-FMGbBoxoubpRMz?usp=sharing&lt;/code&gt;\" target=\"_blank\">colab</a></td>\n</tr>\n<tr>\n<td><strong>Base Model</strong></td>\n<td><a href=\"https://huggingface.co/openai/gpt-oss-120b\" target=\"_blank\">gpt-oss-120b</a></td>\n</tr>\n</tbody>\n</table>\n<p>The submitted Kaggle notebook is open-sourced and publicly viewable. A simplified Colab version is provided as supplementary material for readers without Kaggle access — it implements the same inference pipeline using the public HuggingFace model weights. No fine-tuning was performed; the contribution is purely an inference pipeline on top of the public base model.</p>\n<hr>\n<h2>Abstract</h2>\n<p>We report an inference-time engineering study for AIMO3, conducted under severe time pressure — joining with 7 days remaining and a 5-submission budget. Using <code>danielhanchen/gpt-oss-120b</code> (116.8B total / ~5.1B active parameters via Mixture-of-Experts) served through vLLM 0.11.2 with FP8 quantization, our best submission achieves <strong>44/50</strong> on the public leaderboard; two identical resubmissions of the same notebook scored 35 and 35, indicating substantial run-to-run variance. Our system runs N=8 parallel tool-integrated reasoning attempts aggregated by entropy-weighted majority voting with early stopping.</p>\n<p>Across 7 notebook versions we test four dimensions of variation: (1) system prompt style — a verbose 5-stage IMO scaffold vs. a 3-line concise prompt; (2) sampling parameters — temperature (0.8 vs. 1.0) and top_p (absent vs. 0.8); (3) voting strategy — entropy-weighted majority vs. ensemble convergence; (4) attempt count — 8 vs. 12 vs. 20. Key findings: the verbose structured prompt outperforms the concise prompt; ensemble convergence voting catastrophically degrades performance (2/10 vs. 9/10 on the reference set); temperature reduction from 1.0 to 0.8 combined with more attempts degrades public LB from 44 to 39; top_p=0.8 has no measurable effect; a missing function definition caused 0/10 scores on two notebook versions before being diagnosed and fixed.</p>\n<p>We also document EOS-resilient retry logic — handling transient vLLM connection failures that affected 6 of 10 reference problems across both runs. Per-problem analysis across two independent reference-set runs reveals a critical finding: <strong>token-level entropy does not predict answer convergence</strong>. The n-Norwegian problem has lower mean token entropy (0.701) than the Tournament problem (0.863), yet Norwegian produces 6 completely distinct answers across 8 attempts while Tournament converges unanimously in 5. This reveals that a model can be locally confident at each reasoning step while globally taking a different wrong path each attempt — a failure mode invisible to entropy-based voting. The n-Norwegian problem also consumes 43× more compute than the average problem, with variance concentrated entirely in this single problem across both reference runs.</p>\n<hr>\n<h2>1. Introduction</h2>\n<h3>1.1 Competition Setting</h3>\n<p>AIMO3 requires solving 50 International Mathematical Olympiad-level problems on a single NVIDIA H100 80GB GPU within a 5-hour wall-clock budget. Problems span algebra, combinatorics, geometry, and number theory. All answers are non-negative integers in [0, 99999], evaluated by exact match. The competition provides a 10-problem reference set (<code>reference.csv</code>) for local development; the remaining 40 problems constitute the private test set.</p>\n<p>The primary constraint is not model quality but compute allocation: with 50 problems and a 17,400-second (4h50m) notebook limit, each problem receives at most 348 seconds on average, far less than the 900-second maximum. Effective adaptive time budgeting is therefore a first-order engineering concern alongside model configuration.</p>\n<p>AIMO3 represents a significant escalation over its predecessors. The AIMO2 winning solution (NemoSkills, Moshkov et al. [4]) achieved 34/50 using a fine-tuned 14B model on 4×L4 GPUs with 540K training problems and custom GenSelect inference. AIMO3 provides H100 hardware, enabling gpt-oss-120b inference without fine-tuning — shifting the landscape from training-time compute to inference-time engineering.</p>\n<h3>1.2 Participation Context</h3>\n<p>We joined AIMO3 with 7 days remaining before the April 15 deadline. This severely limited the number of controlled experiments we could run — 5 leaderboard submissions over 7 days, with local reference-set evaluation as the primary development signal. Our approach was targeted engineering based on hypotheses rather than broad search.</p>\n<p>This context affects how we interpret results: several ablations are confounded (multiple variables changed simultaneously), single-run comparisons have high variance, and we lack the noise floor characterization that would come from repeated identical submissions. We document these limitations explicitly throughout.</p>\n<h3>1.3 Contributions</h3>\n<ol>\n<li><strong>Complete ablation study</strong> across 8 notebook versions with exact public LB and local reference scores.</li>\n<li><strong>EOS-resilient retry logic</strong> — the only documented implementation of exponential-backoff retry for transient vLLM connection failures in this competition, with per-problem evidence of recovery.</li>\n<li><strong>Token entropy ≠ answer convergence</strong> — empirical finding that locally confident models can globally diverge: Norwegian (entropy 0.701) fails completely while Tournament (entropy 0.863) converges unanimously, showing entropy voting cannot detect \"confident divergence.\"</li>\n<li><strong>Cross-run stability analysis</strong> — 9 of 10 reference problems produce identical answers across two independent runs with different problem orderings.</li>\n<li><strong>Per-problem compute analysis</strong> — n-Norwegian consumes 43× more tokens than the average problem, revealing that hard problems are identifiable by compute signature, not just answer entropy.</li>\n<li><strong>Negative results documentation</strong> — entropy convergence voting (−7 problems), more attempts under fixed budget (−5 to −11 problems), and missing function bugs (0/10).</li>\n</ol>\n<hr>\n<h2>2. System Architecture</h2>\n<p><strong>Why this architecture matters:</strong> AIMO3 presents a unique constraint: 50 problems, 5 hours, single GPU. The solution is not about finding the best model, but about efficiently allocating limited compute across problems. Our architecture prioritizes (1) making hard problems get enough time, (2) not wasting time on easy problems that converge quickly, and (3) handling infrastructure failures gracefully.</p>\n<h3>2.1 Model and vLLM Configuration</h3>\n<p>We serve <code>danielhanchen/gpt-oss-120b</code> through a local vLLM 0.11.2 server using the proprietary <code>openai_harmony</code> protocol. Model weights (~65 GB in FP8) are pre-loaded into OS page cache via parallel sequential reads before server launch, reducing cold-start latency from ~240s to ~116s.</p>\n<table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Value</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Model</td>\n<td>danielhanchen/gpt-oss-120b</td>\n<td></td>\n</tr>\n<tr>\n<td>Total / active params</td>\n<td>116.8B / ~5.1B</td>\n<td>Mixture-of-Experts</td>\n</tr>\n<tr>\n<td>Weight format</td>\n<td>FP8 (MXFP4 E2M1)</td>\n<td></td>\n</tr>\n<tr>\n<td>KV cache</td>\n<td>fp8_e4m3</td>\n<td></td>\n</tr>\n<tr>\n<td>Engine</td>\n<td>vLLM 0.11.2</td>\n<td></td>\n</tr>\n<tr>\n<td>Tensor parallel</td>\n<td>1</td>\n<td>Single H100</td>\n</tr>\n<tr>\n<td>batch_size (max_num_seqs)</td>\n<td>128</td>\n<td>Baseline config</td>\n</tr>\n<tr>\n<td>gpu_memory_utilization</td>\n<td>0.95</td>\n<td></td>\n</tr>\n<tr>\n<td>context_tokens (max_model_len)</td>\n<td>65,536</td>\n<td></td>\n</tr>\n<tr>\n<td>stream_interval</td>\n<td>200</td>\n<td></td>\n</tr>\n<tr>\n<td>Key flags</td>\n<td><code>--async-scheduling</code> <code>--enable-prefix-caching</code> <code>--trust-remote-code</code></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>The server is started as a subprocess and polled until <code>/v1/models</code> responds (180-second timeout). All server output is written to <code>vllm_server.log</code> for debugging.</p>\n<h3>2.2 Inference Pipeline — Five Stages</h3>\n<p><strong>Why five stages:</strong> We decomposed the inference problem into a pipeline because each stage has different resource requirements and failure modes. Adaptive budget allocation needs to know the problem sequence; parallel attempts need independent seeds; early stopping needs to track answer consensus; entropy voting needs per-attempt confidence scores.</p>\n<p><strong>Stage 1 — Adaptive budget allocation.</strong> Per-problem time budget:</p>\n<pre><code>reserved = max(0, problems_remaining - 1) * base_problem_timeout  # 300s each\nbudget = max(base_timeout, min(high_timeout, notebook_limit - elapsed - reserved))\n</code></pre>\n<p>With <code>base_timeout=300s</code>, <code>high_timeout=900s</code>, <code>notebook_limit=17400s</code>: early problems receive up to 900s when time is abundant; later problems compress toward 300s as the notebook limit approaches. This avoids both under-serving hard early problems and running out of time for late problems.</p>\n<p><strong>Stage 2 — Parallel attempts.</strong> N=8 inference threads dispatched concurrently, each with a distinct seed computed as <code>attempt_seed = int((seed + i)²) mod 2³¹</code> for i ∈ [0, 7]. Temperature T=1.0 with <code>min_p=0.02</code> — the minimum token probability threshold that prevents very low-probability tokens from being sampled.</p>\n<p><strong>Stage 3 — Tool-integrated reasoning.</strong> Each attempt operates within an <code>openai_harmony</code> Harmony conversation loop, implementing Tool-Integrated Reasoning (TIR) [3]. <code>AIMO3Template</code> constructs a <code>SystemContent</code> with <code>ReasoningEffort.HIGH</code>, attaching the tool namespace for the Python sandbox. The model alternates among three channels:</p>\n<ul>\n<li><code>assistant</code>: reasoning and code generation</li>\n<li><code>python</code> (tool): code execution, result returned to conversation  </li>\n<li><code>final</code>: terminal channel where the answer is emitted</li>\n</ul>\n<p><strong>Stage 4 — Early stopping.</strong> A shared <code>threading.Event</code> is set as soon as 4 attempts agree on the same answer. Remaining futures are cancelled. This saves substantial compute on problems where the model converges quickly — in our reference runs, 8 of 9 correctly-solved problems reached early stop within 4–5 attempts, conserving approximately 3–4 attempt-slots of compute each.</p>\n<p><strong>Stage 5 — Entropy-weighted voting.</strong> Each attempt's answer is weighted by inverse mean token-level Shannon entropy:</p>\n<p>$$\\hat{a} = \\arg\\max_a \\sum_{i: ans_i = a} \\frac{1}{\\max(H_i, \\epsilon)}$$</p>\n<p>where $H_i$ is the mean entropy computed from top-5 logprobs:</p>\n<p>$$H_i = \\frac{1}{|T_i|} \\sum_{t \\in T_i} \\left(-\\sum_k p_{t,k} \\log_2 p_{t,k}\\right)$$</p>\n<p>Lower entropy = higher confidence = higher vote weight.</p>\n<p><strong>Why entropy weighting:</strong> Standard majority voting treats all attempts equally. But when the model generates a confident response (low entropy), it should carry more weight than a hesitant response (high entropy). This is especially important when some attempts take a \"shortcut\" to a wrong answer — those tend to have higher entropy because the model is less certain.</p>\n<h3>2.3 Persistent Jupyter Kernel Pool</h3>\n<p><strong>Why persistent kernels:</strong> Tool-integrated reasoning requires stateful execution — the model needs to define variables in one code cell and use them in the next. Standard Python subprocess execution loses state between calls. Persistent kernels solve this by maintaining a running Python interpreter.</p>\n<p>We maintain 8 persistent Jupyter kernels, one allocated per parallel attempt. Kernels are initialized at notebook startup (parallel, ~2 seconds total) with:</p>\n<pre><code>import math, numpy, sympy, itertools, collections, mpmath\nmpmath.mp.dps = 64   # 64 decimal places of precision\n</code></pre>\n<p>Kernel ports are allocated dynamically from 50000+ using a class-level lock for thread safety. State persists across code cells within a single attempt — variables from earlier executions survive into later ones, mimicking a real Jupyter session. Between problems, kernels are reset via <code>%reset -f</code> followed by re-importing the standard libraries.</p>\n<p><code>AIMO3Tool._ensure_last_print()</code> auto-wraps the final line of model-generated code with <code>print()</code> when it does not already produce output. This prevents silent failures when the model writes a bare expression rather than an explicit print statement — a common pattern in exploratory mathematical code.</p>\n<h3>2.4 EOS-Resilient Retry Logic</h3>\n<p>During inference, vLLM occasionally drops connections mid-stream. These errors manifest as exceptions at the Python HTTP client layer with messages including <code>\"Unexpected EOS while waiting for message header\"</code>, <code>\"connection reset\"</code>, and <code>\"broken pipe\"</code>. Without retry, each such error silently discards an entire attempt — reducing effective N and degrading voting quality.</p>\n<p>We implement retry with exponential backoff inside <code>_run_one_turn()</code>, the function that issues a single completion request and streams the result:</p>\n<pre><code>_EOS_MESSAGES = (\n    'unexpected eos', 'waiting for message header',\n    'connection reset', 'connection aborted',\n    'remote end closed', 'empty response',\n    'peer closed', 'broken pipe',\n)\n_MAX_EOS_RETRIES = 3\n_EOS_BACKOFF = [1.0, 2.0, 4.0]   # seconds before retries 1, 2, 3\n\n@staticmethod\ndef _is_eos_error(exc: Exception) -&gt; bool:\n    return any(kw in str(exc).lower() for kw in AIMO3Solver._EOS_MESSAGES)\n</code></pre>\n<p>When an EOS-class exception is caught, the method waits for the specified backoff duration and re-issues the identical completion request (same seed, same conversation state). Non-EOS exceptions propagate immediately without retry.</p>\n<p><strong>Evidence of effectiveness.</strong> In our two reference-set runs (10 problems × 2 runs = 20 problem-run pairs), EOS errors affected 6 problems in Run 1 and 6 in Run 2, for a total of approximately 13 and 9 error events respectively. The per-problem breakdown for Run 1:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>EOS Errors</th>\n<th>Attempts Affected</th>\n<th>Final Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Tournament</td>\n<td>1</td>\n<td>Attempt 7</td>\n<td>21818 ✓</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>3</td>\n<td>Attempts 1, 3, 7</td>\n<td>580 ✓</td>\n</tr>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>3</td>\n<td>Attempts 4, 5, 8</td>\n<td>50 ✓</td>\n</tr>\n<tr>\n<td>f(n)=Σgcd</td>\n<td>3</td>\n<td>Attempts 1, 6, 7</td>\n<td>32951 ✓</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>1</td>\n<td>Attempt 5</td>\n<td>160 ✓</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>2</td>\n<td>Attempts 6, 7</td>\n<td>57447 ✓</td>\n</tr>\n</tbody>\n</table>\n<p>In every case where an attempt experienced an EOS error, the retry mechanism allowed the attempt to eventually contribute a valid answer. The total overhead is at most 7 seconds per recovered attempt (1+2+4s), negligible against a 300–900-second per-problem budget.</p>\n<p>The key architectural insight is that without retry, these 13 error events would each consume an attempt slot while producing <code>None</code> as the answer — silently reducing effective N from 8 toward 2 on some problems, potentially shifting the vote from correct to incorrect.</p>\n<hr>\n<h2>3. Voting Strategy</h2>\n<p><strong>Why this section matters:</strong> Voting is where the rubber meets the road — even a perfect model can fail if the voting strategy picks the wrong answer. We tested two approaches: entropy-weighted majority voting (our winner) and ensemble convergence voting (catastrophic failure).</p>\n<h3>3.1 Entropy-Weighted Majority Voting</h3>\n<p>The voting function weights each attempt by the inverse of its mean token-level Shannon entropy. Lower entropy = higher confidence = higher vote weight. This extends the self-consistency voting approach of Wang et al. [1] by weighting votes rather than treating them uniformly. This is used in all notebook versions (baseline, v1, v2, v5, v6).</p>\n<p>The answer with the highest cumulative weight wins. If no answer reaches the early_stop threshold (4 agreeing votes), the highest-weighted answer is returned.</p>\n<h3>3.2 Ensemble Convergence Voting — Why It Failed</h3>\n<p>In notebook v4 we replaced entropy voting with a more complex ensemble that monitored answer distribution stability. The implementation combined dual-temperature sampling (T=0.8 primary, T=1.2 secondary), per-answer running statistics (votes, entropy weight, position weight), a convergence detector that stopped when the running mean stabilized, and a keyword-based difficulty classifier routing each problem to an easy (150s), medium (300s), or hard (900s) time budget.</p>\n<p><strong>Result: 2/10 on the reference set.</strong> The ensemble produced \"1\" or \"2\" as answers to most hard problems. The failure has two distinct mechanisms:</p>\n<p><em>Mechanism 1 — Lock-on to first wrong answer:</em> On hard problems with high answer diversity, the first answer to appear in the running distribution gets a head start. The convergence criterion then stabilizes around this first answer rather than waiting for a genuine majority. Majority voting avoids this by requiring a threshold count, not distribution stability.</p>\n<p><em>Mechanism 2 — Difficulty misclassification:</em> The keyword classifier is heuristic — keywords like \"circle,\" \"integer,\" \"divisor\" trigger \"hard\" classification, while simpler-seeming problems might be routed to 150 seconds. A 150-second budget for even a moderately complex problem produces 0 valid attempts, giving a vote of zero on that problem.</p>\n<p>The comparison is stark: entropy voting with N=8, T=1.0, verbose prompt → 9/10; convergence voting with N=20, T=0.8, V40 prompt → 2/10. This 7-problem regression validates entropy-weighted majority voting as the correct aggregation strategy for this problem distribution.</p>\n<hr>\n<h2>4. System Prompt Design</h2>\n<p><strong>Why prompt design matters:</strong> The system prompt shapes how the model approaches every problem. A good prompt guides the model through structured reasoning (UNDERSTAND → EXPLORE → PLAN → EXECUTE → VERIFY), reducing the chance of jumping directly to a wrong answer. We tested two extremes: verbose 5-stage vs. concise 3-line.</p>\n<h3>4.1 Verbose 5-Stage IMO Prompt</h3>\n<p>Used in baseline, v1, v2, v5, v6:</p>\n<pre><code>You are an elite mathematical problem solver with expertise at the International\nMathematical Olympiad (IMO) level. Your goal is to find the correct answer through\nrigorous mathematical reasoning.\n\n# Problem-Solving Approach:\n1. UNDERSTAND: Carefully read the problem. Identify what is given,\n   what needs to be found, and constraints.\n2. EXPLORE: Consider multiple solution strategies before committing to one.\n3. PLAN: Outline key steps of the most promising approach.\n4. EXECUTE: Work through the solution methodically with clear reasoning.\n5. VERIFY: Check your answer using substitution, edge cases,\n   or alternative methods.\n\n# Output Format:\nThe final answer must be a non-negative integer between 0 and 99999.\nPlace your final numerical answer inside \\boxed{}, e.g., \\boxed{42}\n\nThink step-by-step. Quality of reasoning is as important as the final answer.\n</code></pre>\n<h3>4.2 Concise V40 Prompt</h3>\n<p>Used in v3, v4:</p>\n<pre><code>You are a world-class IMO competitor.\nThe final answer must be 0-99999.\nPlace answer inside \\boxed{}.\n</code></pre>\n<p>The motivation for V40 was that verbose instructions might add unnecessary cognitive overhead, causing the model to spend tokens on structural compliance rather than mathematical reasoning.</p>\n<h3>4.3 Prompt Comparison — Evidence and Limitations</h3>\n<p>The cleanest evidence comes from the reference set: <strong>v1</strong> (verbose prompt) achieves 9/10; v4 (V40 prompt + convergence voting) achieves 2/10. However, this comparison is entirely confounded — v4 changes prompt, temperature, voting strategy, attempt count, and early_stop simultaneously. We cannot attribute the regression to the prompt.</p>\n<p>The only semi-controlled comparison is v6 (verbose, top_p=0.8, mean entropy) scoring 8/10 vs. v1 (verbose, no top_p, mean entropy) scoring 9/10. This suggests the verbose prompt is not harmful, but the prompt × voting interaction is not separable from our data.</p>\n<p><strong>Tentative conclusion:</strong> The verbose 5-stage prompt is at minimum neutral and likely beneficial by ~1 problem on the reference set. The structured UNDERSTAND/EXPLORE/PLAN/EXECUTE/VERIFY scaffold appears to organize the model's reasoning into distinct phases, reducing the likelihood of jumping directly to an incorrect answer without exploration.</p>\n<hr>\n<h2>5. Ablation Study</h2>\n<p><strong>Why ablation matters:</strong> We joined late with only 5 submissions. Every change had to be justified by theory and tested on the reference set. The ablations below document what we learned — including what <em>didn't</em> work.</p>\n<h3>5.1 All Configurations</h3>\n<table>\n<thead>\n<tr>\n<th>Version</th>\n<th>Prompt</th>\n<th>Temp</th>\n<th>top_p</th>\n<th>Voting</th>\n<th>Attempts</th>\n<th>Workers</th>\n<th>Early Stop</th>\n<th>Local /10</th>\n<th>LB Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>baseline</td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>0 (bug)</strong></td>\n<td>—</td>\n</tr>\n<tr>\n<td><strong>v1</strong></td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>9/10</strong></td>\n<td><strong>44</strong></td>\n</tr>\n<tr>\n<td>v2</td>\n<td>Verbose</td>\n<td>0.8</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>12</td>\n<td>8</td>\n<td>5</td>\n<td>—</td>\n<td>39</td>\n</tr>\n<tr>\n<td>v3</td>\n<td>V40</td>\n<td>0.8+1.2</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>20</td>\n<td>16</td>\n<td>7</td>\n<td>—</td>\n<td>33</td>\n</tr>\n<tr>\n<td>v4</td>\n<td>V40</td>\n<td>0.8+1.2</td>\n<td>—</td>\n<td>Convergence</td>\n<td>20</td>\n<td>16</td>\n<td>7</td>\n<td><strong>2/10</strong></td>\n<td>35</td>\n</tr>\n<tr>\n<td>v5</td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>0.8</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>8/10</strong></td>\n<td>39</td>\n</tr>\n<tr>\n<td>v6</td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>0.8</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>8/10</strong></td>\n<td>—</td>\n</tr>\n</tbody>\n</table>\n<p>Additional versions (baseline, v5) contained a missing function bug (0/10). v6 tested top_p=0.8 without submission (8/10 local). Only v1 was submitted to the leaderboard multiple times.</p>\n<h3>5.2 Finding 1: Convergence Voting — Catastrophic Failure (−7 problems)</h3>\n<p>v4 scores 2/10 vs. 9/10 for v1. As documented in Section 3.2, the failure is systematic and attributable to two distinct mechanisms: lock-on to first wrong answer and difficulty misclassification. This is the single most important finding: for this model and problem distribution, entropy-weighted majority voting is strongly preferred over convergence-based ensemble methods.</p>\n<h3>5.3 Finding 2: More Attempts Under Fixed Time Budget — Public LB Regression (−5 to −11)</h3>\n<p>v2 raises attempts from 8 to 12 and early_stop from 4 to 5, and reduces temperature from 1.0 to 0.8. Public LB drops from 44 to 39. v3 raises attempts to 20, drops to 33. The regression has a clear mechanism: more attempts per problem means less time per problem on average. When problems are ordered in a fixed sequence and some problems consume their full 900-second budget, later problems in a high-attempt configuration may receive only 60–90 seconds — insufficient for any valid attempt to complete. Problems that timeout return 0.</p>\n<p>The expected score under a time budget constraint is:</p>\n<p>$$E[score] = \\sum_{i=1}^{50} p_i \\cdot \\mathbf{1}[problem_i \\text{ does not timeout}]$$</p>\n<p>Increasing N from 8 to 20 reduces the second factor even as it might increase the first — and the overall effect is negative.</p>\n<p><strong>Lesson:</strong> Under a hard wall-clock constraint, the optimal N is not \"maximize\" but \"fit within the time budget across all 50 problems.\" N=8 with early stopping appears near-optimal for a 17,400-second budget on this model and problem distribution.</p>\n<h3>5.4 Finding 3: top_p=0.8 — No Measurable Effect</h3>\n<p>v5 and v6 add <code>top_p=0.8</code> (not set in v1, which uses the vLLM default of 1.0). v6 (which fixes the bug in v5) scores 8/10 vs. 9/10 for v1. The single additional error is the n-Norwegian problem, which v1 also gets wrong. <code>top_p=0.8</code> does not detectably change accuracy for this model at T=1.0.</p>\n<p>This is consistent with theoretical expectations: <code>min_p=0.02</code> already filters out very low-probability tokens; <code>top_p=0.8</code> at T=1.0 adds additional filtering of the low end of the distribution. For a model as large as gpt-oss-120b, the marginal tokens filtered by top_p=0.8 are unlikely to be relevant to mathematical reasoning quality.</p>\n<h3>5.5 Finding 4: Missing Function Definition — Complete Failure (0/10)</h3>\n<p>The <code>baseline</code> and <code>v5</code> notebooks reference <code>compute_weighted_entropy()</code> in the voting code path, but the function is not defined in those versions. Every call falls through to the <code>return 0</code> fallback, producing all-zero scores regardless of model output.</p>\n<p>The diagnosis required reading the exception traceback carefully — the model was generating valid answers, but the voting function silently returned 0 before they were compared. Fixing this by ensuring the entropy function is properly defined and wired into the voting path restored normal scoring.</p>\n<p><strong>Lesson:</strong> Before any leaderboard submission, run the complete pipeline on at least one reference problem and verify that the voting function returns a finite, non-zero value and that the predicted answer matches the model's actual output.</p>\n<hr>\n<h2>6. Results</h2>\n<h3>6.1 Leaderboard Submission History</h3>\n<table>\n<thead>\n<tr>\n<th>Submission</th>\n<th>Version</th>\n<th>Public LB</th>\n<th>Key Difference from v1</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>v1</td>\n<td><strong>44</strong></td>\n<td>— (best config)</td>\n</tr>\n<tr>\n<td>2</td>\n<td>v2</td>\n<td><strong>39</strong></td>\n<td>12 attempts, early_stop=5, T=0.8</td>\n</tr>\n<tr>\n<td>3</td>\n<td>v3</td>\n<td><strong>33</strong></td>\n<td>V40 prompt, 20 attempts, 16 workers</td>\n</tr>\n<tr>\n<td>4</td>\n<td>v1</td>\n<td><strong>42</strong></td>\n<td>Re-submission (variance)</td>\n</tr>\n<tr>\n<td>5</td>\n<td>v1</td>\n<td><strong>39</strong></td>\n<td>Re-submission (variance)</td>\n</tr>\n</tbody>\n</table>\n<p>The two re-submissions of v1 scoring 42 (vs. the original 44) illustrate the run-to-run variance inherent in stochastic sampling at T=1.0. Without repeated runs, we cannot establish the true mean — 44 could be a favorable sample from a distribution centered around 39–40, or the configuration could have a genuine mean near 44. The two reference-set runs (both 9/10) provide weak evidence of stability on the reference problems, but cannot bound competition-set variance.</p>\n<h3>6.2 Reference Set Results — v1 (9/10)</h3>\n<table>\n<thead>\n<tr>\n<th>#</th>\n<th>Problem Description</th>\n<th>GT</th>\n<th>Answer</th>\n<th>Votes</th>\n<th>Early Stop</th>\n<th>Correct</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>500×500 square, k rectangles</td>\n<td>520</td>\n<td>520</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>2</td>\n<td>Tournament, 2²⁰ runners</td>\n<td>21818</td>\n<td>21818</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>3</td>\n<td>f: Z≥1→Z≥1, coprime condition</td>\n<td>580</td>\n<td>580</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>4</td>\n<td>Acute triangle ABC, integer sides</td>\n<td>336</td>\n<td>336</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>5</td>\n<td>Alice &amp; Bob sweets</td>\n<td>50</td>\n<td>50</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>6</td>\n<td>Ken blackboard, integer n</td>\n<td>32193</td>\n<td>32193</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>7</td>\n<td>f(n) = Σ gcd(i,n), i=1..n</td>\n<td>32951</td>\n<td>32951</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>8</td>\n<td>α: Z→Z, finitely nonzero</td>\n<td>160</td>\n<td>160</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>9</td>\n<td>Triangle ABC, circumcircle Ω</td>\n<td>57447</td>\n<td>57447</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>10</td>\n<td>n-Norwegian numbers</td>\n<td>?</td>\n<td>8687</td>\n<td>1</td>\n<td>✗</td>\n<td>?</td>\n</tr>\n</tbody>\n</table>\n<p>Problem 10 is the only one without early stop. The ground truth for the Norwegian problem in the reference set context may differ from what the writeup suggests — the community discussion indicates 8687 is a plausible answer for the specific parameterization of this problem.</p>\n<h3>6.3 Per-Problem Compute Analysis</h3>\n<p>A key finding from our per-problem analysis is the extreme variance in compute consumption:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>Total Tokens</th>\n<th>Relative Cost</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>7,501</td>\n<td>1×</td>\n</tr>\n<tr>\n<td>f(n) = Σgcd</td>\n<td>19,402</td>\n<td>2.6×</td>\n</tr>\n<tr>\n<td>Ken blackboard</td>\n<td>24,125</td>\n<td>3.2×</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>31,525</td>\n<td>4.2×</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>62,328</td>\n<td>8.3×</td>\n</tr>\n<tr>\n<td>500×500</td>\n<td>62,855</td>\n<td>8.4×</td>\n</tr>\n<tr>\n<td>Triangle (336)</td>\n<td>59,553</td>\n<td>7.9×</td>\n</tr>\n<tr>\n<td>Tournament</td>\n<td>75,327</td>\n<td>10×</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>119,270</td>\n<td>15.9×</td>\n</tr>\n<tr>\n<td><strong>n-Norwegian</strong></td>\n<td><strong>322,515</strong></td>\n<td><strong>43×</strong></td>\n</tr>\n</tbody>\n</table>\n<p>The n-Norwegian problem consumes 43× the compute of Alice &amp; Bob and more than the next two hardest problems combined. Under a time budget, this problem represents a significant drain — if it appears early in the sequence, it leaves less budget for subsequent problems.</p>\n<h3>6.4 Full Per-Problem Attempt Analysis (v1)</h3>\n<h4>Problem 2 — Tournament with 2²⁰ runners (correct)</h4>\n<table>\n<thead>\n<tr>\n<th>Attempt</th>\n<th>Tokens</th>\n<th>Python Calls</th>\n<th>Errors</th>\n<th>Entropy</th>\n<th>Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>14,287</td>\n<td>15</td>\n<td>2</td>\n<td>0.813</td>\n<td>21818</td>\n</tr>\n<tr>\n<td>2</td>\n<td>14,756</td>\n<td>16</td>\n<td>1</td>\n<td>0.887</td>\n<td>21818</td>\n</tr>\n<tr>\n<td>3</td>\n<td>15,259</td>\n<td>5</td>\n<td>0</td>\n<td><strong>0.938</strong></td>\n<td><strong>62140</strong></td>\n</tr>\n<tr>\n<td>4</td>\n<td>15,316</td>\n<td>13</td>\n<td>2</td>\n<td>0.854</td>\n<td>21818</td>\n</tr>\n<tr>\n<td>5</td>\n<td>15,709</td>\n<td>16</td>\n<td>3</td>\n<td>0.822</td>\n<td>21818</td>\n</tr>\n</tbody>\n</table>\n<p>Attempt 3 produces the wrong answer (62140) with the <em>highest</em> entropy in the group (0.938). Entropy weighting correctly reduces its influence: inverse weight 1/0.938 = 1.066 vs. 1/0.813 = 1.230 for the most confident correct attempt. Early stop at 5 correct votes. The entropy voting function performs exactly as designed here — the wrong answer comes from the least confident attempt.</p>\n<h4>Problem 8 — α: Z→Z, finitely nonzero (correct, slow convergence)</h4>\n<table>\n<thead>\n<tr>\n<th>Attempt</th>\n<th>Tokens</th>\n<th>Python Calls</th>\n<th>Errors</th>\n<th>Entropy</th>\n<th>Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>7,601</td>\n<td>0</td>\n<td>0</td>\n<td>0.861</td>\n<td><strong>2</strong></td>\n</tr>\n<tr>\n<td>2</td>\n<td>15,280</td>\n<td>10</td>\n<td>2</td>\n<td>0.777</td>\n<td>160</td>\n</tr>\n<tr>\n<td>3</td>\n<td>16,385</td>\n<td>11</td>\n<td>3</td>\n<td>0.814</td>\n<td><strong>114</strong></td>\n</tr>\n<tr>\n<td>4</td>\n<td>18,871</td>\n<td>32</td>\n<td>7</td>\n<td>0.705</td>\n<td>160</td>\n</tr>\n<tr>\n<td>5</td>\n<td>16,921</td>\n<td>23</td>\n<td>5</td>\n<td>0.780</td>\n<td><strong>266</strong></td>\n</tr>\n<tr>\n<td>6</td>\n<td>19,892</td>\n<td>21</td>\n<td>3</td>\n<td>0.801</td>\n<td>160</td>\n</tr>\n<tr>\n<td>7</td>\n<td>24,320</td>\n<td>24</td>\n<td>1</td>\n<td>0.808</td>\n<td>160</td>\n</tr>\n</tbody>\n</table>\n<p>Attempt 1 reaches an answer (2) after only 7,601 tokens with 0 Python calls — the model jumped directly to a conclusion without exploration. This attempt has high entropy (0.861) and produces a wrong answer. Attempts 2, 4, 6, 7 all produce the correct answer (160) through extensive tool use (10–32 Python calls). Early stop at 7 correct votes. This illustrates why early stopping requires 4 <em>agreeing</em> votes rather than stopping after any 4 attempts — on this problem, the first attempt's fast-but-wrong answer would have derailed a less robust stopping criterion.</p>\n<h4>Problem 10 — n-Norwegian (wrong, no convergence)</h4>\n<table>\n<thead>\n<tr>\n<th>Attempt</th>\n<th>Tokens</th>\n<th>Python Calls</th>\n<th>Errors</th>\n<th>Entropy</th>\n<th>Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>24,757</td>\n<td>22</td>\n<td>2</td>\n<td>0.731</td>\n<td>6825</td>\n</tr>\n<tr>\n<td>2</td>\n<td>30,388</td>\n<td>17</td>\n<td>3</td>\n<td>0.665</td>\n<td>24433</td>\n</tr>\n<tr>\n<td>3</td>\n<td>29,426</td>\n<td>15</td>\n<td>3</td>\n<td>0.758</td>\n<td>88272</td>\n</tr>\n<tr>\n<td>4</td>\n<td>32,952</td>\n<td>44</td>\n<td>3</td>\n<td>0.678</td>\n<td>96985</td>\n</tr>\n<tr>\n<td>5</td>\n<td>42,942</td>\n<td>60</td>\n<td>2</td>\n<td>0.659</td>\n<td>8687</td>\n</tr>\n<tr>\n<td>6</td>\n<td>43,158</td>\n<td>66</td>\n<td>5</td>\n<td>0.701</td>\n<td>36162</td>\n</tr>\n<tr>\n<td>7</td>\n<td>56,708</td>\n<td>58</td>\n<td>7</td>\n<td>0.690</td>\n<td>NA</td>\n</tr>\n<tr>\n<td>8</td>\n<td>62,184</td>\n<td>42</td>\n<td>4</td>\n<td>0.725</td>\n<td>NA</td>\n</tr>\n</tbody>\n</table>\n<p>Total tokens: 322,515 — 3–10× more than any other problem. All 6 non-NA answers are distinct. The model exhausts the full 8 attempts without any consensus. The model approaches the problem via different algorithmic paths in each attempt (different enumeration strategies, different edge-case handling), each confident in its own path, arriving at different wrong answers.</p>\n<p><strong>The critical observation: token entropy does not predict convergence failure.</strong> The mean token entropy of Norwegian (0.701) is <em>lower</em> than the Tournament problem (0.863) — yet Tournament converges unanimously in 5 attempts while Norwegian produces 6 distinct answers. By token entropy alone, the model appears <em>more confident</em> on Norwegian than on Tournament. This dissociation reveals a phenomenon we call <strong>confident divergence</strong>: the model has multiple internally-consistent but mutually-incompatible solution paths. Each attempt confidently follows one path to its conclusion — low token entropy throughout — but different attempts follow different paths.</p>\n<p>This finding has a direct implication: entropy-weighted voting correctly downweights <em>uncertain</em> attempts (high entropy), but cannot detect <em>confidently wrong</em> attempts that take different wrong paths. A complementary signal — answer-level diversity across attempts — would detect this case and flag the problem as requiring more attempts or a verifier.</p>\n<p>The n-Norwegian problem also illustrates the practical compute cost of this failure mode: 322,515 tokens consumed without any useful signal, versus 75,327 for Tournament (which resolved correctly). Under a fixed time budget, this represents a 4× compute drain for a problem that entropy-voting has no way to identify as harder in advance.</p>\n<h3>6.5 Cross-Run Stability Analysis</h3>\n<p>We executed the reference set twice with different problem orderings. Results:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>Run 1 Answer</th>\n<th>Run 2 Answer</th>\n<th>Consistent</th>\n<th>Both Correct</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>500×500 square</td>\n<td>520</td>\n<td>520</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Tournament</td>\n<td>21818</td>\n<td>21818</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>580</td>\n<td>580</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Triangle (336)</td>\n<td>336</td>\n<td>336</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>50</td>\n<td>50</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Ken blackboard</td>\n<td>32193</td>\n<td>32193</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>f(n) = Σgcd</td>\n<td>32951</td>\n<td>32951</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>160</td>\n<td>160</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>57447</td>\n<td>57447</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>n-Norwegian</td>\n<td>8687</td>\n<td>31329</td>\n<td>✗</td>\n<td>?</td>\n</tr>\n</tbody>\n</table>\n<p>9 of 10 problems produce identical answers across both runs, with early stopping triggered in all 9. The n-Norwegian problem diverges — Run 1 produces 8687 (1 vote of 6 valid attempts), Run 2 produces 31329 (1 vote of 3 valid attempts with 5 returning NA). The different orderings affected GPU state and memory allocation, leaving fewer tokens available for later problems in Run 2, which is why Norwegian (appearing 4th in Run 2 vs. 10th in Run 1) has more NA attempts in Run 2.</p>\n<p>This stability analysis has an important implication: <strong>the notebook's variance is concentrated in the n-Norwegian problem</strong>. The other 9 problems are stable enough that running twice with different orderings makes no difference. For the private test set, we expect a similar partition: most problems will produce consistent answers regardless of problem order, and a small number of genuinely hard problems will dominate the score variance.</p>\n<hr>\n<h2>7. Limitations</h2>\n<p><strong>Single competition submission for the best configuration.</strong> We submitted v1 once and obtained 44. Two re-submissions of the same notebook scored 35 and 35. Without more repeated submissions we cannot determine whether 44 is the configuration's true mean or a favorable tail. The reference-set stability (9/10 consistent) suggests stability on problems with signal, but competition-set variance is unknown.</p>\n<p><strong>Confounded ablations.</strong> v3 changes prompt style, temperature, attempt count, workers, early_stop, voting function, and batch_size simultaneously. v2 changes temperature (1.0→0.8), attempt count (8→12), early_stop (4→5), system prompt wording, and per-turn token cap simultaneously — <code>temperature_secondary = 1.2</code> was declared in v2's CFG but never passed to <code>completions.create</code>, so all v2 attempts ran at T=0.8. No ablation in our experiment sequence changes exactly one variable. Clean single-variable ablations were not feasible within the 7-day, 5-submission constraint.</p>\n<p><strong>workers=8 vs. standard 16 may explain variance.</strong> With attempts=8 and workers=8, every running attempt occupies exactly one kernel — there is no buffer for kernel startup latency or slow execution. A kernel that takes 2+ seconds to return a code result directly delays the next code cell in that attempt. We observed no timeouts attributable to this, but the pattern of scores for our v1 config (44, 35, 35) contrasts with merkiraz's similar config using workers=16 and batch_size=256 (44, 42, 42, std≈1.2). The tighter worker pool may amplify infrastructure variance under different GPU load conditions, explaining the wider spread in our observed scores.</p>\n<p><strong>batch_size=128 vs. community standard 256.</strong> Lower batch size may reduce vLLM server throughput when multiple attempts request completions simultaneously. Combined with the verbose prompt (more tokens per completion), this could increase per-problem latency slightly. This is another dimension where our config differs from configurations that showed lower variance.</p>\n<p><strong>No external answer verification.</strong> Our system has no mechanism to verify candidate answers against the problem's mathematical constraints before committing. The n-Norwegian problem is the clearest demonstration of this gap: a verifier that re-executed the model's enumeration code and checked whether the output satisfies the three-distinct-divisors property would catch many of the wrong answers before they enter the vote.</p>\n<p><strong>Note on entropy as a signal.</strong> The AMO system (David Babu et al. [6]) reports that token entropy added noise in their pipeline — \"entropy had only a weak correlation to correctness\" in their Python-tooled traces. Our finding that entropy correctly downweighted the wrong answer in Tournament (Section 6.4, Attempt 3: entropy 0.938, answer 62140 wrong) may reflect a different configuration: our system uses simpler, shorter traces than AMO's multi-agent pipeline. The entropy–convergence dissociation we document (Norwegian vs Tournament) is consistent with both findings — entropy works within a single attempt but cannot predict cross-attempt convergence.</p>\n<hr>\n<h2>8. Lessons Learned</h2>\n<p><strong>Token entropy and answer convergence are different signals.</strong> Mean token entropy measures local confidence at each decoding step. It does not measure whether different attempts will converge to the same answer. The n-Norwegian problem (entropy 0.701) looks more confident than Tournament (entropy 0.863) by this metric, yet it fails completely. An answer-diversity signal — tracking how many distinct answers appear across attempts — would catch this failure mode that entropy alone misses.</p>\n<p><strong>Verify the voting function end-to-end before submitting.</strong> The baseline and v5 notebooks failed completely (0/10) due to a missing function definition. A 30-second local test on one reference problem would have caught this before consuming a submission slot.</p>\n<p><strong>Respect the hard time budget.</strong> Every increase in attempts-per-problem reduces the fraction of problems that receive adequate compute. The improvement from N=8 to N=20 in per-problem expected accuracy is smaller than the degradation from problems timing out. The cliff is hard: a timed-out problem returns 0, not a partial credit.</p>\n<p><strong>Convergence voting is fragile.</strong> Entropy-weighted majority voting requires a threshold count of agreeing answers — it is robust to a minority of wrong attempts. Convergence-based methods stabilize around whatever answer appears first, making them vulnerable to early noise. For a problem distribution where hard problems have diverse answers, majority voting is strongly preferred.</p>\n<p><strong>Compute variance is concentrated in hard problems.</strong> The n-Norwegian problem consumes 43× more tokens than the average problem. Under a fixed time budget, these outlier problems drain compute that could be allocated to other problems. An adaptive system that detects high-token-consumption problems early and reduces their budget would improve overall efficiency.</p>\n<p><strong>EOS errors are recoverable and worth recovering.</strong> Without retry logic, approximately 13 attempt-slots were silently discarded in Run 1. With retry (overhead: 1–7 seconds per recovered attempt), all 13 recovered correctly. The implementation is simple and the benefit is concrete.</p>\n<hr>\n<h2>9. Conclusion</h2>\n<p>We presented a 7-day participation in AIMO3 achieving 44/50 (top 14 of 4,133 teams) through targeted inference engineering. The core system — 8 parallel tool-integrated reasoning attempts with entropy-weighted majority voting, adaptive time budgeting, EOS-resilient retry, and early stopping — is stable across two reference runs with different problem orderings: 9 of 10 problems produce identical correct answers, with variance concentrated entirely in one problem where the model produces no consensus at N=8.</p>\n<p>Four experiments across 8 notebook versions yield clear negative results: convergence voting catastrophically degrades performance (2/10 vs. 9/10); increasing attempt count under a fixed time budget hurts public LB score; top_p=0.8 has no detectable effect; and a missing function definition causes complete failure. These negative results are reproducible from the source notebooks provided with this writeup.</p>\n<p>The most important empirical finding is the dissociation between token-level entropy and answer convergence. The n-Norwegian problem has lower mean token entropy (0.701) than the Tournament problem (0.863), yet Norwegian fails completely while Tournament converges in 5 attempts. This \"confident divergence\" — where the model is locally confident at each step but globally takes a different wrong path each attempt — is invisible to entropy-weighted voting. Entropy voting correctly handles uncertain attempts; it cannot handle confidently-wrong divergent ones. Answer-level diversity monitoring is the missing signal, and building it into the voting function is the most important direction for future work.</p>\n<hr>\n<h2>References</h2>\n<p>[1] Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A., &amp; Zhou, D. (2023). Self-consistency improves chain of thought reasoning in language models. <em>ICLR 2023</em>. arXiv:2203.11171</p>\n<p>[2] Kwon, W., Li, Z., Zhuang, S., Sheng, Y., Zheng, L., Yu, C. H., Gonzalez, J. E., Zhang, H., &amp; Stoica, I. (2023). Efficient memory management for large language model serving with PagedAttention. <em>SOSP 2023</em>.</p>\n<p>[3] Gou, Z., Shao, Z., Gong, Y., Yang, Y., Huang, M., Duan, N., Chen, W., &amp; Zhang, T. (2023). ToRA: A tool-integrated reasoning agent for mathematical problem solving. arXiv:2309.17452</p>\n<p>[4] Moshkov, I., et al. (2025). AIMO-2 winning solution: Building state-of-the-art mathematical reasoning models with OpenMathReasoning dataset. arXiv:2504.16891</p>\n<p>[5] Frieder, S., et al. (2025). AI Mathematical Olympiad — Progress Prize 3. Kaggle Competition. <a href=\"https://kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3\" target=\"_blank\">https://kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3</a></p>\n<p>[6] David Babu et al. (2026). AMO: Agentic Math Orchestrator for Olympiad Mathematics. AIMO3 Writeup, Kaggle.</p>\n<p>[7] Nitarach, N. (2026). Model Capability Dominates: Inference-Time Optimization Lessons from AIMO 3. arXiv:2603.27844</p>\n<hr>\n<h2>Appendix A: Full Configuration — v1 (Best Submission)</h2>\n<pre><code>class CFG:\n    system_prompt = (\n        'You are an elite mathematical problem solver with expertise at the International '\n        'Mathematical Olympiad (IMO) level. Your goal is to find the correct answer through '\n        'rigorous mathematical reasoning.\\n\\n'\n        '# Problem-Solving Approach:\\n'\n        '1. UNDERSTAND: Carefully read the problem. Identify what is given, '\n        'what needs to be found, and constraints.\\n'\n        '2. EXPLORE: Consider multiple solution strategies before committing to one.\\n'\n        '3. PLAN: Outline key steps of the most promising approach.\\n'\n        '4. EXECUTE: Work through the solution methodically with clear reasoning.\\n'\n        '5. VERIFY: Check your answer using substitution, edge cases, '\n        'or alternative methods.\\n\\n'\n        '# Output Format:\\n'\n        'The final answer must be a non-negative integer between 0 and 99999.\\n'\n        'Place your final numerical answer inside \\\\boxed{}, e.g., \\\\boxed{42}\\n\\n'\n        'Think step-by-step. Quality of reasoning is as important as the final answer.'\n    )\n    tool_prompt = (\n        'Use this tool to execute Python code for:\\n'\n        '- Complex or error-prone calculations\\n'\n        '- Numerical verification of analytical results\\n'\n        '- Testing conjectures or brute-force checking small cases\\n\\n'\n        'The environment is a stateful Jupyter notebook. Code persists between executions.\\n'\n        'Always use print() to display results.\\n\\n'\n        'Code should support your reasoning, not replace it.'\n    )\n    preference_prompt = (\n        'You have access to `math`, `numpy`, `sympy`, and `mpmath`. '\n        'Use sympy for exact symbolic answers, numpy for numerical work, '\n        'and mpmath for high-precision arithmetic when needed.'\n    )\n    # Model\n    served_model_name      = 'gpt-oss'\n    model_path             = '/kaggle/input/models/danielhanchen/gpt-oss-120b/transformers/default/1'\n    # vLLM\n    dtype                  = 'auto'\n    kv_cache_dtype         = 'fp8_e4m3'\n    gpu_memory_utilization = 0.95\n    context_tokens         = 65536\n    batch_size             = 128\n    stream_interval        = 200\n    # Timing\n    notebook_limit         = 17400\n    high_problem_timeout   = 900\n    base_problem_timeout   = 300\n    server_timeout         = 180\n    session_timeout        = 960\n    jupyter_timeout        = 8\n    sandbox_timeout        = 3\n    # Solver\n    attempts               = 8\n    turns                  = 128\n    workers                = 8\n    early_stop             = 4\n    seed                   = 42\n    # Sampling\n    temperature            = 1.0\n    min_p                  = 0.02\n    top_logprobs           = 5\n    buffer_tokens          = 512\n    search_tokens          = 32\n</code></pre>\n<h2>Appendix B: Notebook Version Summary</h2>\n<table>\n<thead>\n<tr>\n<th>Filename</th>\n<th>Description</th>\n<th>Local /10</th>\n<th>LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>baseline.ipynb</code></td>\n<td>First version; <code>compute_weighted_entropy</code> undefined → bug</td>\n<td>0</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>v1.ipynb</code></td>\n<td>Full reference run; verbose prompt; mean entropy voting</td>\n<td><strong>9/10</strong></td>\n<td><strong>44</strong></td>\n</tr>\n<tr>\n<td><code>v2.ipynb</code></td>\n<td>12 attempts, early_stop=5, T=0.8/1.2 dual temperature</td>\n<td>—</td>\n<td>39</td>\n</tr>\n<tr>\n<td><code>v3.ipynb</code></td>\n<td>V40 prompt, 20 attempts, 16 workers</td>\n<td>—</td>\n<td>33</td>\n</tr>\n<tr>\n<td><code>v4.ipynb</code></td>\n<td>V40 + ensemble convergence voting, 20 attempts</td>\n<td><strong>2/10</strong></td>\n<td>35</td>\n</tr>\n<tr>\n<td><code>v5.ipynb</code></td>\n<td>Verbose, top_p=0.8; bug present</td>\n<td>0</td>\n<td>39</td>\n</tr>\n<tr>\n<td><code>v6.ipynb</code></td>\n<td>Verbose, top_p=0.8, 5-component entropy voting</td>\n<td><strong>8/10</strong></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>v1 is the only version submitted to the leaderboard (scored 44, 35, 35 across three runs).</p>\n<h2>Appendix C: Answer Extraction Logic</h2>\n<pre><code>patterns = [\n    r'\\\\boxed\\s*\\{\\s*([0-9,]+)\\s*\\}',        # \\boxed{N}\n    r'\\\\\\\\boxed\\s*\\{\\s*([0-9,]+)\\s*\\}',      # \\\\boxed{N} (escaped)\n    r'final\\s+answer\\s+is\\s*:?\\s*([0-9,]+)', # \"final answer is N\"\n    r'answer\\s*[:=]\\s*([0-9,]+)',             # \"answer: N\" or \"answer = N\"\n]\n# Scan last search_tokens=32 chunks of streamed text\n# Use last match (reversed order) to prefer the model's most recent answer\n# Validate: 0 ≤ value ≤ 99999\n</code></pre>\n<h2>Appendix D: vLLM Launch Command</h2>\n<pre><code>python -m vllm.entrypoints.openai.api_server \\\n    --seed 42 \\\n    --model /kaggle/input/models/danielhanchen/gpt-oss-120b/transformers/default/1 \\\n    --served-model-name gpt-oss \\\n    --tensor-parallel-size 1 \\\n    --max-num-seqs 128 \\\n    --gpu-memory-utilization 0.95 \\\n    --host 0.0.0.0 --port 8000 \\\n    --dtype auto \\\n    --kv-cache-dtype fp8_e4m3 \\\n    --max-model-len 65536 \\\n    --stream-interval 200 \\\n    --async-scheduling \\\n    --disable-log-stats \\\n    --enable-prefix-caching \\\n    --trust-remote-code\n</code></pre>\n<p>Note: <code>--enable-auto-tool-choice</code> and <code>--tool-call-parser pythonic</code> are deliberately excluded. These flags configure vLLM's native tool-call parsing layer, which is incompatible with <code>openai_harmony</code>'s custom encoding. Including them causes tool calls to be silently mis-parsed, producing empty responses and infinite reasoning loops.</p>",
  "comments": [
    {
      "id": 3458325,
      "author_name": "Sam Bealing",
      "author_url": "",
      "post_date": "2026-05-15T16:20:21.543000",
      "content": "<p>Following up on the questions from <a href=\"https://www.kaggle.com/philipvonderlind\" target=\"_blank\">@philipvonderlind</a>, here are some additional questions to help us assess your submission:</p>\n<ol>\n<li><strong>Compute signature as difficulty signal:</strong> The Norwegian problem consumes 43× the average compute (322k vs 7.5k tokens) and is also where the cross-run 9/10 stability breaks. Could a running token-count signal after the first 1-2 attempts be used as an early difficulty flag, triggering more budget or extra attempts before the vote commits? What would you propose for this in practice?</li>\n<li><strong>Is detecting confident divergence useful:</strong> You propose answer-level diversity monitoring as the missing signal that entropy can't catch (Norwegian's 6 distinct answers across 8 attempts). But if 8 attempts produce that many distinct answers, it may just indicate the model fundamentally can't solve the problem within budget. Is there reason to believe interventions triggered by this signal (more attempts, verifier injection) would actually recover the correct answer, rather than just generating more wrong answers?</li>\n</ol>\n<p>Look forward to reading your responses on these.</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3459144,
          "author_name": "Lê Bảo",
          "author_url": "",
          "post_date": "2026-05-17T11:38:23.737000",
          "content": "<p>Hi Sam, thank you for the follow-up questions. These are exactly the two open problems that I think matter most after the writeup: whether compute usage can be turned into an online routing signal, and whether answer-level diversity is useful when the model may simply be unable to solve the problem.</p>\n<h3>1. Could a running token-count signal after the first 1–2 attempts be used as an early difficulty flag?</h3>\n<p>Yes. I think the evidence in the writeup supports this, but I would use the signal for <strong>routing and budget protection</strong>, not simply for \"more attempts.\"</p>\n<p>In Section 6.3, the Norwegian problem is the clear compute outlier:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>Total tokens</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>7,501</td>\n</tr>\n<tr>\n<td>f(n) = Σgcd</td>\n<td>19,402</td>\n</tr>\n<tr>\n<td>Ken blackboard</td>\n<td>24,125</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>31,525</td>\n</tr>\n<tr>\n<td>Triangle</td>\n<td>59,553</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>62,328</td>\n</tr>\n<tr>\n<td>500×500</td>\n<td>62,855</td>\n</tr>\n<tr>\n<td>Tournament</td>\n<td>75,327</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>119,270</td>\n</tr>\n<tr>\n<td>n-Norwegian</td>\n<td>322,515</td>\n</tr>\n</tbody>\n</table>\n<p>Norwegian used about 322k tokens — far more than any other reference problem. It also failed to produce strong answer consensus in the run analyzed in Section 6.4. That means the difficulty signal is not only visible after the full run; it likely starts appearing after the first 1–2 completed attempts.</p>\n<p>A practical online monitor could track:</p>\n<pre><code># Evaluated after first 2 completed attempts\n\nvalid_answers = [a for a in answers if a is not None]\n\nmedian_tokens  = median(tokens_per_attempt_so_far)\ndistinct_count = len(set(valid_answers))\nmax_vote       = max(Counter(valid_answers).values(), default=0)\nvalid_rate     = len(valid_answers) / completed_attempts\n\nhigh_cost    = median_tokens &gt; 20_000\nno_consensus = len(valid_answers) &gt;= 2 and distinct_count == len(valid_answers)\n\nis_unstable = high_cost and no_consensus\n</code></pre>\n<p>The threshold <code>20_000</code> is not meant to be universal — it is a reference-set heuristic. The right value should be calibrated from more runs. The important point is the <strong>combination</strong> of two signals: high per-attempt token usage <strong>and</strong> no answer agreement. A problem can be expensive and still worth continuing if the answers are converging. The danger case is expensive <strong>and</strong> diverse.</p>\n<p>I would use the signal as a routing table:</p>\n<table>\n<thead>\n<tr>\n<th>Observed after 1–2 attempts</th>\n<th>Interpretation</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Low token usage + agreement</td>\n<td>Easy, stable</td>\n<td>Early stop as soon as threshold is met</td>\n</tr>\n<tr>\n<td>High token usage + agreement emerging</td>\n<td>Hard but converging</td>\n<td>Allow full budget, continue normally</td>\n</tr>\n<tr>\n<td>High token usage + all answers distinct</td>\n<td>Unstable / confident divergence</td>\n<td>Switch strategy or cap budget</td>\n</tr>\n<tr>\n<td>High NA / invalid rate</td>\n<td>Timeout or infrastructure risk</td>\n<td>Reduce spending or skip</td>\n</tr>\n</tbody>\n</table>\n<p>The most important practical constraint is that the <strong>global time budget dominates</strong>. Section 5.3 of the writeup shows that increasing attempts under a fixed wall-clock budget can reduce public LB score because later problems get starved. So if a problem is flagged as unstable, I would not automatically give it more attempts. Instead, I would route it to one of two branches:</p>\n<p><strong>Branch A — enough global time remains</strong></p>\n<p>Use a targeted intervention rather than another full solve:</p>\n<ul>\n<li>run a verifier pass on the top candidate answers;</li>\n<li>ask the model to compare competing derivations and identify where they diverge;</li>\n<li>run a problem-specific checker if the structure permits it.</li>\n</ul>\n<p><strong>Branch B — global time is tight</strong></p>\n<p>Cap the budget and move on:</p>\n<ul>\n<li>avoid spending 300k+ tokens on a problem with no consensus;</li>\n<li>preserve time for later problems where early agreement is more likely;</li>\n<li>return the best available answer, flagged internally as low-consensus.</li>\n</ul>\n<p>So the correct framing is not:</p>\n<blockquote>\n  <p>detect hard problem → spend more</p>\n</blockquote>\n<p>It is:</p>\n<blockquote>\n  <p>detect expensive + non-convergent problem → either verify differently or stop wasting budget</p>\n</blockquote>\n<p>That is the main engineering lesson I would take from the Norwegian problem.</p>\n<hr>\n<h3>2. Is detecting confident divergence useful if 8 distinct answers may mean the model cannot solve the problem?</h3>\n<p>I agree with the concern. If 8 attempts produce many distinct answers, there is no guarantee that attempts 9 or 10 will recover the correct answer. The Norwegian analysis suggests that simply increasing N is likely the wrong intervention.</p>\n<p>The reason I still think detecting confident divergence is useful is that it improves <strong>calibration</strong> even when it does not improve <strong>recovery</strong>.</p>\n<p>The failure mode in the writeup is:</p>\n<ul>\n<li>token entropy says: the model seems confident</li>\n<li>answer diversity says: the attempts do not agree at all</li>\n</ul>\n<p>As Section 6.4 documents, Norwegian has <em>lower</em> mean token entropy (0.701) than Tournament (0.863), yet Tournament converges unanimously while Norwegian produces 6 distinct answers. Token entropy and answer convergence are measuring different things:</p>\n<table>\n<thead>\n<tr>\n<th>Signal</th>\n<th>What it measures</th>\n<th>Failure case</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Token entropy</td>\n<td>Local confidence during generation</td>\n<td>Model is confidently following a wrong path</td>\n</tr>\n<tr>\n<td>Answer consensus</td>\n<td>Agreement across attempts</td>\n<td>Model produces many incompatible answers</td>\n</tr>\n<tr>\n<td>Token usage</td>\n<td>Compute cost / difficulty signature</td>\n<td>Model spends large budget without convergence</td>\n</tr>\n</tbody>\n</table>\n<p>Entropy-weighted voting can downweight hesitant attempts. It cannot detect a set of confident but mutually inconsistent attempts. That is why answer-level diversity is a complementary signal.</p>\n<p>A concrete divergence monitor:</p>\n<pre><code>valid_answers = [a for a in answers if a is not None]\nvalid_N       = len(valid_answers)\n\nmax_vote_count  = max(Counter(valid_answers).values(), default=0)\ndistinct_count  = len(set(valid_answers))\n\nconsensus    = max_vote_count / valid_N if valid_N else 0\ndiversity    = distinct_count / valid_N if valid_N else 1\nmean_entropy = mean(entropies)\n\nconfident_divergence = (\n    valid_N &gt;= 4\n    and consensus  &lt;= 0.25\n    and diversity  &gt;= 0.75\n    and mean_entropy &lt; entropy_threshold   # locally confident\n)\n</code></pre>\n<p>The thresholds should be calibrated from more runs. The qualitative condition is: <strong>low entropy + high diversity = locally confident, globally inconsistent</strong>.</p>\n<p>When this is detected, I would not trust the normal entropy-weighted vote and would instead trigger one of the following actions, in order of preference:</p>\n<p><strong>Action 1 — Candidate verification</strong></p>\n<p>Take the top-2 or top-3 candidate answers and ask the model to check each against the problem's defining constraints. This is structurally easier than re-deriving from scratch — the model only needs to discriminate between candidates rather than reconstruct a full solution path.</p>\n<p><strong>Action 2 — Solution-path comparison</strong></p>\n<p>Ask the model to compare the assumptions behind two conflicting derivations and identify where they diverge. This targets the divergence directly rather than ignoring it.</p>\n<p><strong>Action 3 — Executable checker</strong></p>\n<p>When the problem structure permits it (number theory, combinatorics), write code to test the defining property on candidate answers. Not always feasible for IMO-level problems, but when available it is a better use of compute than another full reasoning attempt.</p>\n<p><strong>Action 4 — Budget protection</strong></p>\n<p>If verification is not feasible and time is tight, stop spending. Return the current best answer flagged as low-consensus and preserve budget for downstream problems.</p>\n<p>This is why detecting confident divergence is useful even when the model cannot reliably recover. It lets the solver distinguish between:</p>\n<table>\n<thead>\n<tr>\n<th>Case</th>\n<th>Example behavior</th>\n<th>How to treat answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Stable majority</td>\n<td>4+ attempts agree on same answer</td>\n<td>High confidence</td>\n</tr>\n<tr>\n<td>Uncertain minority</td>\n<td>One high-entropy outlier</td>\n<td>Downweight by entropy</td>\n</tr>\n<tr>\n<td>Confident divergence</td>\n<td>Many low-entropy distinct answers</td>\n<td>Low confidence despite entropy</td>\n</tr>\n<tr>\n<td>No valid answers</td>\n<td>NA / timeouts throughout</td>\n<td>Fallback / budget cap</td>\n</tr>\n</tbody>\n</table>\n<p>The Norwegian problem sits in the third category.</p>\n<p>The cross-run stability analysis in Section 6.5 supports this interpretation. The same <code>v1</code> configuration was stable on 9 of 10 reference problems across two independent runs, while Norwegian changed between runs — one run selected the reference answer 8687, another selected a different answer. This suggests the model can sometimes reach the correct answer, but the standard voting signal is not reliable enough to know when it has done so. Detecting divergence would at minimum flag the returned answer as unreliable rather than giving it the same apparent confidence as a stable 4-vote majority.</p>\n<p>To summarize:</p>\n<ul>\n<li><strong>If the question is \"would diversity detection guarantee recovery?\"</strong> — no.</li>\n<li><strong>If the question is \"would diversity detection make the system better calibrated and more budget-aware?\"</strong> — yes.</li>\n</ul>\n<p>The practical intervention should be verification, candidate comparison, or budget capping — not blindly increasing attempts.</p>\n<p>In hindsight, the voting layer should have used at least four signals together:</p>\n<pre><code>confidence = 1 / mean_token_entropy      # local confidence per attempt\nconsensus  = max_vote_count / valid_N    # cross-attempt agreement\ndiversity  = distinct_answers / valid_N  # cross-attempt disagreement\ncost       = tokens_used_so_far          # budget pressure\n</code></pre>\n<p>The submitted pipeline used entropy and majority voting but did not explicitly track answer diversity or token-cost routing. That is the main change I would make in a next version.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3457719,
      "author_name": "Philip Vonderlind",
      "author_url": "",
      "post_date": "2026-05-14T08:25:41.663000",
      "content": "<p>Hi, thank you for your submission to the Writeup Prize. <a href=\"https://www.kaggle.com/sambealing\" target=\"_blank\">@sambealing</a> and I will post some questions below that help us in assessing your submission more closely, as described in the <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/discussion/689703\" target=\"_blank\">updated discussion post</a>.</p>\n<p>I have a few questions regarding your work:</p>\n<ol>\n<li><p><strong>Comparison to Public Notebook</strong>: Some parts of your submission appear similar to the public notebook shared in the discussion, which many participants used as a starting point. While building on others' work is certainly encouraged, it would be helpful if you could cite the original notebook, include a link to it, and clearly describe which parts you adapted, as well as the motivation behind each change.</p></li>\n<li><p><strong>Plots</strong>: Adding plots to summarize your results, especially the ensemble consensus mechanism, would improve both the readability and presentation of your work. For example, it would be useful to include plots comparing the performance of all ablations on both the public leaderboard and your local evaluation set.</p></li>\n<li><p><strong>Experiment Construction</strong>: In many of your experiments, several changes appear to be introduced at the same time, which makes the results harder to interpret. Do you have results from more isolated experiments where only one component is changed at a time? This would make it easier to attribute score changes to specific modifications and to build on those findings in future work.</p></li>\n</ol>\n<p>Looking forward to your response :)</p>",
      "votes": 0,
      "replies": [
        {
          "id": 3459123,
          "author_name": "Lê Bảo",
          "author_url": "",
          "post_date": "2026-05-17T11:14:31.037000",
          "content": "<p>Hi Philip, thank you for the detailed questions. I agree with all three concerns: attribution to the public starting point should have been clearer, the results would be easier to understand with plots, and many of my experiments are practical engineering iterations rather than clean single-variable ablations.</p>\n<h3>1. Comparison to the Public Notebook</h3>\n<p>My work started from the public <a href=\"https://www.kaggle.com/code/scottford2701/hcmus-group-4?scriptVersionId=310860229\" target=\"_blank\">HCMUS Group 4 notebook</a>, which I used as the initial runnable baseline. I also used the public <a href=\"https://www.kaggle.com/code/andreasbis/aimo-3-utils\" target=\"_blank\">AIMO 3 Utils notebook by andreasbis</a> for offline dependency packaging, especially the <code>vllm</code> and <code>openai_harmony</code> wheels.</p>\n<p>I should have cited both of these explicitly in the writeup.</p>\n<p>The HCMUS baseline already provided the main competition-compatible pipeline:</p>\n<ul>\n<li><code>gpt-oss-120b</code> served through vLLM;</li>\n<li><code>openai_harmony</code> formatting;</li>\n<li>Python tool-use through persistent Jupyter kernels;</li>\n<li>parallel self-consistency attempts;</li>\n<li>entropy-weighted majority voting;</li>\n<li>early stopping;</li>\n<li>adaptive per-problem budgeting;</li>\n<li>EOS / connection-error handling;</li>\n<li>offline Kaggle dependency setup.</li>\n</ul>\n<p>So the most accurate description of my work is not “a new pipeline from scratch,” but an inference-time engineering and evaluation study built on top of that public baseline.</p>\n<p>The parts I adapted directly were:</p>\n<table>\n<thead>\n<tr>\n<th>Component</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>vLLM serving of <code>gpt-oss-120b</code></td>\n<td>kept the same general serving approach</td>\n</tr>\n<tr>\n<td><code>openai_harmony</code> conversation format</td>\n<td>kept because it is the expected format for <code>gpt-oss</code></td>\n</tr>\n<tr>\n<td>persistent Jupyter kernel tool-use</td>\n<td>kept because stateful tool use is important for multi-step math/code reasoning</td>\n</tr>\n<tr>\n<td>parallel attempts + early stopping</td>\n<td>kept the same general self-consistency structure</td>\n</tr>\n<tr>\n<td>entropy-weighted voting</td>\n<td>kept as the main aggregation method</td>\n</tr>\n<tr>\n<td>Kaggle offline dependency setup</td>\n<td>used the public utility input by andreasbis</td>\n</tr>\n</tbody>\n</table>\n<p>My own work was mainly in changing, testing, and analyzing the inference-time configuration around this baseline: prompt variants, attempt count, worker count, batch size, temperature, convergence-voting variants, intended <code>top_p</code> variants, reference-set reruns, public LB submissions, per-problem token analysis, and failure-mode analysis around answer diversity vs. entropy.</p>\n<p>The main changes and motivations were:</p>\n<table>\n<thead>\n<tr>\n<th>Version</th>\n<th>Change</th>\n<th>Motivation</th>\n<th>Result / interpretation</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>baseline</code></td>\n<td>first version with missing entropy function bug</td>\n<td>initial run</td>\n<td>failed due implementation bug, not model quality</td>\n</tr>\n<tr>\n<td><code>v1</code></td>\n<td>8 attempts, entropy voting, verbose prompt</td>\n<td>stable baseline under time budget</td>\n<td>best public LB result</td>\n</tr>\n<tr>\n<td><code>v2</code></td>\n<td>12 attempts, <code>early_stop=5</code>, lower <code>temperature=0.8</code></td>\n<td>test whether more samples + lower randomness improves reliability</td>\n<td>public LB decreased, likely due time-budget pressure and confounded changes</td>\n</tr>\n<tr>\n<td><code>v3</code></td>\n<td>concise V40 prompt, 20 attempts, 16 workers, larger batch</td>\n<td>test whether shorter prompt + more self-consistency improves score</td>\n<td>public LB decreased; too expensive under fixed budget</td>\n</tr>\n<tr>\n<td><code>v4</code></td>\n<td>convergence / ensemble voting family</td>\n<td>test whether answer-distribution convergence is better than majority voting</td>\n<td>strong negative result locally</td>\n</tr>\n<tr>\n<td><code>v5/v6</code></td>\n<td>intended <code>top_p=0.8</code> variants</td>\n<td>test whether tail-token filtering improves math reliability</td>\n<td>weak/no clear evidence; in the code, <code>top_p</code> was declared in <code>CFG</code> but not passed to <code>completions.create</code>, so this experiment did not cleanly test <code>top_p</code></td>\n</tr>\n</tbody>\n</table>\n<p>The key lesson is that increasing inference complexity did not automatically help under the 5-hour budget. The best-performing setup was comparatively simple: 8 attempts, early stop at 4, entropy-weighted majority voting.</p>\n<h3>2. Plots</h3>\n<p>I agree that the writeup would have been much easier to read with plots. Since the writeup has already been submitted, I cannot insert them into the original text, but these are the supplemental plots I prepared after your comment.</p>\n<p><strong>Public LB score by submitted notebook version</strong></p>\n<p>This summarizes the practical outcome of the submitted configurations: <code>v1</code>, <code>v2</code>, <code>v3</code>, <code>v4</code>, and <code>v5</code>. It also makes clear that these are engineering iterations, not clean one-variable ablations.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F8e5516927cba0a7e3786a4b6bab11072%2F01_public_lb_ablation.png?generation=1779015244003143&amp;alt=media\" alt=\"\"></p>\n<p><strong>Notebook version change matrix</strong></p>\n<p>This plot is meant to make the confounding explicit. Most versions change multiple dimensions at once, which is why I should not present them as clean single-variable ablations.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F0b053c7e132e4f3331cfa60ae52f6480%2F05_ablation_change_matrix.png?generation=1779016183515576&amp;alt=media\" alt=\"\"></p>\n<p><strong>Per-problem compute signature</strong></p>\n<p>This shows Norwegian as the clear compute outlier and motivates the token-count difficulty signal.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F56448d59520aa1bb4e3478b4d3f762c3%2F03_problem_token_usage.png?generation=1779015315445959&amp;alt=media\" alt=\"\"></p>\n<p><strong>Answer diversity vs. consensus</strong></p>\n<p>This replaces the table I should have included for the ensemble/consensus discussion. Stable problems cluster around high consensus and low diversity, while Norwegian is the high-diversity / low-consensus outlier.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F4b167e956abcaab2ec95c71b25fd27a1%2F06_consensus_diversity_scatter.png?generation=1779016203985032&amp;alt=media\" alt=\"\"></p>\n<h3>3. Experiment Construction / Isolated Experiments</h3>\n<p>I agree that many experiments changed multiple things at once. This is the biggest limitation of the study.</p>\n<p>Because I joined with only 7 days remaining and had a limited submission budget, I treated the notebook versions as practical engineering iterations rather than clean scientific ablations. In hindsight, the writeup should have separated these two categories more explicitly:</p>\n<table>\n<thead>\n<tr>\n<th>Type</th>\n<th>Examples</th>\n<th>How much can be concluded?</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>repeated same-config check</td>\n<td>repeated reference run of <code>v1</code></td>\n<td>useful for run-to-run stability</td>\n</tr>\n<tr>\n<td>practical engineering iteration</td>\n<td><code>v2</code>, <code>v3</code>, <code>v4</code>, <code>v5</code>, <code>v6</code></td>\n<td>useful negative results, but confounded</td>\n</tr>\n<tr>\n<td>clean one-variable ablation</td>\n<td>mostly not available</td>\n<td>limited by time/submission budget</td>\n</tr>\n</tbody>\n</table>\n<p>The closest I have to isolated evidence is the repeated reference-set run of the same <code>v1</code> configuration discussed in Section 6.5. That checks stability rather than a component change: 9 of 10 reference problems were stable across runs, while the Norwegian problem changed.</p>\n<p>For the version comparisons:</p>\n<ul>\n<li><code>v2</code> vs. <code>v1</code> is not isolated because it changes attempt count, early-stop threshold, and temperature.</li>\n<li><code>v3</code> vs. <code>v1</code> is not isolated because it changes prompt style, attempts, workers, batch size, and early stopping.</li>\n<li><code>v4</code> should not be interpreted as “only voting changed from <code>v1</code>.” It belongs to the V40 / 20-attempt family and adds convergence / ensemble voting and related routing logic.</li>\n<li><code>v5/v6</code> were intended to test the <code>top_p=0.8</code> direction, but because <code>top_p</code> was not actually passed into the completion call, this does not support a strong conclusion about <code>top_p</code>.</li>\n</ul>\n<p>So the safe conclusions are:</p>\n<ul>\n<li>the <code>v1</code>-style entropy-voting setup was the strongest practical configuration I found;</li>\n<li>increasing attempts under the fixed wall-clock budget did not reliably improve score;</li>\n<li>convergence-style voting was a strong negative engineering result in my local test;</li>\n<li>run-to-run variance was real and concentrated mainly in the Norwegian reference problem;</li>\n<li>stronger single-variable ablations would be needed to assign precise causal effects to prompt, temperature, <code>top_p</code>, or worker count.</li>\n</ul>\n<p>If I were repeating the study with more time, I would run a proper ablation grid:</p>\n<table>\n<thead>\n<tr>\n<th>Experiment</th>\n<th>Keep fixed</th>\n<th>Change only</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>prompt ablation</td>\n<td>N=8, T=1.0, same voting</td>\n<td>verbose vs concise prompt</td>\n</tr>\n<tr>\n<td>temperature ablation</td>\n<td>N=8, same prompt/voting</td>\n<td>T=1.0 vs T=0.8</td>\n</tr>\n<tr>\n<td>attempt-count ablation</td>\n<td>same prompt/voting/T</td>\n<td>N=8 vs N=12 vs N=20</td>\n</tr>\n<tr>\n<td>voting ablation</td>\n<td>same prompt/N/T</td>\n<td>majority vs entropy-weighted vs convergence</td>\n</tr>\n<tr>\n<td>worker/batch ablation</td>\n<td>same solver config</td>\n<td>workers/batch-size only</td>\n</tr>\n</tbody>\n</table>\n<p>That would make attribution much cleaner than the constrained 7-day experiment I was able to run.</p>",
          "votes": 0,
          "replies": []
        }
      ]
    },
    {
      "id": 3447425,
      "author_name": "ayushokaay",
      "author_url": "",
      "post_date": "2026-04-23T05:29:22.890000",
      "content": "<p>looks like lot of efforts <a href=\"https://www.kaggle.com/heon29\" target=\"_blank\">@heon29</a> nice work!</p>",
      "votes": 0,
      "replies": []
    }
  ],
  "comment_count": 5,
  "messages": [
    {
      "id": 3446856,
      "postDate": "2026-04-22T08:51:10.923Z",
      "content": "<p><strong>Author:</strong> Lê Bảo<br>\n<strong>Competition:</strong> AI Mathematical Olympiad — Progress Prize 3 (AIMO3)<br>\n<strong>Notebook versions:</strong> 7 experimental configurations, 5 leaderboard submissions  </p>\n<hr>\n<h2>Reproducibility</h2>\n<table>\n<thead>\n<tr>\n<th>Resource</th>\n<th>Link</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>Kaggle Notebook (submitted)</strong></td>\n<td><a href=\"https://www.kaggle.com/code/heon29/aimoooooooooooooooooo?scriptVersionId=310606235\" target=\"_blank\">notebook</a></td>\n</tr>\n<tr>\n<td><strong>Colab Notebook (simplified)</strong></td>\n<td><a href=\"&lt;code&gt;https://colab.research.google.com/drive/1ih71S7eRTzDqC5RjY-FMGbBoxoubpRMz?usp=sharing&lt;/code&gt;\" target=\"_blank\">colab</a></td>\n</tr>\n<tr>\n<td><strong>Base Model</strong></td>\n<td><a href=\"https://huggingface.co/openai/gpt-oss-120b\" target=\"_blank\">gpt-oss-120b</a></td>\n</tr>\n</tbody>\n</table>\n<p>The submitted Kaggle notebook is open-sourced and publicly viewable. A simplified Colab version is provided as supplementary material for readers without Kaggle access — it implements the same inference pipeline using the public HuggingFace model weights. No fine-tuning was performed; the contribution is purely an inference pipeline on top of the public base model.</p>\n<hr>\n<h2>Abstract</h2>\n<p>We report an inference-time engineering study for AIMO3, conducted under severe time pressure — joining with 7 days remaining and a 5-submission budget. Using <code>danielhanchen/gpt-oss-120b</code> (116.8B total / ~5.1B active parameters via Mixture-of-Experts) served through vLLM 0.11.2 with FP8 quantization, our best submission achieves <strong>44/50</strong> on the public leaderboard; two identical resubmissions of the same notebook scored 35 and 35, indicating substantial run-to-run variance. Our system runs N=8 parallel tool-integrated reasoning attempts aggregated by entropy-weighted majority voting with early stopping.</p>\n<p>Across 7 notebook versions we test four dimensions of variation: (1) system prompt style — a verbose 5-stage IMO scaffold vs. a 3-line concise prompt; (2) sampling parameters — temperature (0.8 vs. 1.0) and top_p (absent vs. 0.8); (3) voting strategy — entropy-weighted majority vs. ensemble convergence; (4) attempt count — 8 vs. 12 vs. 20. Key findings: the verbose structured prompt outperforms the concise prompt; ensemble convergence voting catastrophically degrades performance (2/10 vs. 9/10 on the reference set); temperature reduction from 1.0 to 0.8 combined with more attempts degrades public LB from 44 to 39; top_p=0.8 has no measurable effect; a missing function definition caused 0/10 scores on two notebook versions before being diagnosed and fixed.</p>\n<p>We also document EOS-resilient retry logic — handling transient vLLM connection failures that affected 6 of 10 reference problems across both runs. Per-problem analysis across two independent reference-set runs reveals a critical finding: <strong>token-level entropy does not predict answer convergence</strong>. The n-Norwegian problem has lower mean token entropy (0.701) than the Tournament problem (0.863), yet Norwegian produces 6 completely distinct answers across 8 attempts while Tournament converges unanimously in 5. This reveals that a model can be locally confident at each reasoning step while globally taking a different wrong path each attempt — a failure mode invisible to entropy-based voting. The n-Norwegian problem also consumes 43× more compute than the average problem, with variance concentrated entirely in this single problem across both reference runs.</p>\n<hr>\n<h2>1. Introduction</h2>\n<h3>1.1 Competition Setting</h3>\n<p>AIMO3 requires solving 50 International Mathematical Olympiad-level problems on a single NVIDIA H100 80GB GPU within a 5-hour wall-clock budget. Problems span algebra, combinatorics, geometry, and number theory. All answers are non-negative integers in [0, 99999], evaluated by exact match. The competition provides a 10-problem reference set (<code>reference.csv</code>) for local development; the remaining 40 problems constitute the private test set.</p>\n<p>The primary constraint is not model quality but compute allocation: with 50 problems and a 17,400-second (4h50m) notebook limit, each problem receives at most 348 seconds on average, far less than the 900-second maximum. Effective adaptive time budgeting is therefore a first-order engineering concern alongside model configuration.</p>\n<p>AIMO3 represents a significant escalation over its predecessors. The AIMO2 winning solution (NemoSkills, Moshkov et al. [4]) achieved 34/50 using a fine-tuned 14B model on 4×L4 GPUs with 540K training problems and custom GenSelect inference. AIMO3 provides H100 hardware, enabling gpt-oss-120b inference without fine-tuning — shifting the landscape from training-time compute to inference-time engineering.</p>\n<h3>1.2 Participation Context</h3>\n<p>We joined AIMO3 with 7 days remaining before the April 15 deadline. This severely limited the number of controlled experiments we could run — 5 leaderboard submissions over 7 days, with local reference-set evaluation as the primary development signal. Our approach was targeted engineering based on hypotheses rather than broad search.</p>\n<p>This context affects how we interpret results: several ablations are confounded (multiple variables changed simultaneously), single-run comparisons have high variance, and we lack the noise floor characterization that would come from repeated identical submissions. We document these limitations explicitly throughout.</p>\n<h3>1.3 Contributions</h3>\n<ol>\n<li><strong>Complete ablation study</strong> across 8 notebook versions with exact public LB and local reference scores.</li>\n<li><strong>EOS-resilient retry logic</strong> — the only documented implementation of exponential-backoff retry for transient vLLM connection failures in this competition, with per-problem evidence of recovery.</li>\n<li><strong>Token entropy ≠ answer convergence</strong> — empirical finding that locally confident models can globally diverge: Norwegian (entropy 0.701) fails completely while Tournament (entropy 0.863) converges unanimously, showing entropy voting cannot detect \"confident divergence.\"</li>\n<li><strong>Cross-run stability analysis</strong> — 9 of 10 reference problems produce identical answers across two independent runs with different problem orderings.</li>\n<li><strong>Per-problem compute analysis</strong> — n-Norwegian consumes 43× more tokens than the average problem, revealing that hard problems are identifiable by compute signature, not just answer entropy.</li>\n<li><strong>Negative results documentation</strong> — entropy convergence voting (−7 problems), more attempts under fixed budget (−5 to −11 problems), and missing function bugs (0/10).</li>\n</ol>\n<hr>\n<h2>2. System Architecture</h2>\n<p><strong>Why this architecture matters:</strong> AIMO3 presents a unique constraint: 50 problems, 5 hours, single GPU. The solution is not about finding the best model, but about efficiently allocating limited compute across problems. Our architecture prioritizes (1) making hard problems get enough time, (2) not wasting time on easy problems that converge quickly, and (3) handling infrastructure failures gracefully.</p>\n<h3>2.1 Model and vLLM Configuration</h3>\n<p>We serve <code>danielhanchen/gpt-oss-120b</code> through a local vLLM 0.11.2 server using the proprietary <code>openai_harmony</code> protocol. Model weights (~65 GB in FP8) are pre-loaded into OS page cache via parallel sequential reads before server launch, reducing cold-start latency from ~240s to ~116s.</p>\n<table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Value</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Model</td>\n<td>danielhanchen/gpt-oss-120b</td>\n<td></td>\n</tr>\n<tr>\n<td>Total / active params</td>\n<td>116.8B / ~5.1B</td>\n<td>Mixture-of-Experts</td>\n</tr>\n<tr>\n<td>Weight format</td>\n<td>FP8 (MXFP4 E2M1)</td>\n<td></td>\n</tr>\n<tr>\n<td>KV cache</td>\n<td>fp8_e4m3</td>\n<td></td>\n</tr>\n<tr>\n<td>Engine</td>\n<td>vLLM 0.11.2</td>\n<td></td>\n</tr>\n<tr>\n<td>Tensor parallel</td>\n<td>1</td>\n<td>Single H100</td>\n</tr>\n<tr>\n<td>batch_size (max_num_seqs)</td>\n<td>128</td>\n<td>Baseline config</td>\n</tr>\n<tr>\n<td>gpu_memory_utilization</td>\n<td>0.95</td>\n<td></td>\n</tr>\n<tr>\n<td>context_tokens (max_model_len)</td>\n<td>65,536</td>\n<td></td>\n</tr>\n<tr>\n<td>stream_interval</td>\n<td>200</td>\n<td></td>\n</tr>\n<tr>\n<td>Key flags</td>\n<td><code>--async-scheduling</code> <code>--enable-prefix-caching</code> <code>--trust-remote-code</code></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>The server is started as a subprocess and polled until <code>/v1/models</code> responds (180-second timeout). All server output is written to <code>vllm_server.log</code> for debugging.</p>\n<h3>2.2 Inference Pipeline — Five Stages</h3>\n<p><strong>Why five stages:</strong> We decomposed the inference problem into a pipeline because each stage has different resource requirements and failure modes. Adaptive budget allocation needs to know the problem sequence; parallel attempts need independent seeds; early stopping needs to track answer consensus; entropy voting needs per-attempt confidence scores.</p>\n<p><strong>Stage 1 — Adaptive budget allocation.</strong> Per-problem time budget:</p>\n<pre><code>reserved = max(0, problems_remaining - 1) * base_problem_timeout  # 300s each\nbudget = max(base_timeout, min(high_timeout, notebook_limit - elapsed - reserved))\n</code></pre>\n<p>With <code>base_timeout=300s</code>, <code>high_timeout=900s</code>, <code>notebook_limit=17400s</code>: early problems receive up to 900s when time is abundant; later problems compress toward 300s as the notebook limit approaches. This avoids both under-serving hard early problems and running out of time for late problems.</p>\n<p><strong>Stage 2 — Parallel attempts.</strong> N=8 inference threads dispatched concurrently, each with a distinct seed computed as <code>attempt_seed = int((seed + i)²) mod 2³¹</code> for i ∈ [0, 7]. Temperature T=1.0 with <code>min_p=0.02</code> — the minimum token probability threshold that prevents very low-probability tokens from being sampled.</p>\n<p><strong>Stage 3 — Tool-integrated reasoning.</strong> Each attempt operates within an <code>openai_harmony</code> Harmony conversation loop, implementing Tool-Integrated Reasoning (TIR) [3]. <code>AIMO3Template</code> constructs a <code>SystemContent</code> with <code>ReasoningEffort.HIGH</code>, attaching the tool namespace for the Python sandbox. The model alternates among three channels:</p>\n<ul>\n<li><code>assistant</code>: reasoning and code generation</li>\n<li><code>python</code> (tool): code execution, result returned to conversation  </li>\n<li><code>final</code>: terminal channel where the answer is emitted</li>\n</ul>\n<p><strong>Stage 4 — Early stopping.</strong> A shared <code>threading.Event</code> is set as soon as 4 attempts agree on the same answer. Remaining futures are cancelled. This saves substantial compute on problems where the model converges quickly — in our reference runs, 8 of 9 correctly-solved problems reached early stop within 4–5 attempts, conserving approximately 3–4 attempt-slots of compute each.</p>\n<p><strong>Stage 5 — Entropy-weighted voting.</strong> Each attempt's answer is weighted by inverse mean token-level Shannon entropy:</p>\n<p>$$\\hat{a} = \\arg\\max_a \\sum_{i: ans_i = a} \\frac{1}{\\max(H_i, \\epsilon)}$$</p>\n<p>where $H_i$ is the mean entropy computed from top-5 logprobs:</p>\n<p>$$H_i = \\frac{1}{|T_i|} \\sum_{t \\in T_i} \\left(-\\sum_k p_{t,k} \\log_2 p_{t,k}\\right)$$</p>\n<p>Lower entropy = higher confidence = higher vote weight.</p>\n<p><strong>Why entropy weighting:</strong> Standard majority voting treats all attempts equally. But when the model generates a confident response (low entropy), it should carry more weight than a hesitant response (high entropy). This is especially important when some attempts take a \"shortcut\" to a wrong answer — those tend to have higher entropy because the model is less certain.</p>\n<h3>2.3 Persistent Jupyter Kernel Pool</h3>\n<p><strong>Why persistent kernels:</strong> Tool-integrated reasoning requires stateful execution — the model needs to define variables in one code cell and use them in the next. Standard Python subprocess execution loses state between calls. Persistent kernels solve this by maintaining a running Python interpreter.</p>\n<p>We maintain 8 persistent Jupyter kernels, one allocated per parallel attempt. Kernels are initialized at notebook startup (parallel, ~2 seconds total) with:</p>\n<pre><code>import math, numpy, sympy, itertools, collections, mpmath\nmpmath.mp.dps = 64   # 64 decimal places of precision\n</code></pre>\n<p>Kernel ports are allocated dynamically from 50000+ using a class-level lock for thread safety. State persists across code cells within a single attempt — variables from earlier executions survive into later ones, mimicking a real Jupyter session. Between problems, kernels are reset via <code>%reset -f</code> followed by re-importing the standard libraries.</p>\n<p><code>AIMO3Tool._ensure_last_print()</code> auto-wraps the final line of model-generated code with <code>print()</code> when it does not already produce output. This prevents silent failures when the model writes a bare expression rather than an explicit print statement — a common pattern in exploratory mathematical code.</p>\n<h3>2.4 EOS-Resilient Retry Logic</h3>\n<p>During inference, vLLM occasionally drops connections mid-stream. These errors manifest as exceptions at the Python HTTP client layer with messages including <code>\"Unexpected EOS while waiting for message header\"</code>, <code>\"connection reset\"</code>, and <code>\"broken pipe\"</code>. Without retry, each such error silently discards an entire attempt — reducing effective N and degrading voting quality.</p>\n<p>We implement retry with exponential backoff inside <code>_run_one_turn()</code>, the function that issues a single completion request and streams the result:</p>\n<pre><code>_EOS_MESSAGES = (\n    'unexpected eos', 'waiting for message header',\n    'connection reset', 'connection aborted',\n    'remote end closed', 'empty response',\n    'peer closed', 'broken pipe',\n)\n_MAX_EOS_RETRIES = 3\n_EOS_BACKOFF = [1.0, 2.0, 4.0]   # seconds before retries 1, 2, 3\n\n@staticmethod\ndef _is_eos_error(exc: Exception) -&gt; bool:\n    return any(kw in str(exc).lower() for kw in AIMO3Solver._EOS_MESSAGES)\n</code></pre>\n<p>When an EOS-class exception is caught, the method waits for the specified backoff duration and re-issues the identical completion request (same seed, same conversation state). Non-EOS exceptions propagate immediately without retry.</p>\n<p><strong>Evidence of effectiveness.</strong> In our two reference-set runs (10 problems × 2 runs = 20 problem-run pairs), EOS errors affected 6 problems in Run 1 and 6 in Run 2, for a total of approximately 13 and 9 error events respectively. The per-problem breakdown for Run 1:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>EOS Errors</th>\n<th>Attempts Affected</th>\n<th>Final Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Tournament</td>\n<td>1</td>\n<td>Attempt 7</td>\n<td>21818 ✓</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>3</td>\n<td>Attempts 1, 3, 7</td>\n<td>580 ✓</td>\n</tr>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>3</td>\n<td>Attempts 4, 5, 8</td>\n<td>50 ✓</td>\n</tr>\n<tr>\n<td>f(n)=Σgcd</td>\n<td>3</td>\n<td>Attempts 1, 6, 7</td>\n<td>32951 ✓</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>1</td>\n<td>Attempt 5</td>\n<td>160 ✓</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>2</td>\n<td>Attempts 6, 7</td>\n<td>57447 ✓</td>\n</tr>\n</tbody>\n</table>\n<p>In every case where an attempt experienced an EOS error, the retry mechanism allowed the attempt to eventually contribute a valid answer. The total overhead is at most 7 seconds per recovered attempt (1+2+4s), negligible against a 300–900-second per-problem budget.</p>\n<p>The key architectural insight is that without retry, these 13 error events would each consume an attempt slot while producing <code>None</code> as the answer — silently reducing effective N from 8 toward 2 on some problems, potentially shifting the vote from correct to incorrect.</p>\n<hr>\n<h2>3. Voting Strategy</h2>\n<p><strong>Why this section matters:</strong> Voting is where the rubber meets the road — even a perfect model can fail if the voting strategy picks the wrong answer. We tested two approaches: entropy-weighted majority voting (our winner) and ensemble convergence voting (catastrophic failure).</p>\n<h3>3.1 Entropy-Weighted Majority Voting</h3>\n<p>The voting function weights each attempt by the inverse of its mean token-level Shannon entropy. Lower entropy = higher confidence = higher vote weight. This extends the self-consistency voting approach of Wang et al. [1] by weighting votes rather than treating them uniformly. This is used in all notebook versions (baseline, v1, v2, v5, v6).</p>\n<p>The answer with the highest cumulative weight wins. If no answer reaches the early_stop threshold (4 agreeing votes), the highest-weighted answer is returned.</p>\n<h3>3.2 Ensemble Convergence Voting — Why It Failed</h3>\n<p>In notebook v4 we replaced entropy voting with a more complex ensemble that monitored answer distribution stability. The implementation combined dual-temperature sampling (T=0.8 primary, T=1.2 secondary), per-answer running statistics (votes, entropy weight, position weight), a convergence detector that stopped when the running mean stabilized, and a keyword-based difficulty classifier routing each problem to an easy (150s), medium (300s), or hard (900s) time budget.</p>\n<p><strong>Result: 2/10 on the reference set.</strong> The ensemble produced \"1\" or \"2\" as answers to most hard problems. The failure has two distinct mechanisms:</p>\n<p><em>Mechanism 1 — Lock-on to first wrong answer:</em> On hard problems with high answer diversity, the first answer to appear in the running distribution gets a head start. The convergence criterion then stabilizes around this first answer rather than waiting for a genuine majority. Majority voting avoids this by requiring a threshold count, not distribution stability.</p>\n<p><em>Mechanism 2 — Difficulty misclassification:</em> The keyword classifier is heuristic — keywords like \"circle,\" \"integer,\" \"divisor\" trigger \"hard\" classification, while simpler-seeming problems might be routed to 150 seconds. A 150-second budget for even a moderately complex problem produces 0 valid attempts, giving a vote of zero on that problem.</p>\n<p>The comparison is stark: entropy voting with N=8, T=1.0, verbose prompt → 9/10; convergence voting with N=20, T=0.8, V40 prompt → 2/10. This 7-problem regression validates entropy-weighted majority voting as the correct aggregation strategy for this problem distribution.</p>\n<hr>\n<h2>4. System Prompt Design</h2>\n<p><strong>Why prompt design matters:</strong> The system prompt shapes how the model approaches every problem. A good prompt guides the model through structured reasoning (UNDERSTAND → EXPLORE → PLAN → EXECUTE → VERIFY), reducing the chance of jumping directly to a wrong answer. We tested two extremes: verbose 5-stage vs. concise 3-line.</p>\n<h3>4.1 Verbose 5-Stage IMO Prompt</h3>\n<p>Used in baseline, v1, v2, v5, v6:</p>\n<pre><code>You are an elite mathematical problem solver with expertise at the International\nMathematical Olympiad (IMO) level. Your goal is to find the correct answer through\nrigorous mathematical reasoning.\n\n# Problem-Solving Approach:\n1. UNDERSTAND: Carefully read the problem. Identify what is given,\n   what needs to be found, and constraints.\n2. EXPLORE: Consider multiple solution strategies before committing to one.\n3. PLAN: Outline key steps of the most promising approach.\n4. EXECUTE: Work through the solution methodically with clear reasoning.\n5. VERIFY: Check your answer using substitution, edge cases,\n   or alternative methods.\n\n# Output Format:\nThe final answer must be a non-negative integer between 0 and 99999.\nPlace your final numerical answer inside \\boxed{}, e.g., \\boxed{42}\n\nThink step-by-step. Quality of reasoning is as important as the final answer.\n</code></pre>\n<h3>4.2 Concise V40 Prompt</h3>\n<p>Used in v3, v4:</p>\n<pre><code>You are a world-class IMO competitor.\nThe final answer must be 0-99999.\nPlace answer inside \\boxed{}.\n</code></pre>\n<p>The motivation for V40 was that verbose instructions might add unnecessary cognitive overhead, causing the model to spend tokens on structural compliance rather than mathematical reasoning.</p>\n<h3>4.3 Prompt Comparison — Evidence and Limitations</h3>\n<p>The cleanest evidence comes from the reference set: <strong>v1</strong> (verbose prompt) achieves 9/10; v4 (V40 prompt + convergence voting) achieves 2/10. However, this comparison is entirely confounded — v4 changes prompt, temperature, voting strategy, attempt count, and early_stop simultaneously. We cannot attribute the regression to the prompt.</p>\n<p>The only semi-controlled comparison is v6 (verbose, top_p=0.8, mean entropy) scoring 8/10 vs. v1 (verbose, no top_p, mean entropy) scoring 9/10. This suggests the verbose prompt is not harmful, but the prompt × voting interaction is not separable from our data.</p>\n<p><strong>Tentative conclusion:</strong> The verbose 5-stage prompt is at minimum neutral and likely beneficial by ~1 problem on the reference set. The structured UNDERSTAND/EXPLORE/PLAN/EXECUTE/VERIFY scaffold appears to organize the model's reasoning into distinct phases, reducing the likelihood of jumping directly to an incorrect answer without exploration.</p>\n<hr>\n<h2>5. Ablation Study</h2>\n<p><strong>Why ablation matters:</strong> We joined late with only 5 submissions. Every change had to be justified by theory and tested on the reference set. The ablations below document what we learned — including what <em>didn't</em> work.</p>\n<h3>5.1 All Configurations</h3>\n<table>\n<thead>\n<tr>\n<th>Version</th>\n<th>Prompt</th>\n<th>Temp</th>\n<th>top_p</th>\n<th>Voting</th>\n<th>Attempts</th>\n<th>Workers</th>\n<th>Early Stop</th>\n<th>Local /10</th>\n<th>LB Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>baseline</td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>0 (bug)</strong></td>\n<td>—</td>\n</tr>\n<tr>\n<td><strong>v1</strong></td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>9/10</strong></td>\n<td><strong>44</strong></td>\n</tr>\n<tr>\n<td>v2</td>\n<td>Verbose</td>\n<td>0.8</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>12</td>\n<td>8</td>\n<td>5</td>\n<td>—</td>\n<td>39</td>\n</tr>\n<tr>\n<td>v3</td>\n<td>V40</td>\n<td>0.8+1.2</td>\n<td>—</td>\n<td>Mean entropy</td>\n<td>20</td>\n<td>16</td>\n<td>7</td>\n<td>—</td>\n<td>33</td>\n</tr>\n<tr>\n<td>v4</td>\n<td>V40</td>\n<td>0.8+1.2</td>\n<td>—</td>\n<td>Convergence</td>\n<td>20</td>\n<td>16</td>\n<td>7</td>\n<td><strong>2/10</strong></td>\n<td>35</td>\n</tr>\n<tr>\n<td>v5</td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>0.8</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>8/10</strong></td>\n<td>39</td>\n</tr>\n<tr>\n<td>v6</td>\n<td>Verbose</td>\n<td>1.0</td>\n<td>0.8</td>\n<td>Mean entropy</td>\n<td>8</td>\n<td>8</td>\n<td>4</td>\n<td><strong>8/10</strong></td>\n<td>—</td>\n</tr>\n</tbody>\n</table>\n<p>Additional versions (baseline, v5) contained a missing function bug (0/10). v6 tested top_p=0.8 without submission (8/10 local). Only v1 was submitted to the leaderboard multiple times.</p>\n<h3>5.2 Finding 1: Convergence Voting — Catastrophic Failure (−7 problems)</h3>\n<p>v4 scores 2/10 vs. 9/10 for v1. As documented in Section 3.2, the failure is systematic and attributable to two distinct mechanisms: lock-on to first wrong answer and difficulty misclassification. This is the single most important finding: for this model and problem distribution, entropy-weighted majority voting is strongly preferred over convergence-based ensemble methods.</p>\n<h3>5.3 Finding 2: More Attempts Under Fixed Time Budget — Public LB Regression (−5 to −11)</h3>\n<p>v2 raises attempts from 8 to 12 and early_stop from 4 to 5, and reduces temperature from 1.0 to 0.8. Public LB drops from 44 to 39. v3 raises attempts to 20, drops to 33. The regression has a clear mechanism: more attempts per problem means less time per problem on average. When problems are ordered in a fixed sequence and some problems consume their full 900-second budget, later problems in a high-attempt configuration may receive only 60–90 seconds — insufficient for any valid attempt to complete. Problems that timeout return 0.</p>\n<p>The expected score under a time budget constraint is:</p>\n<p>$$E[score] = \\sum_{i=1}^{50} p_i \\cdot \\mathbf{1}[problem_i \\text{ does not timeout}]$$</p>\n<p>Increasing N from 8 to 20 reduces the second factor even as it might increase the first — and the overall effect is negative.</p>\n<p><strong>Lesson:</strong> Under a hard wall-clock constraint, the optimal N is not \"maximize\" but \"fit within the time budget across all 50 problems.\" N=8 with early stopping appears near-optimal for a 17,400-second budget on this model and problem distribution.</p>\n<h3>5.4 Finding 3: top_p=0.8 — No Measurable Effect</h3>\n<p>v5 and v6 add <code>top_p=0.8</code> (not set in v1, which uses the vLLM default of 1.0). v6 (which fixes the bug in v5) scores 8/10 vs. 9/10 for v1. The single additional error is the n-Norwegian problem, which v1 also gets wrong. <code>top_p=0.8</code> does not detectably change accuracy for this model at T=1.0.</p>\n<p>This is consistent with theoretical expectations: <code>min_p=0.02</code> already filters out very low-probability tokens; <code>top_p=0.8</code> at T=1.0 adds additional filtering of the low end of the distribution. For a model as large as gpt-oss-120b, the marginal tokens filtered by top_p=0.8 are unlikely to be relevant to mathematical reasoning quality.</p>\n<h3>5.5 Finding 4: Missing Function Definition — Complete Failure (0/10)</h3>\n<p>The <code>baseline</code> and <code>v5</code> notebooks reference <code>compute_weighted_entropy()</code> in the voting code path, but the function is not defined in those versions. Every call falls through to the <code>return 0</code> fallback, producing all-zero scores regardless of model output.</p>\n<p>The diagnosis required reading the exception traceback carefully — the model was generating valid answers, but the voting function silently returned 0 before they were compared. Fixing this by ensuring the entropy function is properly defined and wired into the voting path restored normal scoring.</p>\n<p><strong>Lesson:</strong> Before any leaderboard submission, run the complete pipeline on at least one reference problem and verify that the voting function returns a finite, non-zero value and that the predicted answer matches the model's actual output.</p>\n<hr>\n<h2>6. Results</h2>\n<h3>6.1 Leaderboard Submission History</h3>\n<table>\n<thead>\n<tr>\n<th>Submission</th>\n<th>Version</th>\n<th>Public LB</th>\n<th>Key Difference from v1</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>v1</td>\n<td><strong>44</strong></td>\n<td>— (best config)</td>\n</tr>\n<tr>\n<td>2</td>\n<td>v2</td>\n<td><strong>39</strong></td>\n<td>12 attempts, early_stop=5, T=0.8</td>\n</tr>\n<tr>\n<td>3</td>\n<td>v3</td>\n<td><strong>33</strong></td>\n<td>V40 prompt, 20 attempts, 16 workers</td>\n</tr>\n<tr>\n<td>4</td>\n<td>v1</td>\n<td><strong>42</strong></td>\n<td>Re-submission (variance)</td>\n</tr>\n<tr>\n<td>5</td>\n<td>v1</td>\n<td><strong>39</strong></td>\n<td>Re-submission (variance)</td>\n</tr>\n</tbody>\n</table>\n<p>The two re-submissions of v1 scoring 42 (vs. the original 44) illustrate the run-to-run variance inherent in stochastic sampling at T=1.0. Without repeated runs, we cannot establish the true mean — 44 could be a favorable sample from a distribution centered around 39–40, or the configuration could have a genuine mean near 44. The two reference-set runs (both 9/10) provide weak evidence of stability on the reference problems, but cannot bound competition-set variance.</p>\n<h3>6.2 Reference Set Results — v1 (9/10)</h3>\n<table>\n<thead>\n<tr>\n<th>#</th>\n<th>Problem Description</th>\n<th>GT</th>\n<th>Answer</th>\n<th>Votes</th>\n<th>Early Stop</th>\n<th>Correct</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>500×500 square, k rectangles</td>\n<td>520</td>\n<td>520</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>2</td>\n<td>Tournament, 2²⁰ runners</td>\n<td>21818</td>\n<td>21818</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>3</td>\n<td>f: Z≥1→Z≥1, coprime condition</td>\n<td>580</td>\n<td>580</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>4</td>\n<td>Acute triangle ABC, integer sides</td>\n<td>336</td>\n<td>336</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>5</td>\n<td>Alice &amp; Bob sweets</td>\n<td>50</td>\n<td>50</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>6</td>\n<td>Ken blackboard, integer n</td>\n<td>32193</td>\n<td>32193</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>7</td>\n<td>f(n) = Σ gcd(i,n), i=1..n</td>\n<td>32951</td>\n<td>32951</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>8</td>\n<td>α: Z→Z, finitely nonzero</td>\n<td>160</td>\n<td>160</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>9</td>\n<td>Triangle ABC, circumcircle Ω</td>\n<td>57447</td>\n<td>57447</td>\n<td>4</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>10</td>\n<td>n-Norwegian numbers</td>\n<td>?</td>\n<td>8687</td>\n<td>1</td>\n<td>✗</td>\n<td>?</td>\n</tr>\n</tbody>\n</table>\n<p>Problem 10 is the only one without early stop. The ground truth for the Norwegian problem in the reference set context may differ from what the writeup suggests — the community discussion indicates 8687 is a plausible answer for the specific parameterization of this problem.</p>\n<h3>6.3 Per-Problem Compute Analysis</h3>\n<p>A key finding from our per-problem analysis is the extreme variance in compute consumption:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>Total Tokens</th>\n<th>Relative Cost</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>7,501</td>\n<td>1×</td>\n</tr>\n<tr>\n<td>f(n) = Σgcd</td>\n<td>19,402</td>\n<td>2.6×</td>\n</tr>\n<tr>\n<td>Ken blackboard</td>\n<td>24,125</td>\n<td>3.2×</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>31,525</td>\n<td>4.2×</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>62,328</td>\n<td>8.3×</td>\n</tr>\n<tr>\n<td>500×500</td>\n<td>62,855</td>\n<td>8.4×</td>\n</tr>\n<tr>\n<td>Triangle (336)</td>\n<td>59,553</td>\n<td>7.9×</td>\n</tr>\n<tr>\n<td>Tournament</td>\n<td>75,327</td>\n<td>10×</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>119,270</td>\n<td>15.9×</td>\n</tr>\n<tr>\n<td><strong>n-Norwegian</strong></td>\n<td><strong>322,515</strong></td>\n<td><strong>43×</strong></td>\n</tr>\n</tbody>\n</table>\n<p>The n-Norwegian problem consumes 43× the compute of Alice &amp; Bob and more than the next two hardest problems combined. Under a time budget, this problem represents a significant drain — if it appears early in the sequence, it leaves less budget for subsequent problems.</p>\n<h3>6.4 Full Per-Problem Attempt Analysis (v1)</h3>\n<h4>Problem 2 — Tournament with 2²⁰ runners (correct)</h4>\n<table>\n<thead>\n<tr>\n<th>Attempt</th>\n<th>Tokens</th>\n<th>Python Calls</th>\n<th>Errors</th>\n<th>Entropy</th>\n<th>Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>14,287</td>\n<td>15</td>\n<td>2</td>\n<td>0.813</td>\n<td>21818</td>\n</tr>\n<tr>\n<td>2</td>\n<td>14,756</td>\n<td>16</td>\n<td>1</td>\n<td>0.887</td>\n<td>21818</td>\n</tr>\n<tr>\n<td>3</td>\n<td>15,259</td>\n<td>5</td>\n<td>0</td>\n<td><strong>0.938</strong></td>\n<td><strong>62140</strong></td>\n</tr>\n<tr>\n<td>4</td>\n<td>15,316</td>\n<td>13</td>\n<td>2</td>\n<td>0.854</td>\n<td>21818</td>\n</tr>\n<tr>\n<td>5</td>\n<td>15,709</td>\n<td>16</td>\n<td>3</td>\n<td>0.822</td>\n<td>21818</td>\n</tr>\n</tbody>\n</table>\n<p>Attempt 3 produces the wrong answer (62140) with the <em>highest</em> entropy in the group (0.938). Entropy weighting correctly reduces its influence: inverse weight 1/0.938 = 1.066 vs. 1/0.813 = 1.230 for the most confident correct attempt. Early stop at 5 correct votes. The entropy voting function performs exactly as designed here — the wrong answer comes from the least confident attempt.</p>\n<h4>Problem 8 — α: Z→Z, finitely nonzero (correct, slow convergence)</h4>\n<table>\n<thead>\n<tr>\n<th>Attempt</th>\n<th>Tokens</th>\n<th>Python Calls</th>\n<th>Errors</th>\n<th>Entropy</th>\n<th>Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>7,601</td>\n<td>0</td>\n<td>0</td>\n<td>0.861</td>\n<td><strong>2</strong></td>\n</tr>\n<tr>\n<td>2</td>\n<td>15,280</td>\n<td>10</td>\n<td>2</td>\n<td>0.777</td>\n<td>160</td>\n</tr>\n<tr>\n<td>3</td>\n<td>16,385</td>\n<td>11</td>\n<td>3</td>\n<td>0.814</td>\n<td><strong>114</strong></td>\n</tr>\n<tr>\n<td>4</td>\n<td>18,871</td>\n<td>32</td>\n<td>7</td>\n<td>0.705</td>\n<td>160</td>\n</tr>\n<tr>\n<td>5</td>\n<td>16,921</td>\n<td>23</td>\n<td>5</td>\n<td>0.780</td>\n<td><strong>266</strong></td>\n</tr>\n<tr>\n<td>6</td>\n<td>19,892</td>\n<td>21</td>\n<td>3</td>\n<td>0.801</td>\n<td>160</td>\n</tr>\n<tr>\n<td>7</td>\n<td>24,320</td>\n<td>24</td>\n<td>1</td>\n<td>0.808</td>\n<td>160</td>\n</tr>\n</tbody>\n</table>\n<p>Attempt 1 reaches an answer (2) after only 7,601 tokens with 0 Python calls — the model jumped directly to a conclusion without exploration. This attempt has high entropy (0.861) and produces a wrong answer. Attempts 2, 4, 6, 7 all produce the correct answer (160) through extensive tool use (10–32 Python calls). Early stop at 7 correct votes. This illustrates why early stopping requires 4 <em>agreeing</em> votes rather than stopping after any 4 attempts — on this problem, the first attempt's fast-but-wrong answer would have derailed a less robust stopping criterion.</p>\n<h4>Problem 10 — n-Norwegian (wrong, no convergence)</h4>\n<table>\n<thead>\n<tr>\n<th>Attempt</th>\n<th>Tokens</th>\n<th>Python Calls</th>\n<th>Errors</th>\n<th>Entropy</th>\n<th>Answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>24,757</td>\n<td>22</td>\n<td>2</td>\n<td>0.731</td>\n<td>6825</td>\n</tr>\n<tr>\n<td>2</td>\n<td>30,388</td>\n<td>17</td>\n<td>3</td>\n<td>0.665</td>\n<td>24433</td>\n</tr>\n<tr>\n<td>3</td>\n<td>29,426</td>\n<td>15</td>\n<td>3</td>\n<td>0.758</td>\n<td>88272</td>\n</tr>\n<tr>\n<td>4</td>\n<td>32,952</td>\n<td>44</td>\n<td>3</td>\n<td>0.678</td>\n<td>96985</td>\n</tr>\n<tr>\n<td>5</td>\n<td>42,942</td>\n<td>60</td>\n<td>2</td>\n<td>0.659</td>\n<td>8687</td>\n</tr>\n<tr>\n<td>6</td>\n<td>43,158</td>\n<td>66</td>\n<td>5</td>\n<td>0.701</td>\n<td>36162</td>\n</tr>\n<tr>\n<td>7</td>\n<td>56,708</td>\n<td>58</td>\n<td>7</td>\n<td>0.690</td>\n<td>NA</td>\n</tr>\n<tr>\n<td>8</td>\n<td>62,184</td>\n<td>42</td>\n<td>4</td>\n<td>0.725</td>\n<td>NA</td>\n</tr>\n</tbody>\n</table>\n<p>Total tokens: 322,515 — 3–10× more than any other problem. All 6 non-NA answers are distinct. The model exhausts the full 8 attempts without any consensus. The model approaches the problem via different algorithmic paths in each attempt (different enumeration strategies, different edge-case handling), each confident in its own path, arriving at different wrong answers.</p>\n<p><strong>The critical observation: token entropy does not predict convergence failure.</strong> The mean token entropy of Norwegian (0.701) is <em>lower</em> than the Tournament problem (0.863) — yet Tournament converges unanimously in 5 attempts while Norwegian produces 6 distinct answers. By token entropy alone, the model appears <em>more confident</em> on Norwegian than on Tournament. This dissociation reveals a phenomenon we call <strong>confident divergence</strong>: the model has multiple internally-consistent but mutually-incompatible solution paths. Each attempt confidently follows one path to its conclusion — low token entropy throughout — but different attempts follow different paths.</p>\n<p>This finding has a direct implication: entropy-weighted voting correctly downweights <em>uncertain</em> attempts (high entropy), but cannot detect <em>confidently wrong</em> attempts that take different wrong paths. A complementary signal — answer-level diversity across attempts — would detect this case and flag the problem as requiring more attempts or a verifier.</p>\n<p>The n-Norwegian problem also illustrates the practical compute cost of this failure mode: 322,515 tokens consumed without any useful signal, versus 75,327 for Tournament (which resolved correctly). Under a fixed time budget, this represents a 4× compute drain for a problem that entropy-voting has no way to identify as harder in advance.</p>\n<h3>6.5 Cross-Run Stability Analysis</h3>\n<p>We executed the reference set twice with different problem orderings. Results:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>Run 1 Answer</th>\n<th>Run 2 Answer</th>\n<th>Consistent</th>\n<th>Both Correct</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>500×500 square</td>\n<td>520</td>\n<td>520</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Tournament</td>\n<td>21818</td>\n<td>21818</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>580</td>\n<td>580</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Triangle (336)</td>\n<td>336</td>\n<td>336</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>50</td>\n<td>50</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Ken blackboard</td>\n<td>32193</td>\n<td>32193</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>f(n) = Σgcd</td>\n<td>32951</td>\n<td>32951</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>160</td>\n<td>160</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>57447</td>\n<td>57447</td>\n<td>✓</td>\n<td>✓</td>\n</tr>\n<tr>\n<td>n-Norwegian</td>\n<td>8687</td>\n<td>31329</td>\n<td>✗</td>\n<td>?</td>\n</tr>\n</tbody>\n</table>\n<p>9 of 10 problems produce identical answers across both runs, with early stopping triggered in all 9. The n-Norwegian problem diverges — Run 1 produces 8687 (1 vote of 6 valid attempts), Run 2 produces 31329 (1 vote of 3 valid attempts with 5 returning NA). The different orderings affected GPU state and memory allocation, leaving fewer tokens available for later problems in Run 2, which is why Norwegian (appearing 4th in Run 2 vs. 10th in Run 1) has more NA attempts in Run 2.</p>\n<p>This stability analysis has an important implication: <strong>the notebook's variance is concentrated in the n-Norwegian problem</strong>. The other 9 problems are stable enough that running twice with different orderings makes no difference. For the private test set, we expect a similar partition: most problems will produce consistent answers regardless of problem order, and a small number of genuinely hard problems will dominate the score variance.</p>\n<hr>\n<h2>7. Limitations</h2>\n<p><strong>Single competition submission for the best configuration.</strong> We submitted v1 once and obtained 44. Two re-submissions of the same notebook scored 35 and 35. Without more repeated submissions we cannot determine whether 44 is the configuration's true mean or a favorable tail. The reference-set stability (9/10 consistent) suggests stability on problems with signal, but competition-set variance is unknown.</p>\n<p><strong>Confounded ablations.</strong> v3 changes prompt style, temperature, attempt count, workers, early_stop, voting function, and batch_size simultaneously. v2 changes temperature (1.0→0.8), attempt count (8→12), early_stop (4→5), system prompt wording, and per-turn token cap simultaneously — <code>temperature_secondary = 1.2</code> was declared in v2's CFG but never passed to <code>completions.create</code>, so all v2 attempts ran at T=0.8. No ablation in our experiment sequence changes exactly one variable. Clean single-variable ablations were not feasible within the 7-day, 5-submission constraint.</p>\n<p><strong>workers=8 vs. standard 16 may explain variance.</strong> With attempts=8 and workers=8, every running attempt occupies exactly one kernel — there is no buffer for kernel startup latency or slow execution. A kernel that takes 2+ seconds to return a code result directly delays the next code cell in that attempt. We observed no timeouts attributable to this, but the pattern of scores for our v1 config (44, 35, 35) contrasts with merkiraz's similar config using workers=16 and batch_size=256 (44, 42, 42, std≈1.2). The tighter worker pool may amplify infrastructure variance under different GPU load conditions, explaining the wider spread in our observed scores.</p>\n<p><strong>batch_size=128 vs. community standard 256.</strong> Lower batch size may reduce vLLM server throughput when multiple attempts request completions simultaneously. Combined with the verbose prompt (more tokens per completion), this could increase per-problem latency slightly. This is another dimension where our config differs from configurations that showed lower variance.</p>\n<p><strong>No external answer verification.</strong> Our system has no mechanism to verify candidate answers against the problem's mathematical constraints before committing. The n-Norwegian problem is the clearest demonstration of this gap: a verifier that re-executed the model's enumeration code and checked whether the output satisfies the three-distinct-divisors property would catch many of the wrong answers before they enter the vote.</p>\n<p><strong>Note on entropy as a signal.</strong> The AMO system (David Babu et al. [6]) reports that token entropy added noise in their pipeline — \"entropy had only a weak correlation to correctness\" in their Python-tooled traces. Our finding that entropy correctly downweighted the wrong answer in Tournament (Section 6.4, Attempt 3: entropy 0.938, answer 62140 wrong) may reflect a different configuration: our system uses simpler, shorter traces than AMO's multi-agent pipeline. The entropy–convergence dissociation we document (Norwegian vs Tournament) is consistent with both findings — entropy works within a single attempt but cannot predict cross-attempt convergence.</p>\n<hr>\n<h2>8. Lessons Learned</h2>\n<p><strong>Token entropy and answer convergence are different signals.</strong> Mean token entropy measures local confidence at each decoding step. It does not measure whether different attempts will converge to the same answer. The n-Norwegian problem (entropy 0.701) looks more confident than Tournament (entropy 0.863) by this metric, yet it fails completely. An answer-diversity signal — tracking how many distinct answers appear across attempts — would catch this failure mode that entropy alone misses.</p>\n<p><strong>Verify the voting function end-to-end before submitting.</strong> The baseline and v5 notebooks failed completely (0/10) due to a missing function definition. A 30-second local test on one reference problem would have caught this before consuming a submission slot.</p>\n<p><strong>Respect the hard time budget.</strong> Every increase in attempts-per-problem reduces the fraction of problems that receive adequate compute. The improvement from N=8 to N=20 in per-problem expected accuracy is smaller than the degradation from problems timing out. The cliff is hard: a timed-out problem returns 0, not a partial credit.</p>\n<p><strong>Convergence voting is fragile.</strong> Entropy-weighted majority voting requires a threshold count of agreeing answers — it is robust to a minority of wrong attempts. Convergence-based methods stabilize around whatever answer appears first, making them vulnerable to early noise. For a problem distribution where hard problems have diverse answers, majority voting is strongly preferred.</p>\n<p><strong>Compute variance is concentrated in hard problems.</strong> The n-Norwegian problem consumes 43× more tokens than the average problem. Under a fixed time budget, these outlier problems drain compute that could be allocated to other problems. An adaptive system that detects high-token-consumption problems early and reduces their budget would improve overall efficiency.</p>\n<p><strong>EOS errors are recoverable and worth recovering.</strong> Without retry logic, approximately 13 attempt-slots were silently discarded in Run 1. With retry (overhead: 1–7 seconds per recovered attempt), all 13 recovered correctly. The implementation is simple and the benefit is concrete.</p>\n<hr>\n<h2>9. Conclusion</h2>\n<p>We presented a 7-day participation in AIMO3 achieving 44/50 (top 14 of 4,133 teams) through targeted inference engineering. The core system — 8 parallel tool-integrated reasoning attempts with entropy-weighted majority voting, adaptive time budgeting, EOS-resilient retry, and early stopping — is stable across two reference runs with different problem orderings: 9 of 10 problems produce identical correct answers, with variance concentrated entirely in one problem where the model produces no consensus at N=8.</p>\n<p>Four experiments across 8 notebook versions yield clear negative results: convergence voting catastrophically degrades performance (2/10 vs. 9/10); increasing attempt count under a fixed time budget hurts public LB score; top_p=0.8 has no detectable effect; and a missing function definition causes complete failure. These negative results are reproducible from the source notebooks provided with this writeup.</p>\n<p>The most important empirical finding is the dissociation between token-level entropy and answer convergence. The n-Norwegian problem has lower mean token entropy (0.701) than the Tournament problem (0.863), yet Norwegian fails completely while Tournament converges in 5 attempts. This \"confident divergence\" — where the model is locally confident at each step but globally takes a different wrong path each attempt — is invisible to entropy-weighted voting. Entropy voting correctly handles uncertain attempts; it cannot handle confidently-wrong divergent ones. Answer-level diversity monitoring is the missing signal, and building it into the voting function is the most important direction for future work.</p>\n<hr>\n<h2>References</h2>\n<p>[1] Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A., &amp; Zhou, D. (2023). Self-consistency improves chain of thought reasoning in language models. <em>ICLR 2023</em>. arXiv:2203.11171</p>\n<p>[2] Kwon, W., Li, Z., Zhuang, S., Sheng, Y., Zheng, L., Yu, C. H., Gonzalez, J. E., Zhang, H., &amp; Stoica, I. (2023). Efficient memory management for large language model serving with PagedAttention. <em>SOSP 2023</em>.</p>\n<p>[3] Gou, Z., Shao, Z., Gong, Y., Yang, Y., Huang, M., Duan, N., Chen, W., &amp; Zhang, T. (2023). ToRA: A tool-integrated reasoning agent for mathematical problem solving. arXiv:2309.17452</p>\n<p>[4] Moshkov, I., et al. (2025). AIMO-2 winning solution: Building state-of-the-art mathematical reasoning models with OpenMathReasoning dataset. arXiv:2504.16891</p>\n<p>[5] Frieder, S., et al. (2025). AI Mathematical Olympiad — Progress Prize 3. Kaggle Competition. <a href=\"https://kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3\" target=\"_blank\">https://kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3</a></p>\n<p>[6] David Babu et al. (2026). AMO: Agentic Math Orchestrator for Olympiad Mathematics. AIMO3 Writeup, Kaggle.</p>\n<p>[7] Nitarach, N. (2026). Model Capability Dominates: Inference-Time Optimization Lessons from AIMO 3. arXiv:2603.27844</p>\n<hr>\n<h2>Appendix A: Full Configuration — v1 (Best Submission)</h2>\n<pre><code>class CFG:\n    system_prompt = (\n        'You are an elite mathematical problem solver with expertise at the International '\n        'Mathematical Olympiad (IMO) level. Your goal is to find the correct answer through '\n        'rigorous mathematical reasoning.\\n\\n'\n        '# Problem-Solving Approach:\\n'\n        '1. UNDERSTAND: Carefully read the problem. Identify what is given, '\n        'what needs to be found, and constraints.\\n'\n        '2. EXPLORE: Consider multiple solution strategies before committing to one.\\n'\n        '3. PLAN: Outline key steps of the most promising approach.\\n'\n        '4. EXECUTE: Work through the solution methodically with clear reasoning.\\n'\n        '5. VERIFY: Check your answer using substitution, edge cases, '\n        'or alternative methods.\\n\\n'\n        '# Output Format:\\n'\n        'The final answer must be a non-negative integer between 0 and 99999.\\n'\n        'Place your final numerical answer inside \\\\boxed{}, e.g., \\\\boxed{42}\\n\\n'\n        'Think step-by-step. Quality of reasoning is as important as the final answer.'\n    )\n    tool_prompt = (\n        'Use this tool to execute Python code for:\\n'\n        '- Complex or error-prone calculations\\n'\n        '- Numerical verification of analytical results\\n'\n        '- Testing conjectures or brute-force checking small cases\\n\\n'\n        'The environment is a stateful Jupyter notebook. Code persists between executions.\\n'\n        'Always use print() to display results.\\n\\n'\n        'Code should support your reasoning, not replace it.'\n    )\n    preference_prompt = (\n        'You have access to `math`, `numpy`, `sympy`, and `mpmath`. '\n        'Use sympy for exact symbolic answers, numpy for numerical work, '\n        'and mpmath for high-precision arithmetic when needed.'\n    )\n    # Model\n    served_model_name      = 'gpt-oss'\n    model_path             = '/kaggle/input/models/danielhanchen/gpt-oss-120b/transformers/default/1'\n    # vLLM\n    dtype                  = 'auto'\n    kv_cache_dtype         = 'fp8_e4m3'\n    gpu_memory_utilization = 0.95\n    context_tokens         = 65536\n    batch_size             = 128\n    stream_interval        = 200\n    # Timing\n    notebook_limit         = 17400\n    high_problem_timeout   = 900\n    base_problem_timeout   = 300\n    server_timeout         = 180\n    session_timeout        = 960\n    jupyter_timeout        = 8\n    sandbox_timeout        = 3\n    # Solver\n    attempts               = 8\n    turns                  = 128\n    workers                = 8\n    early_stop             = 4\n    seed                   = 42\n    # Sampling\n    temperature            = 1.0\n    min_p                  = 0.02\n    top_logprobs           = 5\n    buffer_tokens          = 512\n    search_tokens          = 32\n</code></pre>\n<h2>Appendix B: Notebook Version Summary</h2>\n<table>\n<thead>\n<tr>\n<th>Filename</th>\n<th>Description</th>\n<th>Local /10</th>\n<th>LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>baseline.ipynb</code></td>\n<td>First version; <code>compute_weighted_entropy</code> undefined → bug</td>\n<td>0</td>\n<td>—</td>\n</tr>\n<tr>\n<td><code>v1.ipynb</code></td>\n<td>Full reference run; verbose prompt; mean entropy voting</td>\n<td><strong>9/10</strong></td>\n<td><strong>44</strong></td>\n</tr>\n<tr>\n<td><code>v2.ipynb</code></td>\n<td>12 attempts, early_stop=5, T=0.8/1.2 dual temperature</td>\n<td>—</td>\n<td>39</td>\n</tr>\n<tr>\n<td><code>v3.ipynb</code></td>\n<td>V40 prompt, 20 attempts, 16 workers</td>\n<td>—</td>\n<td>33</td>\n</tr>\n<tr>\n<td><code>v4.ipynb</code></td>\n<td>V40 + ensemble convergence voting, 20 attempts</td>\n<td><strong>2/10</strong></td>\n<td>35</td>\n</tr>\n<tr>\n<td><code>v5.ipynb</code></td>\n<td>Verbose, top_p=0.8; bug present</td>\n<td>0</td>\n<td>39</td>\n</tr>\n<tr>\n<td><code>v6.ipynb</code></td>\n<td>Verbose, top_p=0.8, 5-component entropy voting</td>\n<td><strong>8/10</strong></td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<p>v1 is the only version submitted to the leaderboard (scored 44, 35, 35 across three runs).</p>\n<h2>Appendix C: Answer Extraction Logic</h2>\n<pre><code>patterns = [\n    r'\\\\boxed\\s*\\{\\s*([0-9,]+)\\s*\\}',        # \\boxed{N}\n    r'\\\\\\\\boxed\\s*\\{\\s*([0-9,]+)\\s*\\}',      # \\\\boxed{N} (escaped)\n    r'final\\s+answer\\s+is\\s*:?\\s*([0-9,]+)', # \"final answer is N\"\n    r'answer\\s*[:=]\\s*([0-9,]+)',             # \"answer: N\" or \"answer = N\"\n]\n# Scan last search_tokens=32 chunks of streamed text\n# Use last match (reversed order) to prefer the model's most recent answer\n# Validate: 0 ≤ value ≤ 99999\n</code></pre>\n<h2>Appendix D: vLLM Launch Command</h2>\n<pre><code>python -m vllm.entrypoints.openai.api_server \\\n    --seed 42 \\\n    --model /kaggle/input/models/danielhanchen/gpt-oss-120b/transformers/default/1 \\\n    --served-model-name gpt-oss \\\n    --tensor-parallel-size 1 \\\n    --max-num-seqs 128 \\\n    --gpu-memory-utilization 0.95 \\\n    --host 0.0.0.0 --port 8000 \\\n    --dtype auto \\\n    --kv-cache-dtype fp8_e4m3 \\\n    --max-model-len 65536 \\\n    --stream-interval 200 \\\n    --async-scheduling \\\n    --disable-log-stats \\\n    --enable-prefix-caching \\\n    --trust-remote-code\n</code></pre>\n<p>Note: <code>--enable-auto-tool-choice</code> and <code>--tool-call-parser pythonic</code> are deliberately excluded. These flags configure vLLM's native tool-call parsing layer, which is incompatible with <code>openai_harmony</code>'s custom encoding. Including them causes tool calls to be silently mis-parsed, producing empty responses and infinite reasoning loops.</p>",
      "rawMarkdown": "**Author:** Lê Bảo                       \n**Competition:** AI Mathematical Olympiad — Progress Prize 3 (AIMO3)  \n**Notebook versions:** 7 experimental configurations, 5 leaderboard submissions  \n\n---\n\n## Reproducibility\n\n| Resource | Link |\n|----------|------|\n| **Kaggle Notebook (submitted)** | [notebook](https://www.kaggle.com/code/heon29/aimoooooooooooooooooo?scriptVersionId=310606235) |\n| **Colab Notebook (simplified)** | [colab] (`https://colab.research.google.com/drive/1ih71S7eRTzDqC5RjY-FMGbBoxoubpRMz?usp=sharing`) |\n| **Base Model** | [gpt-oss-120b](https://huggingface.co/openai/gpt-oss-120b) |\n\nThe submitted Kaggle notebook is open-sourced and publicly viewable. A simplified Colab version is provided as supplementary material for readers without Kaggle access — it implements the same inference pipeline using the public HuggingFace model weights. No fine-tuning was performed; the contribution is purely an inference pipeline on top of the public base model.\n\n---\n\n## Abstract\n\nWe report an inference-time engineering study for AIMO3, conducted under severe time pressure — joining with 7 days remaining and a 5-submission budget. Using `danielhanchen/gpt-oss-120b` (116.8B total / ~5.1B active parameters via Mixture-of-Experts) served through vLLM 0.11.2 with FP8 quantization, our best submission achieves **44/50** on the public leaderboard; two identical resubmissions of the same notebook scored 35 and 35, indicating substantial run-to-run variance. Our system runs N=8 parallel tool-integrated reasoning attempts aggregated by entropy-weighted majority voting with early stopping.\n\nAcross 7 notebook versions we test four dimensions of variation: (1) system prompt style — a verbose 5-stage IMO scaffold vs. a 3-line concise prompt; (2) sampling parameters — temperature (0.8 vs. 1.0) and top_p (absent vs. 0.8); (3) voting strategy — entropy-weighted majority vs. ensemble convergence; (4) attempt count — 8 vs. 12 vs. 20. Key findings: the verbose structured prompt outperforms the concise prompt; ensemble convergence voting catastrophically degrades performance (2/10 vs. 9/10 on the reference set); temperature reduction from 1.0 to 0.8 combined with more attempts degrades public LB from 44 to 39; top_p=0.8 has no measurable effect; a missing function definition caused 0/10 scores on two notebook versions before being diagnosed and fixed.\n\nWe also document EOS-resilient retry logic — handling transient vLLM connection failures that affected 6 of 10 reference problems across both runs. Per-problem analysis across two independent reference-set runs reveals a critical finding: **token-level entropy does not predict answer convergence**. The n-Norwegian problem has lower mean token entropy (0.701) than the Tournament problem (0.863), yet Norwegian produces 6 completely distinct answers across 8 attempts while Tournament converges unanimously in 5. This reveals that a model can be locally confident at each reasoning step while globally taking a different wrong path each attempt — a failure mode invisible to entropy-based voting. The n-Norwegian problem also consumes 43× more compute than the average problem, with variance concentrated entirely in this single problem across both reference runs.\n\n---\n\n## 1. Introduction\n\n### 1.1 Competition Setting\n\nAIMO3 requires solving 50 International Mathematical Olympiad-level problems on a single NVIDIA H100 80GB GPU within a 5-hour wall-clock budget. Problems span algebra, combinatorics, geometry, and number theory. All answers are non-negative integers in [0, 99999], evaluated by exact match. The competition provides a 10-problem reference set (`reference.csv`) for local development; the remaining 40 problems constitute the private test set.\n\nThe primary constraint is not model quality but compute allocation: with 50 problems and a 17,400-second (4h50m) notebook limit, each problem receives at most 348 seconds on average, far less than the 900-second maximum. Effective adaptive time budgeting is therefore a first-order engineering concern alongside model configuration.\n\nAIMO3 represents a significant escalation over its predecessors. The AIMO2 winning solution (NemoSkills, Moshkov et al. [4]) achieved 34/50 using a fine-tuned 14B model on 4×L4 GPUs with 540K training problems and custom GenSelect inference. AIMO3 provides H100 hardware, enabling gpt-oss-120b inference without fine-tuning — shifting the landscape from training-time compute to inference-time engineering.\n\n### 1.2 Participation Context\n\nWe joined AIMO3 with 7 days remaining before the April 15 deadline. This severely limited the number of controlled experiments we could run — 5 leaderboard submissions over 7 days, with local reference-set evaluation as the primary development signal. Our approach was targeted engineering based on hypotheses rather than broad search.\n\nThis context affects how we interpret results: several ablations are confounded (multiple variables changed simultaneously), single-run comparisons have high variance, and we lack the noise floor characterization that would come from repeated identical submissions. We document these limitations explicitly throughout.\n\n### 1.3 Contributions\n\n1. **Complete ablation study** across 8 notebook versions with exact public LB and local reference scores.\n2. **EOS-resilient retry logic** — the only documented implementation of exponential-backoff retry for transient vLLM connection failures in this competition, with per-problem evidence of recovery.\n3. **Token entropy ≠ answer convergence** — empirical finding that locally confident models can globally diverge: Norwegian (entropy 0.701) fails completely while Tournament (entropy 0.863) converges unanimously, showing entropy voting cannot detect \"confident divergence.\"\n4. **Cross-run stability analysis** — 9 of 10 reference problems produce identical answers across two independent runs with different problem orderings.\n5. **Per-problem compute analysis** — n-Norwegian consumes 43× more tokens than the average problem, revealing that hard problems are identifiable by compute signature, not just answer entropy.\n6. **Negative results documentation** — entropy convergence voting (−7 problems), more attempts under fixed budget (−5 to −11 problems), and missing function bugs (0/10).\n\n---\n\n## 2. System Architecture\n\n**Why this architecture matters:** AIMO3 presents a unique constraint: 50 problems, 5 hours, single GPU. The solution is not about finding the best model, but about efficiently allocating limited compute across problems. Our architecture prioritizes (1) making hard problems get enough time, (2) not wasting time on easy problems that converge quickly, and (3) handling infrastructure failures gracefully.\n\n### 2.1 Model and vLLM Configuration\n\nWe serve `danielhanchen/gpt-oss-120b` through a local vLLM 0.11.2 server using the proprietary `openai_harmony` protocol. Model weights (~65 GB in FP8) are pre-loaded into OS page cache via parallel sequential reads before server launch, reducing cold-start latency from ~240s to ~116s.\n\n| Parameter | Value | Notes |\n|---|---|---|\n| Model | danielhanchen/gpt-oss-120b | |\n| Total / active params | 116.8B / ~5.1B | Mixture-of-Experts |\n| Weight format | FP8 (MXFP4 E2M1) | |\n| KV cache | fp8_e4m3 | |\n| Engine | vLLM 0.11.2 | |\n| Tensor parallel | 1 | Single H100 |\n| batch_size (max_num_seqs) | 128 | Baseline config |\n| gpu_memory_utilization | 0.95 | |\n| context_tokens (max_model_len) | 65,536 | |\n| stream_interval | 200 | |\n| Key flags | `--async-scheduling` `--enable-prefix-caching` `--trust-remote-code` | |\n\nThe server is started as a subprocess and polled until `/v1/models` responds (180-second timeout). All server output is written to `vllm_server.log` for debugging.\n\n### 2.2 Inference Pipeline — Five Stages\n\n**Why five stages:** We decomposed the inference problem into a pipeline because each stage has different resource requirements and failure modes. Adaptive budget allocation needs to know the problem sequence; parallel attempts need independent seeds; early stopping needs to track answer consensus; entropy voting needs per-attempt confidence scores.\n\n**Stage 1 — Adaptive budget allocation.** Per-problem time budget:\n\n```python\nreserved = max(0, problems_remaining - 1) * base_problem_timeout  # 300s each\nbudget = max(base_timeout, min(high_timeout, notebook_limit - elapsed - reserved))\n```\n\nWith `base_timeout=300s`, `high_timeout=900s`, `notebook_limit=17400s`: early problems receive up to 900s when time is abundant; later problems compress toward 300s as the notebook limit approaches. This avoids both under-serving hard early problems and running out of time for late problems.\n\n**Stage 2 — Parallel attempts.** N=8 inference threads dispatched concurrently, each with a distinct seed computed as `attempt_seed = int((seed + i)²) mod 2³¹` for i ∈ [0, 7]. Temperature T=1.0 with `min_p=0.02` — the minimum token probability threshold that prevents very low-probability tokens from being sampled.\n\n**Stage 3 — Tool-integrated reasoning.** Each attempt operates within an `openai_harmony` Harmony conversation loop, implementing Tool-Integrated Reasoning (TIR) [3]. `AIMO3Template` constructs a `SystemContent` with `ReasoningEffort.HIGH`, attaching the tool namespace for the Python sandbox. The model alternates among three channels:\n- `assistant`: reasoning and code generation\n- `python` (tool): code execution, result returned to conversation  \n- `final`: terminal channel where the answer is emitted\n\n**Stage 4 — Early stopping.** A shared `threading.Event` is set as soon as 4 attempts agree on the same answer. Remaining futures are cancelled. This saves substantial compute on problems where the model converges quickly — in our reference runs, 8 of 9 correctly-solved problems reached early stop within 4–5 attempts, conserving approximately 3–4 attempt-slots of compute each.\n\n**Stage 5 — Entropy-weighted voting.** Each attempt's answer is weighted by inverse mean token-level Shannon entropy:\n\n$$\\hat{a} = \\arg\\max_a \\sum_{i: ans_i = a} \\frac{1}{\\max(H_i, \\epsilon)}$$\n\nwhere $H_i$ is the mean entropy computed from top-5 logprobs:\n\n$$H_i = \\frac{1}{|T_i|} \\sum_{t \\in T_i} \\left(-\\sum_k p_{t,k} \\log_2 p_{t,k}\\right)$$\n\nLower entropy = higher confidence = higher vote weight.\n\n**Why entropy weighting:** Standard majority voting treats all attempts equally. But when the model generates a confident response (low entropy), it should carry more weight than a hesitant response (high entropy). This is especially important when some attempts take a \"shortcut\" to a wrong answer — those tend to have higher entropy because the model is less certain.\n\n### 2.3 Persistent Jupyter Kernel Pool\n\n**Why persistent kernels:** Tool-integrated reasoning requires stateful execution — the model needs to define variables in one code cell and use them in the next. Standard Python subprocess execution loses state between calls. Persistent kernels solve this by maintaining a running Python interpreter.\n\nWe maintain 8 persistent Jupyter kernels, one allocated per parallel attempt. Kernels are initialized at notebook startup (parallel, ~2 seconds total) with:\n\n```python\nimport math, numpy, sympy, itertools, collections, mpmath\nmpmath.mp.dps = 64   # 64 decimal places of precision\n```\n\nKernel ports are allocated dynamically from 50000+ using a class-level lock for thread safety. State persists across code cells within a single attempt — variables from earlier executions survive into later ones, mimicking a real Jupyter session. Between problems, kernels are reset via `%reset -f` followed by re-importing the standard libraries.\n\n`AIMO3Tool._ensure_last_print()` auto-wraps the final line of model-generated code with `print()` when it does not already produce output. This prevents silent failures when the model writes a bare expression rather than an explicit print statement — a common pattern in exploratory mathematical code.\n\n### 2.4 EOS-Resilient Retry Logic\n\nDuring inference, vLLM occasionally drops connections mid-stream. These errors manifest as exceptions at the Python HTTP client layer with messages including `\"Unexpected EOS while waiting for message header\"`, `\"connection reset\"`, and `\"broken pipe\"`. Without retry, each such error silently discards an entire attempt — reducing effective N and degrading voting quality.\n\nWe implement retry with exponential backoff inside `_run_one_turn()`, the function that issues a single completion request and streams the result:\n\n```python\n_EOS_MESSAGES = (\n    'unexpected eos', 'waiting for message header',\n    'connection reset', 'connection aborted',\n    'remote end closed', 'empty response',\n    'peer closed', 'broken pipe',\n)\n_MAX_EOS_RETRIES = 3\n_EOS_BACKOFF = [1.0, 2.0, 4.0]   # seconds before retries 1, 2, 3\n\n@staticmethod\ndef _is_eos_error(exc: Exception) -> bool:\n    return any(kw in str(exc).lower() for kw in AIMO3Solver._EOS_MESSAGES)\n```\n\nWhen an EOS-class exception is caught, the method waits for the specified backoff duration and re-issues the identical completion request (same seed, same conversation state). Non-EOS exceptions propagate immediately without retry.\n\n**Evidence of effectiveness.** In our two reference-set runs (10 problems × 2 runs = 20 problem-run pairs), EOS errors affected 6 problems in Run 1 and 6 in Run 2, for a total of approximately 13 and 9 error events respectively. The per-problem breakdown for Run 1:\n\n| Problem | EOS Errors | Attempts Affected | Final Answer |\n|---|---|---|---|\n| Tournament | 1 | Attempt 7 | 21818 ✓ |\n| Coprime f(580) | 3 | Attempts 1, 3, 7 | 580 ✓ |\n| Alice & Bob | 3 | Attempts 4, 5, 8 | 50 ✓ |\n| f(n)=Σgcd | 3 | Attempts 1, 6, 7 | 32951 ✓ |\n| α: Z→Z | 1 | Attempt 5 | 160 ✓ |\n| Circumcircle | 2 | Attempts 6, 7 | 57447 ✓ |\n\nIn every case where an attempt experienced an EOS error, the retry mechanism allowed the attempt to eventually contribute a valid answer. The total overhead is at most 7 seconds per recovered attempt (1+2+4s), negligible against a 300–900-second per-problem budget.\n\nThe key architectural insight is that without retry, these 13 error events would each consume an attempt slot while producing `None` as the answer — silently reducing effective N from 8 toward 2 on some problems, potentially shifting the vote from correct to incorrect.\n\n---\n\n## 3. Voting Strategy\n\n**Why this section matters:** Voting is where the rubber meets the road — even a perfect model can fail if the voting strategy picks the wrong answer. We tested two approaches: entropy-weighted majority voting (our winner) and ensemble convergence voting (catastrophic failure).\n\n### 3.1 Entropy-Weighted Majority Voting\n\nThe voting function weights each attempt by the inverse of its mean token-level Shannon entropy. Lower entropy = higher confidence = higher vote weight. This extends the self-consistency voting approach of Wang et al. [1] by weighting votes rather than treating them uniformly. This is used in all notebook versions (baseline, v1, v2, v5, v6).\n\nThe answer with the highest cumulative weight wins. If no answer reaches the early_stop threshold (4 agreeing votes), the highest-weighted answer is returned.\n\n### 3.2 Ensemble Convergence Voting — Why It Failed\n\nIn notebook v4 we replaced entropy voting with a more complex ensemble that monitored answer distribution stability. The implementation combined dual-temperature sampling (T=0.8 primary, T=1.2 secondary), per-answer running statistics (votes, entropy weight, position weight), a convergence detector that stopped when the running mean stabilized, and a keyword-based difficulty classifier routing each problem to an easy (150s), medium (300s), or hard (900s) time budget.\n\n**Result: 2/10 on the reference set.** The ensemble produced \"1\" or \"2\" as answers to most hard problems. The failure has two distinct mechanisms:\n\n*Mechanism 1 — Lock-on to first wrong answer:* On hard problems with high answer diversity, the first answer to appear in the running distribution gets a head start. The convergence criterion then stabilizes around this first answer rather than waiting for a genuine majority. Majority voting avoids this by requiring a threshold count, not distribution stability.\n\n*Mechanism 2 — Difficulty misclassification:* The keyword classifier is heuristic — keywords like \"circle,\" \"integer,\" \"divisor\" trigger \"hard\" classification, while simpler-seeming problems might be routed to 150 seconds. A 150-second budget for even a moderately complex problem produces 0 valid attempts, giving a vote of zero on that problem.\n\nThe comparison is stark: entropy voting with N=8, T=1.0, verbose prompt → 9/10; convergence voting with N=20, T=0.8, V40 prompt → 2/10. This 7-problem regression validates entropy-weighted majority voting as the correct aggregation strategy for this problem distribution.\n\n---\n\n## 4. System Prompt Design\n\n**Why prompt design matters:** The system prompt shapes how the model approaches every problem. A good prompt guides the model through structured reasoning (UNDERSTAND → EXPLORE → PLAN → EXECUTE → VERIFY), reducing the chance of jumping directly to a wrong answer. We tested two extremes: verbose 5-stage vs. concise 3-line.\n\n### 4.1 Verbose 5-Stage IMO Prompt\n\nUsed in baseline, v1, v2, v5, v6:\n\n```\nYou are an elite mathematical problem solver with expertise at the International\nMathematical Olympiad (IMO) level. Your goal is to find the correct answer through\nrigorous mathematical reasoning.\n\n# Problem-Solving Approach:\n1. UNDERSTAND: Carefully read the problem. Identify what is given,\n   what needs to be found, and constraints.\n2. EXPLORE: Consider multiple solution strategies before committing to one.\n3. PLAN: Outline key steps of the most promising approach.\n4. EXECUTE: Work through the solution methodically with clear reasoning.\n5. VERIFY: Check your answer using substitution, edge cases,\n   or alternative methods.\n\n# Output Format:\nThe final answer must be a non-negative integer between 0 and 99999.\nPlace your final numerical answer inside \\boxed{}, e.g., \\boxed{42}\n\nThink step-by-step. Quality of reasoning is as important as the final answer.\n```\n\n### 4.2 Concise V40 Prompt\n\nUsed in v3, v4:\n\n```\nYou are a world-class IMO competitor.\nThe final answer must be 0-99999.\nPlace answer inside \\boxed{}.\n```\n\nThe motivation for V40 was that verbose instructions might add unnecessary cognitive overhead, causing the model to spend tokens on structural compliance rather than mathematical reasoning.\n\n### 4.3 Prompt Comparison — Evidence and Limitations\n\nThe cleanest evidence comes from the reference set: **v1** (verbose prompt) achieves 9/10; v4 (V40 prompt + convergence voting) achieves 2/10. However, this comparison is entirely confounded — v4 changes prompt, temperature, voting strategy, attempt count, and early_stop simultaneously. We cannot attribute the regression to the prompt.\n\nThe only semi-controlled comparison is v6 (verbose, top_p=0.8, mean entropy) scoring 8/10 vs. v1 (verbose, no top_p, mean entropy) scoring 9/10. This suggests the verbose prompt is not harmful, but the prompt × voting interaction is not separable from our data.\n\n**Tentative conclusion:** The verbose 5-stage prompt is at minimum neutral and likely beneficial by ~1 problem on the reference set. The structured UNDERSTAND/EXPLORE/PLAN/EXECUTE/VERIFY scaffold appears to organize the model's reasoning into distinct phases, reducing the likelihood of jumping directly to an incorrect answer without exploration.\n\n---\n\n## 5. Ablation Study\n\n**Why ablation matters:** We joined late with only 5 submissions. Every change had to be justified by theory and tested on the reference set. The ablations below document what we learned — including what *didn't* work.\n\n### 5.1 All Configurations\n\n| Version | Prompt | Temp | top_p | Voting | Attempts | Workers | Early Stop | Local /10 | LB Score |\n|---|---|---|---|---|---|---|---|---|---|\n| baseline | Verbose | 1.0 | — | Mean entropy | 8 | 8 | 4 | **0 (bug)** | — |\n| **v1** | Verbose | 1.0 | — | Mean entropy | 8 | 8 | 4 | **9/10** | **44** |\n| v2 | Verbose | 0.8 | — | Mean entropy | 12 | 8 | 5 | — | 39 |\n| v3 | V40 | 0.8+1.2 | — | Mean entropy | 20 | 16 | 7 | — | 33 |\n| v4 | V40 | 0.8+1.2 | — | Convergence | 20 | 16 | 7 | **2/10** | 35 |\n| v5 | Verbose | 1.0 | 0.8 | Mean entropy | 8 | 8 | 4 | **8/10** | 39 |\n| v6 | Verbose | 1.0 | 0.8 | Mean entropy | 8 | 8 | 4 | **8/10** | — |\n\nAdditional versions (baseline, v5) contained a missing function bug (0/10). v6 tested top_p=0.8 without submission (8/10 local). Only v1 was submitted to the leaderboard multiple times.\n\n### 5.2 Finding 1: Convergence Voting — Catastrophic Failure (−7 problems)\n\nv4 scores 2/10 vs. 9/10 for v1. As documented in Section 3.2, the failure is systematic and attributable to two distinct mechanisms: lock-on to first wrong answer and difficulty misclassification. This is the single most important finding: for this model and problem distribution, entropy-weighted majority voting is strongly preferred over convergence-based ensemble methods.\n\n### 5.3 Finding 2: More Attempts Under Fixed Time Budget — Public LB Regression (−5 to −11)\n\nv2 raises attempts from 8 to 12 and early_stop from 4 to 5, and reduces temperature from 1.0 to 0.8. Public LB drops from 44 to 39. v3 raises attempts to 20, drops to 33. The regression has a clear mechanism: more attempts per problem means less time per problem on average. When problems are ordered in a fixed sequence and some problems consume their full 900-second budget, later problems in a high-attempt configuration may receive only 60–90 seconds — insufficient for any valid attempt to complete. Problems that timeout return 0.\n\nThe expected score under a time budget constraint is:\n\n$$E[score] = \\sum_{i=1}^{50} p_i \\cdot \\mathbf{1}[problem_i \\text{ does not timeout}]$$\n\nIncreasing N from 8 to 20 reduces the second factor even as it might increase the first — and the overall effect is negative.\n\n**Lesson:** Under a hard wall-clock constraint, the optimal N is not \"maximize\" but \"fit within the time budget across all 50 problems.\" N=8 with early stopping appears near-optimal for a 17,400-second budget on this model and problem distribution.\n\n### 5.4 Finding 3: top_p=0.8 — No Measurable Effect\n\nv5 and v6 add `top_p=0.8` (not set in v1, which uses the vLLM default of 1.0). v6 (which fixes the bug in v5) scores 8/10 vs. 9/10 for v1. The single additional error is the n-Norwegian problem, which v1 also gets wrong. `top_p=0.8` does not detectably change accuracy for this model at T=1.0.\n\nThis is consistent with theoretical expectations: `min_p=0.02` already filters out very low-probability tokens; `top_p=0.8` at T=1.0 adds additional filtering of the low end of the distribution. For a model as large as gpt-oss-120b, the marginal tokens filtered by top_p=0.8 are unlikely to be relevant to mathematical reasoning quality.\n\n### 5.5 Finding 4: Missing Function Definition — Complete Failure (0/10)\n\nThe `baseline` and `v5` notebooks reference `compute_weighted_entropy()` in the voting code path, but the function is not defined in those versions. Every call falls through to the `return 0` fallback, producing all-zero scores regardless of model output.\n\nThe diagnosis required reading the exception traceback carefully — the model was generating valid answers, but the voting function silently returned 0 before they were compared. Fixing this by ensuring the entropy function is properly defined and wired into the voting path restored normal scoring.\n\n**Lesson:** Before any leaderboard submission, run the complete pipeline on at least one reference problem and verify that the voting function returns a finite, non-zero value and that the predicted answer matches the model's actual output.\n\n---\n\n## 6. Results\n\n### 6.1 Leaderboard Submission History\n\n| Submission | Version | Public LB | Key Difference from v1 |\n|---|---|---|---|\n| 1 | v1 | **44** | — (best config) |\n| 2 | v2 | **39** | 12 attempts, early_stop=5, T=0.8 |\n| 3 | v3 | **33** | V40 prompt, 20 attempts, 16 workers |\n| 4 | v1 | **42** | Re-submission (variance) |\n| 5 | v1 | **39** | Re-submission (variance) |\n\nThe two re-submissions of v1 scoring 42 (vs. the original 44) illustrate the run-to-run variance inherent in stochastic sampling at T=1.0. Without repeated runs, we cannot establish the true mean — 44 could be a favorable sample from a distribution centered around 39–40, or the configuration could have a genuine mean near 44. The two reference-set runs (both 9/10) provide weak evidence of stability on the reference problems, but cannot bound competition-set variance.\n\n### 6.2 Reference Set Results — v1 (9/10)\n\n| # | Problem Description | GT | Answer | Votes | Early Stop | Correct |\n|---|---|---|---|---|---|---|\n| 1 | 500×500 square, k rectangles | 520 | 520 | 4 | ✓ | ✓ |\n| 2 | Tournament, 2²⁰ runners | 21818 | 21818 | 4 | ✓ | ✓ |\n| 3 | f: Z≥1→Z≥1, coprime condition | 580 | 580 | 4 | ✓ | ✓ |\n| 4 | Acute triangle ABC, integer sides | 336 | 336 | 4 | ✓ | ✓ |\n| 5 | Alice & Bob sweets | 50 | 50 | 4 | ✓ | ✓ |\n| 6 | Ken blackboard, integer n | 32193 | 32193 | 4 | ✓ | ✓ |\n| 7 | f(n) = Σ gcd(i,n), i=1..n | 32951 | 32951 | 4 | ✓ | ✓ |\n| 8 | α: Z→Z, finitely nonzero | 160 | 160 | 4 | ✓ | ✓ |\n| 9 | Triangle ABC, circumcircle Ω | 57447 | 57447 | 4 | ✓ | ✓ |\n| 10 | n-Norwegian numbers | ? | 8687 | 1 | ✗ | ? |\n\nProblem 10 is the only one without early stop. The ground truth for the Norwegian problem in the reference set context may differ from what the writeup suggests — the community discussion indicates 8687 is a plausible answer for the specific parameterization of this problem.\n\n### 6.3 Per-Problem Compute Analysis\n\nA key finding from our per-problem analysis is the extreme variance in compute consumption:\n\n| Problem | Total Tokens | Relative Cost |\n|---|---|---|\n| Alice & Bob | 7,501 | 1× |\n| f(n) = Σgcd | 19,402 | 2.6× |\n| Ken blackboard | 24,125 | 3.2× |\n| Coprime f(580) | 31,525 | 4.2× |\n| Circumcircle | 62,328 | 8.3× |\n| 500×500 | 62,855 | 8.4× |\n| Triangle (336) | 59,553 | 7.9× |\n| Tournament | 75,327 | 10× |\n| α: Z→Z | 119,270 | 15.9× |\n| **n-Norwegian** | **322,515** | **43×** |\n\nThe n-Norwegian problem consumes 43× the compute of Alice & Bob and more than the next two hardest problems combined. Under a time budget, this problem represents a significant drain — if it appears early in the sequence, it leaves less budget for subsequent problems.\n\n### 6.4 Full Per-Problem Attempt Analysis (v1)\n\n#### Problem 2 — Tournament with 2²⁰ runners (correct)\n\n| Attempt | Tokens | Python Calls | Errors | Entropy | Answer |\n|---|---|---|---|---|---|\n| 1 | 14,287 | 15 | 2 | 0.813 | 21818 |\n| 2 | 14,756 | 16 | 1 | 0.887 | 21818 |\n| 3 | 15,259 | 5 | 0 | **0.938** | **62140** |\n| 4 | 15,316 | 13 | 2 | 0.854 | 21818 |\n| 5 | 15,709 | 16 | 3 | 0.822 | 21818 |\n\nAttempt 3 produces the wrong answer (62140) with the *highest* entropy in the group (0.938). Entropy weighting correctly reduces its influence: inverse weight 1/0.938 = 1.066 vs. 1/0.813 = 1.230 for the most confident correct attempt. Early stop at 5 correct votes. The entropy voting function performs exactly as designed here — the wrong answer comes from the least confident attempt.\n\n#### Problem 8 — α: Z→Z, finitely nonzero (correct, slow convergence)\n\n| Attempt | Tokens | Python Calls | Errors | Entropy | Answer |\n|---|---|---|---|---|---|\n| 1 | 7,601 | 0 | 0 | 0.861 | **2** |\n| 2 | 15,280 | 10 | 2 | 0.777 | 160 |\n| 3 | 16,385 | 11 | 3 | 0.814 | **114** |\n| 4 | 18,871 | 32 | 7 | 0.705 | 160 |\n| 5 | 16,921 | 23 | 5 | 0.780 | **266** |\n| 6 | 19,892 | 21 | 3 | 0.801 | 160 |\n| 7 | 24,320 | 24 | 1 | 0.808 | 160 |\n\nAttempt 1 reaches an answer (2) after only 7,601 tokens with 0 Python calls — the model jumped directly to a conclusion without exploration. This attempt has high entropy (0.861) and produces a wrong answer. Attempts 2, 4, 6, 7 all produce the correct answer (160) through extensive tool use (10–32 Python calls). Early stop at 7 correct votes. This illustrates why early stopping requires 4 *agreeing* votes rather than stopping after any 4 attempts — on this problem, the first attempt's fast-but-wrong answer would have derailed a less robust stopping criterion.\n\n#### Problem 10 — n-Norwegian (wrong, no convergence)\n\n| Attempt | Tokens | Python Calls | Errors | Entropy | Answer |\n|---|---|---|---|---|---|\n| 1 | 24,757 | 22 | 2 | 0.731 | 6825 |\n| 2 | 30,388 | 17 | 3 | 0.665 | 24433 |\n| 3 | 29,426 | 15 | 3 | 0.758 | 88272 |\n| 4 | 32,952 | 44 | 3 | 0.678 | 96985 |\n| 5 | 42,942 | 60 | 2 | 0.659 | 8687 |\n| 6 | 43,158 | 66 | 5 | 0.701 | 36162 |\n| 7 | 56,708 | 58 | 7 | 0.690 | NA |\n| 8 | 62,184 | 42 | 4 | 0.725 | NA |\n\nTotal tokens: 322,515 — 3–10× more than any other problem. All 6 non-NA answers are distinct. The model exhausts the full 8 attempts without any consensus. The model approaches the problem via different algorithmic paths in each attempt (different enumeration strategies, different edge-case handling), each confident in its own path, arriving at different wrong answers.\n\n**The critical observation: token entropy does not predict convergence failure.** The mean token entropy of Norwegian (0.701) is *lower* than the Tournament problem (0.863) — yet Tournament converges unanimously in 5 attempts while Norwegian produces 6 distinct answers. By token entropy alone, the model appears *more confident* on Norwegian than on Tournament. This dissociation reveals a phenomenon we call **confident divergence**: the model has multiple internally-consistent but mutually-incompatible solution paths. Each attempt confidently follows one path to its conclusion — low token entropy throughout — but different attempts follow different paths.\n\nThis finding has a direct implication: entropy-weighted voting correctly downweights *uncertain* attempts (high entropy), but cannot detect *confidently wrong* attempts that take different wrong paths. A complementary signal — answer-level diversity across attempts — would detect this case and flag the problem as requiring more attempts or a verifier.\n\nThe n-Norwegian problem also illustrates the practical compute cost of this failure mode: 322,515 tokens consumed without any useful signal, versus 75,327 for Tournament (which resolved correctly). Under a fixed time budget, this represents a 4× compute drain for a problem that entropy-voting has no way to identify as harder in advance.\n\n### 6.5 Cross-Run Stability Analysis\n\nWe executed the reference set twice with different problem orderings. Results:\n\n| Problem | Run 1 Answer | Run 2 Answer | Consistent | Both Correct |\n|---|---|---|---|---|\n| 500×500 square | 520 | 520 | ✓ | ✓ |\n| Tournament | 21818 | 21818 | ✓ | ✓ |\n| Coprime f(580) | 580 | 580 | ✓ | ✓ |\n| Triangle (336) | 336 | 336 | ✓ | ✓ |\n| Alice & Bob | 50 | 50 | ✓ | ✓ |\n| Ken blackboard | 32193 | 32193 | ✓ | ✓ |\n| f(n) = Σgcd | 32951 | 32951 | ✓ | ✓ |\n| α: Z→Z | 160 | 160 | ✓ | ✓ |\n| Circumcircle | 57447 | 57447 | ✓ | ✓ |\n| n-Norwegian | 8687 | 31329 | ✗ | ? |\n\n9 of 10 problems produce identical answers across both runs, with early stopping triggered in all 9. The n-Norwegian problem diverges — Run 1 produces 8687 (1 vote of 6 valid attempts), Run 2 produces 31329 (1 vote of 3 valid attempts with 5 returning NA). The different orderings affected GPU state and memory allocation, leaving fewer tokens available for later problems in Run 2, which is why Norwegian (appearing 4th in Run 2 vs. 10th in Run 1) has more NA attempts in Run 2.\n\nThis stability analysis has an important implication: **the notebook's variance is concentrated in the n-Norwegian problem**. The other 9 problems are stable enough that running twice with different orderings makes no difference. For the private test set, we expect a similar partition: most problems will produce consistent answers regardless of problem order, and a small number of genuinely hard problems will dominate the score variance.\n\n---\n\n## 7. Limitations\n\n**Single competition submission for the best configuration.** We submitted v1 once and obtained 44. Two re-submissions of the same notebook scored 35 and 35. Without more repeated submissions we cannot determine whether 44 is the configuration's true mean or a favorable tail. The reference-set stability (9/10 consistent) suggests stability on problems with signal, but competition-set variance is unknown.\n\n**Confounded ablations.** v3 changes prompt style, temperature, attempt count, workers, early_stop, voting function, and batch_size simultaneously. v2 changes temperature (1.0→0.8), attempt count (8→12), early_stop (4→5), system prompt wording, and per-turn token cap simultaneously — `temperature_secondary = 1.2` was declared in v2's CFG but never passed to `completions.create`, so all v2 attempts ran at T=0.8. No ablation in our experiment sequence changes exactly one variable. Clean single-variable ablations were not feasible within the 7-day, 5-submission constraint.\n\n**workers=8 vs. standard 16 may explain variance.** With attempts=8 and workers=8, every running attempt occupies exactly one kernel — there is no buffer for kernel startup latency or slow execution. A kernel that takes 2+ seconds to return a code result directly delays the next code cell in that attempt. We observed no timeouts attributable to this, but the pattern of scores for our v1 config (44, 35, 35) contrasts with merkiraz's similar config using workers=16 and batch_size=256 (44, 42, 42, std≈1.2). The tighter worker pool may amplify infrastructure variance under different GPU load conditions, explaining the wider spread in our observed scores.\n\n**batch_size=128 vs. community standard 256.** Lower batch size may reduce vLLM server throughput when multiple attempts request completions simultaneously. Combined with the verbose prompt (more tokens per completion), this could increase per-problem latency slightly. This is another dimension where our config differs from configurations that showed lower variance.\n\n**No external answer verification.** Our system has no mechanism to verify candidate answers against the problem's mathematical constraints before committing. The n-Norwegian problem is the clearest demonstration of this gap: a verifier that re-executed the model's enumeration code and checked whether the output satisfies the three-distinct-divisors property would catch many of the wrong answers before they enter the vote.\n\n**Note on entropy as a signal.** The AMO system (David Babu et al. [6]) reports that token entropy added noise in their pipeline — \"entropy had only a weak correlation to correctness\" in their Python-tooled traces. Our finding that entropy correctly downweighted the wrong answer in Tournament (Section 6.4, Attempt 3: entropy 0.938, answer 62140 wrong) may reflect a different configuration: our system uses simpler, shorter traces than AMO's multi-agent pipeline. The entropy–convergence dissociation we document (Norwegian vs Tournament) is consistent with both findings — entropy works within a single attempt but cannot predict cross-attempt convergence.\n\n---\n\n## 8. Lessons Learned\n\n**Token entropy and answer convergence are different signals.** Mean token entropy measures local confidence at each decoding step. It does not measure whether different attempts will converge to the same answer. The n-Norwegian problem (entropy 0.701) looks more confident than Tournament (entropy 0.863) by this metric, yet it fails completely. An answer-diversity signal — tracking how many distinct answers appear across attempts — would catch this failure mode that entropy alone misses.\n\n**Verify the voting function end-to-end before submitting.** The baseline and v5 notebooks failed completely (0/10) due to a missing function definition. A 30-second local test on one reference problem would have caught this before consuming a submission slot.\n\n**Respect the hard time budget.** Every increase in attempts-per-problem reduces the fraction of problems that receive adequate compute. The improvement from N=8 to N=20 in per-problem expected accuracy is smaller than the degradation from problems timing out. The cliff is hard: a timed-out problem returns 0, not a partial credit.\n\n**Convergence voting is fragile.** Entropy-weighted majority voting requires a threshold count of agreeing answers — it is robust to a minority of wrong attempts. Convergence-based methods stabilize around whatever answer appears first, making them vulnerable to early noise. For a problem distribution where hard problems have diverse answers, majority voting is strongly preferred.\n\n**Compute variance is concentrated in hard problems.** The n-Norwegian problem consumes 43× more tokens than the average problem. Under a fixed time budget, these outlier problems drain compute that could be allocated to other problems. An adaptive system that detects high-token-consumption problems early and reduces their budget would improve overall efficiency.\n\n**EOS errors are recoverable and worth recovering.** Without retry logic, approximately 13 attempt-slots were silently discarded in Run 1. With retry (overhead: 1–7 seconds per recovered attempt), all 13 recovered correctly. The implementation is simple and the benefit is concrete.\n\n---\n\n## 9. Conclusion\n\nWe presented a 7-day participation in AIMO3 achieving 44/50 (top 14 of 4,133 teams) through targeted inference engineering. The core system — 8 parallel tool-integrated reasoning attempts with entropy-weighted majority voting, adaptive time budgeting, EOS-resilient retry, and early stopping — is stable across two reference runs with different problem orderings: 9 of 10 problems produce identical correct answers, with variance concentrated entirely in one problem where the model produces no consensus at N=8.\n\nFour experiments across 8 notebook versions yield clear negative results: convergence voting catastrophically degrades performance (2/10 vs. 9/10); increasing attempt count under a fixed time budget hurts public LB score; top_p=0.8 has no detectable effect; and a missing function definition causes complete failure. These negative results are reproducible from the source notebooks provided with this writeup.\n\nThe most important empirical finding is the dissociation between token-level entropy and answer convergence. The n-Norwegian problem has lower mean token entropy (0.701) than the Tournament problem (0.863), yet Norwegian fails completely while Tournament converges in 5 attempts. This \"confident divergence\" — where the model is locally confident at each step but globally takes a different wrong path each attempt — is invisible to entropy-weighted voting. Entropy voting correctly handles uncertain attempts; it cannot handle confidently-wrong divergent ones. Answer-level diversity monitoring is the missing signal, and building it into the voting function is the most important direction for future work.\n\n---\n\n## References\n\n[1] Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A., & Zhou, D. (2023). Self-consistency improves chain of thought reasoning in language models. *ICLR 2023*. arXiv:2203.11171\n\n[2] Kwon, W., Li, Z., Zhuang, S., Sheng, Y., Zheng, L., Yu, C. H., Gonzalez, J. E., Zhang, H., & Stoica, I. (2023). Efficient memory management for large language model serving with PagedAttention. *SOSP 2023*.\n\n[3] Gou, Z., Shao, Z., Gong, Y., Yang, Y., Huang, M., Duan, N., Chen, W., & Zhang, T. (2023). ToRA: A tool-integrated reasoning agent for mathematical problem solving. arXiv:2309.17452\n\n[4] Moshkov, I., et al. (2025). AIMO-2 winning solution: Building state-of-the-art mathematical reasoning models with OpenMathReasoning dataset. arXiv:2504.16891\n\n[5] Frieder, S., et al. (2025). AI Mathematical Olympiad — Progress Prize 3. Kaggle Competition. https://kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3\n\n[6] David Babu et al. (2026). AMO: Agentic Math Orchestrator for Olympiad Mathematics. AIMO3 Writeup, Kaggle.\n\n[7] Nitarach, N. (2026). Model Capability Dominates: Inference-Time Optimization Lessons from AIMO 3. arXiv:2603.27844\n\n---\n\n## Appendix A: Full Configuration — v1 (Best Submission)\n\n```python\nclass CFG:\n    system_prompt = (\n        'You are an elite mathematical problem solver with expertise at the International '\n        'Mathematical Olympiad (IMO) level. Your goal is to find the correct answer through '\n        'rigorous mathematical reasoning.\\n\\n'\n        '# Problem-Solving Approach:\\n'\n        '1. UNDERSTAND: Carefully read the problem. Identify what is given, '\n        'what needs to be found, and constraints.\\n'\n        '2. EXPLORE: Consider multiple solution strategies before committing to one.\\n'\n        '3. PLAN: Outline key steps of the most promising approach.\\n'\n        '4. EXECUTE: Work through the solution methodically with clear reasoning.\\n'\n        '5. VERIFY: Check your answer using substitution, edge cases, '\n        'or alternative methods.\\n\\n'\n        '# Output Format:\\n'\n        'The final answer must be a non-negative integer between 0 and 99999.\\n'\n        'Place your final numerical answer inside \\\\boxed{}, e.g., \\\\boxed{42}\\n\\n'\n        'Think step-by-step. Quality of reasoning is as important as the final answer.'\n    )\n    tool_prompt = (\n        'Use this tool to execute Python code for:\\n'\n        '- Complex or error-prone calculations\\n'\n        '- Numerical verification of analytical results\\n'\n        '- Testing conjectures or brute-force checking small cases\\n\\n'\n        'The environment is a stateful Jupyter notebook. Code persists between executions.\\n'\n        'Always use print() to display results.\\n\\n'\n        'Code should support your reasoning, not replace it.'\n    )\n    preference_prompt = (\n        'You have access to `math`, `numpy`, `sympy`, and `mpmath`. '\n        'Use sympy for exact symbolic answers, numpy for numerical work, '\n        'and mpmath for high-precision arithmetic when needed.'\n    )\n    # Model\n    served_model_name      = 'gpt-oss'\n    model_path             = '/kaggle/input/models/danielhanchen/gpt-oss-120b/transformers/default/1'\n    # vLLM\n    dtype                  = 'auto'\n    kv_cache_dtype         = 'fp8_e4m3'\n    gpu_memory_utilization = 0.95\n    context_tokens         = 65536\n    batch_size             = 128\n    stream_interval        = 200\n    # Timing\n    notebook_limit         = 17400\n    high_problem_timeout   = 900\n    base_problem_timeout   = 300\n    server_timeout         = 180\n    session_timeout        = 960\n    jupyter_timeout        = 8\n    sandbox_timeout        = 3\n    # Solver\n    attempts               = 8\n    turns                  = 128\n    workers                = 8\n    early_stop             = 4\n    seed                   = 42\n    # Sampling\n    temperature            = 1.0\n    min_p                  = 0.02\n    top_logprobs           = 5\n    buffer_tokens          = 512\n    search_tokens          = 32\n```\n\n## Appendix B: Notebook Version Summary\n\n| Filename | Description | Local /10 | LB |\n|---|---|---|---|\n| `baseline.ipynb` | First version; `compute_weighted_entropy` undefined → bug | 0 | — |\n| `v1.ipynb` | Full reference run; verbose prompt; mean entropy voting | **9/10** | **44** |\n| `v2.ipynb` | 12 attempts, early_stop=5, T=0.8/1.2 dual temperature | — | 39 |\n| `v3.ipynb` | V40 prompt, 20 attempts, 16 workers | — | 33 |\n| `v4.ipynb` | V40 + ensemble convergence voting, 20 attempts | **2/10** | 35 |\n| `v5.ipynb` | Verbose, top_p=0.8; bug present | 0 | 39 |\n| `v6.ipynb` | Verbose, top_p=0.8, 5-component entropy voting | **8/10** |  |\n\nv1 is the only version submitted to the leaderboard (scored 44, 35, 35 across three runs).\n\n## Appendix C: Answer Extraction Logic\n\n```python\npatterns = [\n    r'\\\\boxed\\s*\\{\\s*([0-9,]+)\\s*\\}',        # \\boxed{N}\n    r'\\\\\\\\boxed\\s*\\{\\s*([0-9,]+)\\s*\\}',      # \\\\boxed{N} (escaped)\n    r'final\\s+answer\\s+is\\s*:?\\s*([0-9,]+)', # \"final answer is N\"\n    r'answer\\s*[:=]\\s*([0-9,]+)',             # \"answer: N\" or \"answer = N\"\n]\n# Scan last search_tokens=32 chunks of streamed text\n# Use last match (reversed order) to prefer the model's most recent answer\n# Validate: 0 ≤ value ≤ 99999\n```\n\n## Appendix D: vLLM Launch Command\n\n```bash\npython -m vllm.entrypoints.openai.api_server \\\n    --seed 42 \\\n    --model /kaggle/input/models/danielhanchen/gpt-oss-120b/transformers/default/1 \\\n    --served-model-name gpt-oss \\\n    --tensor-parallel-size 1 \\\n    --max-num-seqs 128 \\\n    --gpu-memory-utilization 0.95 \\\n    --host 0.0.0.0 --port 8000 \\\n    --dtype auto \\\n    --kv-cache-dtype fp8_e4m3 \\\n    --max-model-len 65536 \\\n    --stream-interval 200 \\\n    --async-scheduling \\\n    --disable-log-stats \\\n    --enable-prefix-caching \\\n    --trust-remote-code\n```\n\nNote: `--enable-auto-tool-choice` and `--tool-call-parser pythonic` are deliberately excluded. These flags configure vLLM's native tool-call parsing layer, which is incompatible with `openai_harmony`'s custom encoding. Including them causes tool calls to be silently mis-parsed, producing empty responses and infinite reasoning loops.\n",
      "votes": 5
    },
    {
      "id": 3458325,
      "postDate": "2026-05-15T16:20:21.543Z",
      "content": "<p>Following up on the questions from <a href=\"https://www.kaggle.com/philipvonderlind\" target=\"_blank\">@philipvonderlind</a>, here are some additional questions to help us assess your submission:</p>\n<ol>\n<li><strong>Compute signature as difficulty signal:</strong> The Norwegian problem consumes 43× the average compute (322k vs 7.5k tokens) and is also where the cross-run 9/10 stability breaks. Could a running token-count signal after the first 1-2 attempts be used as an early difficulty flag, triggering more budget or extra attempts before the vote commits? What would you propose for this in practice?</li>\n<li><strong>Is detecting confident divergence useful:</strong> You propose answer-level diversity monitoring as the missing signal that entropy can't catch (Norwegian's 6 distinct answers across 8 attempts). But if 8 attempts produce that many distinct answers, it may just indicate the model fundamentally can't solve the problem within budget. Is there reason to believe interventions triggered by this signal (more attempts, verifier injection) would actually recover the correct answer, rather than just generating more wrong answers?</li>\n</ol>\n<p>Look forward to reading your responses on these.</p>",
      "rawMarkdown": "Following up on the questions from @philipvonderlind, here are some additional questions to help us assess your submission:\n\n1. **Compute signature as difficulty signal:** The Norwegian problem consumes 43× the average compute (322k vs 7.5k tokens) and is also where the cross-run 9/10 stability breaks. Could a running token-count signal after the first 1-2 attempts be used as an early difficulty flag, triggering more budget or extra attempts before the vote commits? What would you propose for this in practice?\n2. **Is detecting confident divergence useful:** You propose answer-level diversity monitoring as the missing signal that entropy can't catch (Norwegian's 6 distinct answers across 8 attempts). But if 8 attempts produce that many distinct answers, it may just indicate the model fundamentally can't solve the problem within budget. Is there reason to believe interventions triggered by this signal (more attempts, verifier injection) would actually recover the correct answer, rather than just generating more wrong answers?\n\nLook forward to reading your responses on these.",
      "replies": [
        {
          "id": 3459144,
          "postDate": "2026-05-17T11:38:23.737Z",
          "content": "<p>Hi Sam, thank you for the follow-up questions. These are exactly the two open problems that I think matter most after the writeup: whether compute usage can be turned into an online routing signal, and whether answer-level diversity is useful when the model may simply be unable to solve the problem.</p>\n<h3>1. Could a running token-count signal after the first 1–2 attempts be used as an early difficulty flag?</h3>\n<p>Yes. I think the evidence in the writeup supports this, but I would use the signal for <strong>routing and budget protection</strong>, not simply for \"more attempts.\"</p>\n<p>In Section 6.3, the Norwegian problem is the clear compute outlier:</p>\n<table>\n<thead>\n<tr>\n<th>Problem</th>\n<th>Total tokens</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Alice &amp; Bob</td>\n<td>7,501</td>\n</tr>\n<tr>\n<td>f(n) = Σgcd</td>\n<td>19,402</td>\n</tr>\n<tr>\n<td>Ken blackboard</td>\n<td>24,125</td>\n</tr>\n<tr>\n<td>Coprime f(580)</td>\n<td>31,525</td>\n</tr>\n<tr>\n<td>Triangle</td>\n<td>59,553</td>\n</tr>\n<tr>\n<td>Circumcircle</td>\n<td>62,328</td>\n</tr>\n<tr>\n<td>500×500</td>\n<td>62,855</td>\n</tr>\n<tr>\n<td>Tournament</td>\n<td>75,327</td>\n</tr>\n<tr>\n<td>α: Z→Z</td>\n<td>119,270</td>\n</tr>\n<tr>\n<td>n-Norwegian</td>\n<td>322,515</td>\n</tr>\n</tbody>\n</table>\n<p>Norwegian used about 322k tokens — far more than any other reference problem. It also failed to produce strong answer consensus in the run analyzed in Section 6.4. That means the difficulty signal is not only visible after the full run; it likely starts appearing after the first 1–2 completed attempts.</p>\n<p>A practical online monitor could track:</p>\n<pre><code># Evaluated after first 2 completed attempts\n\nvalid_answers = [a for a in answers if a is not None]\n\nmedian_tokens  = median(tokens_per_attempt_so_far)\ndistinct_count = len(set(valid_answers))\nmax_vote       = max(Counter(valid_answers).values(), default=0)\nvalid_rate     = len(valid_answers) / completed_attempts\n\nhigh_cost    = median_tokens &gt; 20_000\nno_consensus = len(valid_answers) &gt;= 2 and distinct_count == len(valid_answers)\n\nis_unstable = high_cost and no_consensus\n</code></pre>\n<p>The threshold <code>20_000</code> is not meant to be universal — it is a reference-set heuristic. The right value should be calibrated from more runs. The important point is the <strong>combination</strong> of two signals: high per-attempt token usage <strong>and</strong> no answer agreement. A problem can be expensive and still worth continuing if the answers are converging. The danger case is expensive <strong>and</strong> diverse.</p>\n<p>I would use the signal as a routing table:</p>\n<table>\n<thead>\n<tr>\n<th>Observed after 1–2 attempts</th>\n<th>Interpretation</th>\n<th>Action</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Low token usage + agreement</td>\n<td>Easy, stable</td>\n<td>Early stop as soon as threshold is met</td>\n</tr>\n<tr>\n<td>High token usage + agreement emerging</td>\n<td>Hard but converging</td>\n<td>Allow full budget, continue normally</td>\n</tr>\n<tr>\n<td>High token usage + all answers distinct</td>\n<td>Unstable / confident divergence</td>\n<td>Switch strategy or cap budget</td>\n</tr>\n<tr>\n<td>High NA / invalid rate</td>\n<td>Timeout or infrastructure risk</td>\n<td>Reduce spending or skip</td>\n</tr>\n</tbody>\n</table>\n<p>The most important practical constraint is that the <strong>global time budget dominates</strong>. Section 5.3 of the writeup shows that increasing attempts under a fixed wall-clock budget can reduce public LB score because later problems get starved. So if a problem is flagged as unstable, I would not automatically give it more attempts. Instead, I would route it to one of two branches:</p>\n<p><strong>Branch A — enough global time remains</strong></p>\n<p>Use a targeted intervention rather than another full solve:</p>\n<ul>\n<li>run a verifier pass on the top candidate answers;</li>\n<li>ask the model to compare competing derivations and identify where they diverge;</li>\n<li>run a problem-specific checker if the structure permits it.</li>\n</ul>\n<p><strong>Branch B — global time is tight</strong></p>\n<p>Cap the budget and move on:</p>\n<ul>\n<li>avoid spending 300k+ tokens on a problem with no consensus;</li>\n<li>preserve time for later problems where early agreement is more likely;</li>\n<li>return the best available answer, flagged internally as low-consensus.</li>\n</ul>\n<p>So the correct framing is not:</p>\n<blockquote>\n  <p>detect hard problem → spend more</p>\n</blockquote>\n<p>It is:</p>\n<blockquote>\n  <p>detect expensive + non-convergent problem → either verify differently or stop wasting budget</p>\n</blockquote>\n<p>That is the main engineering lesson I would take from the Norwegian problem.</p>\n<hr>\n<h3>2. Is detecting confident divergence useful if 8 distinct answers may mean the model cannot solve the problem?</h3>\n<p>I agree with the concern. If 8 attempts produce many distinct answers, there is no guarantee that attempts 9 or 10 will recover the correct answer. The Norwegian analysis suggests that simply increasing N is likely the wrong intervention.</p>\n<p>The reason I still think detecting confident divergence is useful is that it improves <strong>calibration</strong> even when it does not improve <strong>recovery</strong>.</p>\n<p>The failure mode in the writeup is:</p>\n<ul>\n<li>token entropy says: the model seems confident</li>\n<li>answer diversity says: the attempts do not agree at all</li>\n</ul>\n<p>As Section 6.4 documents, Norwegian has <em>lower</em> mean token entropy (0.701) than Tournament (0.863), yet Tournament converges unanimously while Norwegian produces 6 distinct answers. Token entropy and answer convergence are measuring different things:</p>\n<table>\n<thead>\n<tr>\n<th>Signal</th>\n<th>What it measures</th>\n<th>Failure case</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Token entropy</td>\n<td>Local confidence during generation</td>\n<td>Model is confidently following a wrong path</td>\n</tr>\n<tr>\n<td>Answer consensus</td>\n<td>Agreement across attempts</td>\n<td>Model produces many incompatible answers</td>\n</tr>\n<tr>\n<td>Token usage</td>\n<td>Compute cost / difficulty signature</td>\n<td>Model spends large budget without convergence</td>\n</tr>\n</tbody>\n</table>\n<p>Entropy-weighted voting can downweight hesitant attempts. It cannot detect a set of confident but mutually inconsistent attempts. That is why answer-level diversity is a complementary signal.</p>\n<p>A concrete divergence monitor:</p>\n<pre><code>valid_answers = [a for a in answers if a is not None]\nvalid_N       = len(valid_answers)\n\nmax_vote_count  = max(Counter(valid_answers).values(), default=0)\ndistinct_count  = len(set(valid_answers))\n\nconsensus    = max_vote_count / valid_N if valid_N else 0\ndiversity    = distinct_count / valid_N if valid_N else 1\nmean_entropy = mean(entropies)\n\nconfident_divergence = (\n    valid_N &gt;= 4\n    and consensus  &lt;= 0.25\n    and diversity  &gt;= 0.75\n    and mean_entropy &lt; entropy_threshold   # locally confident\n)\n</code></pre>\n<p>The thresholds should be calibrated from more runs. The qualitative condition is: <strong>low entropy + high diversity = locally confident, globally inconsistent</strong>.</p>\n<p>When this is detected, I would not trust the normal entropy-weighted vote and would instead trigger one of the following actions, in order of preference:</p>\n<p><strong>Action 1 — Candidate verification</strong></p>\n<p>Take the top-2 or top-3 candidate answers and ask the model to check each against the problem's defining constraints. This is structurally easier than re-deriving from scratch — the model only needs to discriminate between candidates rather than reconstruct a full solution path.</p>\n<p><strong>Action 2 — Solution-path comparison</strong></p>\n<p>Ask the model to compare the assumptions behind two conflicting derivations and identify where they diverge. This targets the divergence directly rather than ignoring it.</p>\n<p><strong>Action 3 — Executable checker</strong></p>\n<p>When the problem structure permits it (number theory, combinatorics), write code to test the defining property on candidate answers. Not always feasible for IMO-level problems, but when available it is a better use of compute than another full reasoning attempt.</p>\n<p><strong>Action 4 — Budget protection</strong></p>\n<p>If verification is not feasible and time is tight, stop spending. Return the current best answer flagged as low-consensus and preserve budget for downstream problems.</p>\n<p>This is why detecting confident divergence is useful even when the model cannot reliably recover. It lets the solver distinguish between:</p>\n<table>\n<thead>\n<tr>\n<th>Case</th>\n<th>Example behavior</th>\n<th>How to treat answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Stable majority</td>\n<td>4+ attempts agree on same answer</td>\n<td>High confidence</td>\n</tr>\n<tr>\n<td>Uncertain minority</td>\n<td>One high-entropy outlier</td>\n<td>Downweight by entropy</td>\n</tr>\n<tr>\n<td>Confident divergence</td>\n<td>Many low-entropy distinct answers</td>\n<td>Low confidence despite entropy</td>\n</tr>\n<tr>\n<td>No valid answers</td>\n<td>NA / timeouts throughout</td>\n<td>Fallback / budget cap</td>\n</tr>\n</tbody>\n</table>\n<p>The Norwegian problem sits in the third category.</p>\n<p>The cross-run stability analysis in Section 6.5 supports this interpretation. The same <code>v1</code> configuration was stable on 9 of 10 reference problems across two independent runs, while Norwegian changed between runs — one run selected the reference answer 8687, another selected a different answer. This suggests the model can sometimes reach the correct answer, but the standard voting signal is not reliable enough to know when it has done so. Detecting divergence would at minimum flag the returned answer as unreliable rather than giving it the same apparent confidence as a stable 4-vote majority.</p>\n<p>To summarize:</p>\n<ul>\n<li><strong>If the question is \"would diversity detection guarantee recovery?\"</strong> — no.</li>\n<li><strong>If the question is \"would diversity detection make the system better calibrated and more budget-aware?\"</strong> — yes.</li>\n</ul>\n<p>The practical intervention should be verification, candidate comparison, or budget capping — not blindly increasing attempts.</p>\n<p>In hindsight, the voting layer should have used at least four signals together:</p>\n<pre><code>confidence = 1 / mean_token_entropy      # local confidence per attempt\nconsensus  = max_vote_count / valid_N    # cross-attempt agreement\ndiversity  = distinct_answers / valid_N  # cross-attempt disagreement\ncost       = tokens_used_so_far          # budget pressure\n</code></pre>\n<p>The submitted pipeline used entropy and majority voting but did not explicitly track answer diversity or token-cost routing. That is the main change I would make in a next version.</p>",
          "rawMarkdown": "Hi Sam, thank you for the follow-up questions. These are exactly the two open problems that I think matter most after the writeup: whether compute usage can be turned into an online routing signal, and whether answer-level diversity is useful when the model may simply be unable to solve the problem.\n\n### 1. Could a running token-count signal after the first 1–2 attempts be used as an early difficulty flag?\n\nYes. I think the evidence in the writeup supports this, but I would use the signal for **routing and budget protection**, not simply for \"more attempts.\"\n\nIn Section 6.3, the Norwegian problem is the clear compute outlier:\n\n| Problem | Total tokens |\n|---|---:|\n| Alice & Bob | 7,501 |\n| f(n) = Σgcd | 19,402 |\n| Ken blackboard | 24,125 |\n| Coprime f(580) | 31,525 |\n| Triangle | 59,553 |\n| Circumcircle | 62,328 |\n| 500×500 | 62,855 |\n| Tournament | 75,327 |\n| α: Z→Z | 119,270 |\n| n-Norwegian | 322,515 |\n\nNorwegian used about 322k tokens — far more than any other reference problem. It also failed to produce strong answer consensus in the run analyzed in Section 6.4. That means the difficulty signal is not only visible after the full run; it likely starts appearing after the first 1–2 completed attempts.\n\nA practical online monitor could track:\n\n```python\n# Evaluated after first 2 completed attempts\n\nvalid_answers = [a for a in answers if a is not None]\n\nmedian_tokens  = median(tokens_per_attempt_so_far)\ndistinct_count = len(set(valid_answers))\nmax_vote       = max(Counter(valid_answers).values(), default=0)\nvalid_rate     = len(valid_answers) / completed_attempts\n\nhigh_cost    = median_tokens > 20_000\nno_consensus = len(valid_answers) >= 2 and distinct_count == len(valid_answers)\n\nis_unstable = high_cost and no_consensus\n```\n\nThe threshold `20_000` is not meant to be universal — it is a reference-set heuristic. The right value should be calibrated from more runs. The important point is the **combination** of two signals: high per-attempt token usage **and** no answer agreement. A problem can be expensive and still worth continuing if the answers are converging. The danger case is expensive **and** diverse.\n\nI would use the signal as a routing table:\n\n| Observed after 1–2 attempts | Interpretation | Action |\n|---|---|---|\n| Low token usage + agreement | Easy, stable | Early stop as soon as threshold is met |\n| High token usage + agreement emerging | Hard but converging | Allow full budget, continue normally |\n| High token usage + all answers distinct | Unstable / confident divergence | Switch strategy or cap budget |\n| High NA / invalid rate | Timeout or infrastructure risk | Reduce spending or skip |\n\nThe most important practical constraint is that the **global time budget dominates**. Section 5.3 of the writeup shows that increasing attempts under a fixed wall-clock budget can reduce public LB score because later problems get starved. So if a problem is flagged as unstable, I would not automatically give it more attempts. Instead, I would route it to one of two branches:\n\n**Branch A — enough global time remains**\n\nUse a targeted intervention rather than another full solve:\n- run a verifier pass on the top candidate answers;\n- ask the model to compare competing derivations and identify where they diverge;\n- run a problem-specific checker if the structure permits it.\n\n**Branch B — global time is tight**\n\nCap the budget and move on:\n- avoid spending 300k+ tokens on a problem with no consensus;\n- preserve time for later problems where early agreement is more likely;\n- return the best available answer, flagged internally as low-consensus.\n\nSo the correct framing is not:\n\n> detect hard problem → spend more\n\nIt is:\n\n> detect expensive + non-convergent problem → either verify differently or stop wasting budget\n\nThat is the main engineering lesson I would take from the Norwegian problem.\n\n---\n\n### 2. Is detecting confident divergence useful if 8 distinct answers may mean the model cannot solve the problem?\n\nI agree with the concern. If 8 attempts produce many distinct answers, there is no guarantee that attempts 9 or 10 will recover the correct answer. The Norwegian analysis suggests that simply increasing N is likely the wrong intervention.\n\nThe reason I still think detecting confident divergence is useful is that it improves **calibration** even when it does not improve **recovery**.\n\nThe failure mode in the writeup is:\n\n- token entropy says: the model seems confident\n- answer diversity says: the attempts do not agree at all\n\nAs Section 6.4 documents, Norwegian has *lower* mean token entropy (0.701) than Tournament (0.863), yet Tournament converges unanimously while Norwegian produces 6 distinct answers. Token entropy and answer convergence are measuring different things:\n\n| Signal | What it measures | Failure case |\n|---|---|---|\n| Token entropy | Local confidence during generation | Model is confidently following a wrong path |\n| Answer consensus | Agreement across attempts | Model produces many incompatible answers |\n| Token usage | Compute cost / difficulty signature | Model spends large budget without convergence |\n\nEntropy-weighted voting can downweight hesitant attempts. It cannot detect a set of confident but mutually inconsistent attempts. That is why answer-level diversity is a complementary signal.\n\nA concrete divergence monitor:\n\n```python\nvalid_answers = [a for a in answers if a is not None]\nvalid_N       = len(valid_answers)\n\nmax_vote_count  = max(Counter(valid_answers).values(), default=0)\ndistinct_count  = len(set(valid_answers))\n\nconsensus    = max_vote_count / valid_N if valid_N else 0\ndiversity    = distinct_count / valid_N if valid_N else 1\nmean_entropy = mean(entropies)\n\nconfident_divergence = (\n    valid_N >= 4\n    and consensus  <= 0.25\n    and diversity  >= 0.75\n    and mean_entropy < entropy_threshold   # locally confident\n)\n```\n\nThe thresholds should be calibrated from more runs. The qualitative condition is: **low entropy + high diversity = locally confident, globally inconsistent**.\n\nWhen this is detected, I would not trust the normal entropy-weighted vote and would instead trigger one of the following actions, in order of preference:\n\n**Action 1 — Candidate verification**\n\nTake the top-2 or top-3 candidate answers and ask the model to check each against the problem's defining constraints. This is structurally easier than re-deriving from scratch — the model only needs to discriminate between candidates rather than reconstruct a full solution path.\n\n**Action 2 — Solution-path comparison**\n\nAsk the model to compare the assumptions behind two conflicting derivations and identify where they diverge. This targets the divergence directly rather than ignoring it.\n\n**Action 3 — Executable checker**\n\nWhen the problem structure permits it (number theory, combinatorics), write code to test the defining property on candidate answers. Not always feasible for IMO-level problems, but when available it is a better use of compute than another full reasoning attempt.\n\n**Action 4 — Budget protection**\n\nIf verification is not feasible and time is tight, stop spending. Return the current best answer flagged as low-consensus and preserve budget for downstream problems.\n\nThis is why detecting confident divergence is useful even when the model cannot reliably recover. It lets the solver distinguish between:\n\n| Case | Example behavior | How to treat answer |\n|---|---|---|\n| Stable majority | 4+ attempts agree on same answer | High confidence |\n| Uncertain minority | One high-entropy outlier | Downweight by entropy |\n| Confident divergence | Many low-entropy distinct answers | Low confidence despite entropy |\n| No valid answers | NA / timeouts throughout | Fallback / budget cap |\n\nThe Norwegian problem sits in the third category.\n\nThe cross-run stability analysis in Section 6.5 supports this interpretation. The same `v1` configuration was stable on 9 of 10 reference problems across two independent runs, while Norwegian changed between runs — one run selected the reference answer 8687, another selected a different answer. This suggests the model can sometimes reach the correct answer, but the standard voting signal is not reliable enough to know when it has done so. Detecting divergence would at minimum flag the returned answer as unreliable rather than giving it the same apparent confidence as a stable 4-vote majority.\n\nTo summarize:\n\n- **If the question is \"would diversity detection guarantee recovery?\"** — no.\n- **If the question is \"would diversity detection make the system better calibrated and more budget-aware?\"** — yes.\n\nThe practical intervention should be verification, candidate comparison, or budget capping — not blindly increasing attempts.\n\nIn hindsight, the voting layer should have used at least four signals together:\n\n```python\nconfidence = 1 / mean_token_entropy      # local confidence per attempt\nconsensus  = max_vote_count / valid_N    # cross-attempt agreement\ndiversity  = distinct_answers / valid_N  # cross-attempt disagreement\ncost       = tokens_used_so_far          # budget pressure\n```\n\nThe submitted pipeline used entropy and majority voting but did not explicitly track answer diversity or token-cost routing. That is the main change I would make in a next version."
        }
      ]
    },
    {
      "id": 3457719,
      "postDate": "2026-05-14T08:25:41.663Z",
      "content": "<p>Hi, thank you for your submission to the Writeup Prize. <a href=\"https://www.kaggle.com/sambealing\" target=\"_blank\">@sambealing</a> and I will post some questions below that help us in assessing your submission more closely, as described in the <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/discussion/689703\" target=\"_blank\">updated discussion post</a>.</p>\n<p>I have a few questions regarding your work:</p>\n<ol>\n<li><p><strong>Comparison to Public Notebook</strong>: Some parts of your submission appear similar to the public notebook shared in the discussion, which many participants used as a starting point. While building on others' work is certainly encouraged, it would be helpful if you could cite the original notebook, include a link to it, and clearly describe which parts you adapted, as well as the motivation behind each change.</p></li>\n<li><p><strong>Plots</strong>: Adding plots to summarize your results, especially the ensemble consensus mechanism, would improve both the readability and presentation of your work. For example, it would be useful to include plots comparing the performance of all ablations on both the public leaderboard and your local evaluation set.</p></li>\n<li><p><strong>Experiment Construction</strong>: In many of your experiments, several changes appear to be introduced at the same time, which makes the results harder to interpret. Do you have results from more isolated experiments where only one component is changed at a time? This would make it easier to attribute score changes to specific modifications and to build on those findings in future work.</p></li>\n</ol>\n<p>Looking forward to your response :)</p>",
      "rawMarkdown": "Hi, thank you for your submission to the Writeup Prize. @sambealing and I will post some questions below that help us in assessing your submission more closely, as described in the [updated discussion post](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/discussion/689703).\n\nI have a few questions regarding your work:\n\n1. **Comparison to Public Notebook**: Some parts of your submission appear similar to the public notebook shared in the discussion, which many participants used as a starting point. While building on others' work is certainly encouraged, it would be helpful if you could cite the original notebook, include a link to it, and clearly describe which parts you adapted, as well as the motivation behind each change.\n\n2. **Plots**: Adding plots to summarize your results, especially the ensemble consensus mechanism, would improve both the readability and presentation of your work. For example, it would be useful to include plots comparing the performance of all ablations on both the public leaderboard and your local evaluation set.\n\n3. **Experiment Construction**: In many of your experiments, several changes appear to be introduced at the same time, which makes the results harder to interpret. Do you have results from more isolated experiments where only one component is changed at a time? This would make it easier to attribute score changes to specific modifications and to build on those findings in future work.\n\nLooking forward to your response :)\n\n\n",
      "replies": [
        {
          "id": 3459123,
          "postDate": "2026-05-17T11:14:31.037Z",
          "content": "<p>Hi Philip, thank you for the detailed questions. I agree with all three concerns: attribution to the public starting point should have been clearer, the results would be easier to understand with plots, and many of my experiments are practical engineering iterations rather than clean single-variable ablations.</p>\n<h3>1. Comparison to the Public Notebook</h3>\n<p>My work started from the public <a href=\"https://www.kaggle.com/code/scottford2701/hcmus-group-4?scriptVersionId=310860229\" target=\"_blank\">HCMUS Group 4 notebook</a>, which I used as the initial runnable baseline. I also used the public <a href=\"https://www.kaggle.com/code/andreasbis/aimo-3-utils\" target=\"_blank\">AIMO 3 Utils notebook by andreasbis</a> for offline dependency packaging, especially the <code>vllm</code> and <code>openai_harmony</code> wheels.</p>\n<p>I should have cited both of these explicitly in the writeup.</p>\n<p>The HCMUS baseline already provided the main competition-compatible pipeline:</p>\n<ul>\n<li><code>gpt-oss-120b</code> served through vLLM;</li>\n<li><code>openai_harmony</code> formatting;</li>\n<li>Python tool-use through persistent Jupyter kernels;</li>\n<li>parallel self-consistency attempts;</li>\n<li>entropy-weighted majority voting;</li>\n<li>early stopping;</li>\n<li>adaptive per-problem budgeting;</li>\n<li>EOS / connection-error handling;</li>\n<li>offline Kaggle dependency setup.</li>\n</ul>\n<p>So the most accurate description of my work is not “a new pipeline from scratch,” but an inference-time engineering and evaluation study built on top of that public baseline.</p>\n<p>The parts I adapted directly were:</p>\n<table>\n<thead>\n<tr>\n<th>Component</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>vLLM serving of <code>gpt-oss-120b</code></td>\n<td>kept the same general serving approach</td>\n</tr>\n<tr>\n<td><code>openai_harmony</code> conversation format</td>\n<td>kept because it is the expected format for <code>gpt-oss</code></td>\n</tr>\n<tr>\n<td>persistent Jupyter kernel tool-use</td>\n<td>kept because stateful tool use is important for multi-step math/code reasoning</td>\n</tr>\n<tr>\n<td>parallel attempts + early stopping</td>\n<td>kept the same general self-consistency structure</td>\n</tr>\n<tr>\n<td>entropy-weighted voting</td>\n<td>kept as the main aggregation method</td>\n</tr>\n<tr>\n<td>Kaggle offline dependency setup</td>\n<td>used the public utility input by andreasbis</td>\n</tr>\n</tbody>\n</table>\n<p>My own work was mainly in changing, testing, and analyzing the inference-time configuration around this baseline: prompt variants, attempt count, worker count, batch size, temperature, convergence-voting variants, intended <code>top_p</code> variants, reference-set reruns, public LB submissions, per-problem token analysis, and failure-mode analysis around answer diversity vs. entropy.</p>\n<p>The main changes and motivations were:</p>\n<table>\n<thead>\n<tr>\n<th>Version</th>\n<th>Change</th>\n<th>Motivation</th>\n<th>Result / interpretation</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>baseline</code></td>\n<td>first version with missing entropy function bug</td>\n<td>initial run</td>\n<td>failed due implementation bug, not model quality</td>\n</tr>\n<tr>\n<td><code>v1</code></td>\n<td>8 attempts, entropy voting, verbose prompt</td>\n<td>stable baseline under time budget</td>\n<td>best public LB result</td>\n</tr>\n<tr>\n<td><code>v2</code></td>\n<td>12 attempts, <code>early_stop=5</code>, lower <code>temperature=0.8</code></td>\n<td>test whether more samples + lower randomness improves reliability</td>\n<td>public LB decreased, likely due time-budget pressure and confounded changes</td>\n</tr>\n<tr>\n<td><code>v3</code></td>\n<td>concise V40 prompt, 20 attempts, 16 workers, larger batch</td>\n<td>test whether shorter prompt + more self-consistency improves score</td>\n<td>public LB decreased; too expensive under fixed budget</td>\n</tr>\n<tr>\n<td><code>v4</code></td>\n<td>convergence / ensemble voting family</td>\n<td>test whether answer-distribution convergence is better than majority voting</td>\n<td>strong negative result locally</td>\n</tr>\n<tr>\n<td><code>v5/v6</code></td>\n<td>intended <code>top_p=0.8</code> variants</td>\n<td>test whether tail-token filtering improves math reliability</td>\n<td>weak/no clear evidence; in the code, <code>top_p</code> was declared in <code>CFG</code> but not passed to <code>completions.create</code>, so this experiment did not cleanly test <code>top_p</code></td>\n</tr>\n</tbody>\n</table>\n<p>The key lesson is that increasing inference complexity did not automatically help under the 5-hour budget. The best-performing setup was comparatively simple: 8 attempts, early stop at 4, entropy-weighted majority voting.</p>\n<h3>2. Plots</h3>\n<p>I agree that the writeup would have been much easier to read with plots. Since the writeup has already been submitted, I cannot insert them into the original text, but these are the supplemental plots I prepared after your comment.</p>\n<p><strong>Public LB score by submitted notebook version</strong></p>\n<p>This summarizes the practical outcome of the submitted configurations: <code>v1</code>, <code>v2</code>, <code>v3</code>, <code>v4</code>, and <code>v5</code>. It also makes clear that these are engineering iterations, not clean one-variable ablations.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F8e5516927cba0a7e3786a4b6bab11072%2F01_public_lb_ablation.png?generation=1779015244003143&amp;alt=media\" alt=\"\"></p>\n<p><strong>Notebook version change matrix</strong></p>\n<p>This plot is meant to make the confounding explicit. Most versions change multiple dimensions at once, which is why I should not present them as clean single-variable ablations.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F0b053c7e132e4f3331cfa60ae52f6480%2F05_ablation_change_matrix.png?generation=1779016183515576&amp;alt=media\" alt=\"\"></p>\n<p><strong>Per-problem compute signature</strong></p>\n<p>This shows Norwegian as the clear compute outlier and motivates the token-count difficulty signal.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F56448d59520aa1bb4e3478b4d3f762c3%2F03_problem_token_usage.png?generation=1779015315445959&amp;alt=media\" alt=\"\"></p>\n<p><strong>Answer diversity vs. consensus</strong></p>\n<p>This replaces the table I should have included for the ensemble/consensus discussion. Stable problems cluster around high consensus and low diversity, while Norwegian is the high-diversity / low-consensus outlier.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F4b167e956abcaab2ec95c71b25fd27a1%2F06_consensus_diversity_scatter.png?generation=1779016203985032&amp;alt=media\" alt=\"\"></p>\n<h3>3. Experiment Construction / Isolated Experiments</h3>\n<p>I agree that many experiments changed multiple things at once. This is the biggest limitation of the study.</p>\n<p>Because I joined with only 7 days remaining and had a limited submission budget, I treated the notebook versions as practical engineering iterations rather than clean scientific ablations. In hindsight, the writeup should have separated these two categories more explicitly:</p>\n<table>\n<thead>\n<tr>\n<th>Type</th>\n<th>Examples</th>\n<th>How much can be concluded?</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>repeated same-config check</td>\n<td>repeated reference run of <code>v1</code></td>\n<td>useful for run-to-run stability</td>\n</tr>\n<tr>\n<td>practical engineering iteration</td>\n<td><code>v2</code>, <code>v3</code>, <code>v4</code>, <code>v5</code>, <code>v6</code></td>\n<td>useful negative results, but confounded</td>\n</tr>\n<tr>\n<td>clean one-variable ablation</td>\n<td>mostly not available</td>\n<td>limited by time/submission budget</td>\n</tr>\n</tbody>\n</table>\n<p>The closest I have to isolated evidence is the repeated reference-set run of the same <code>v1</code> configuration discussed in Section 6.5. That checks stability rather than a component change: 9 of 10 reference problems were stable across runs, while the Norwegian problem changed.</p>\n<p>For the version comparisons:</p>\n<ul>\n<li><code>v2</code> vs. <code>v1</code> is not isolated because it changes attempt count, early-stop threshold, and temperature.</li>\n<li><code>v3</code> vs. <code>v1</code> is not isolated because it changes prompt style, attempts, workers, batch size, and early stopping.</li>\n<li><code>v4</code> should not be interpreted as “only voting changed from <code>v1</code>.” It belongs to the V40 / 20-attempt family and adds convergence / ensemble voting and related routing logic.</li>\n<li><code>v5/v6</code> were intended to test the <code>top_p=0.8</code> direction, but because <code>top_p</code> was not actually passed into the completion call, this does not support a strong conclusion about <code>top_p</code>.</li>\n</ul>\n<p>So the safe conclusions are:</p>\n<ul>\n<li>the <code>v1</code>-style entropy-voting setup was the strongest practical configuration I found;</li>\n<li>increasing attempts under the fixed wall-clock budget did not reliably improve score;</li>\n<li>convergence-style voting was a strong negative engineering result in my local test;</li>\n<li>run-to-run variance was real and concentrated mainly in the Norwegian reference problem;</li>\n<li>stronger single-variable ablations would be needed to assign precise causal effects to prompt, temperature, <code>top_p</code>, or worker count.</li>\n</ul>\n<p>If I were repeating the study with more time, I would run a proper ablation grid:</p>\n<table>\n<thead>\n<tr>\n<th>Experiment</th>\n<th>Keep fixed</th>\n<th>Change only</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>prompt ablation</td>\n<td>N=8, T=1.0, same voting</td>\n<td>verbose vs concise prompt</td>\n</tr>\n<tr>\n<td>temperature ablation</td>\n<td>N=8, same prompt/voting</td>\n<td>T=1.0 vs T=0.8</td>\n</tr>\n<tr>\n<td>attempt-count ablation</td>\n<td>same prompt/voting/T</td>\n<td>N=8 vs N=12 vs N=20</td>\n</tr>\n<tr>\n<td>voting ablation</td>\n<td>same prompt/N/T</td>\n<td>majority vs entropy-weighted vs convergence</td>\n</tr>\n<tr>\n<td>worker/batch ablation</td>\n<td>same solver config</td>\n<td>workers/batch-size only</td>\n</tr>\n</tbody>\n</table>\n<p>That would make attribution much cleaner than the constrained 7-day experiment I was able to run.</p>",
          "rawMarkdown": "Hi Philip, thank you for the detailed questions. I agree with all three concerns: attribution to the public starting point should have been clearer, the results would be easier to understand with plots, and many of my experiments are practical engineering iterations rather than clean single-variable ablations.\n\n### 1. Comparison to the Public Notebook\n\nMy work started from the public [HCMUS Group 4 notebook](https://www.kaggle.com/code/scottford2701/hcmus-group-4?scriptVersionId=310860229), which I used as the initial runnable baseline. I also used the public [AIMO 3 Utils notebook by andreasbis](https://www.kaggle.com/code/andreasbis/aimo-3-utils) for offline dependency packaging, especially the `vllm` and `openai_harmony` wheels.\n\nI should have cited both of these explicitly in the writeup.\n\nThe HCMUS baseline already provided the main competition-compatible pipeline:\n\n- `gpt-oss-120b` served through vLLM;\n- `openai_harmony` formatting;\n- Python tool-use through persistent Jupyter kernels;\n- parallel self-consistency attempts;\n- entropy-weighted majority voting;\n- early stopping;\n- adaptive per-problem budgeting;\n- EOS / connection-error handling;\n- offline Kaggle dependency setup.\n\nSo the most accurate description of my work is not “a new pipeline from scratch,” but an inference-time engineering and evaluation study built on top of that public baseline.\n\nThe parts I adapted directly were:\n\n| Component | Notes |\n|---|---|\n| vLLM serving of `gpt-oss-120b` | kept the same general serving approach |\n| `openai_harmony` conversation format | kept because it is the expected format for `gpt-oss` |\n| persistent Jupyter kernel tool-use | kept because stateful tool use is important for multi-step math/code reasoning |\n| parallel attempts + early stopping | kept the same general self-consistency structure |\n| entropy-weighted voting | kept as the main aggregation method |\n| Kaggle offline dependency setup | used the public utility input by andreasbis |\n\nMy own work was mainly in changing, testing, and analyzing the inference-time configuration around this baseline: prompt variants, attempt count, worker count, batch size, temperature, convergence-voting variants, intended `top_p` variants, reference-set reruns, public LB submissions, per-problem token analysis, and failure-mode analysis around answer diversity vs. entropy.\n\nThe main changes and motivations were:\n\n| Version | Change | Motivation | Result / interpretation |\n|---|---|---|---|\n| `baseline` | first version with missing entropy function bug | initial run | failed due implementation bug, not model quality |\n| `v1` | 8 attempts, entropy voting, verbose prompt | stable baseline under time budget | best public LB result |\n| `v2` | 12 attempts, `early_stop=5`, lower `temperature=0.8` | test whether more samples + lower randomness improves reliability | public LB decreased, likely due time-budget pressure and confounded changes |\n| `v3` | concise V40 prompt, 20 attempts, 16 workers, larger batch | test whether shorter prompt + more self-consistency improves score | public LB decreased; too expensive under fixed budget |\n| `v4` | convergence / ensemble voting family | test whether answer-distribution convergence is better than majority voting | strong negative result locally |\n| `v5/v6` | intended `top_p=0.8` variants | test whether tail-token filtering improves math reliability | weak/no clear evidence; in the code, `top_p` was declared in `CFG` but not passed to `completions.create`, so this experiment did not cleanly test `top_p` |\n\nThe key lesson is that increasing inference complexity did not automatically help under the 5-hour budget. The best-performing setup was comparatively simple: 8 attempts, early stop at 4, entropy-weighted majority voting.\n\n### 2. Plots\n\nI agree that the writeup would have been much easier to read with plots. Since the writeup has already been submitted, I cannot insert them into the original text, but these are the supplemental plots I prepared after your comment.\n\n**Public LB score by submitted notebook version**\n\nThis summarizes the practical outcome of the submitted configurations: `v1`, `v2`, `v3`, `v4`, and `v5`. It also makes clear that these are engineering iterations, not clean one-variable ablations.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F8e5516927cba0a7e3786a4b6bab11072%2F01_public_lb_ablation.png?generation=1779015244003143&alt=media)\n\n**Notebook version change matrix**\n\nThis plot is meant to make the confounding explicit. Most versions change multiple dimensions at once, which is why I should not present them as clean single-variable ablations.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F0b053c7e132e4f3331cfa60ae52f6480%2F05_ablation_change_matrix.png?generation=1779016183515576&alt=media)\n\n**Per-problem compute signature**\n\nThis shows Norwegian as the clear compute outlier and motivates the token-count difficulty signal.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F56448d59520aa1bb4e3478b4d3f762c3%2F03_problem_token_usage.png?generation=1779015315445959&alt=media)\n\n**Answer diversity vs. consensus**\n\nThis replaces the table I should have included for the ensemble/consensus discussion. Stable problems cluster around high consensus and low diversity, while Norwegian is the high-diversity / low-consensus outlier.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F29262272%2F4b167e956abcaab2ec95c71b25fd27a1%2F06_consensus_diversity_scatter.png?generation=1779016203985032&alt=media)\n\n### 3. Experiment Construction / Isolated Experiments\n\nI agree that many experiments changed multiple things at once. This is the biggest limitation of the study.\n\nBecause I joined with only 7 days remaining and had a limited submission budget, I treated the notebook versions as practical engineering iterations rather than clean scientific ablations. In hindsight, the writeup should have separated these two categories more explicitly:\n\n| Type | Examples | How much can be concluded? |\n|---|---|---|\n| repeated same-config check | repeated reference run of `v1` | useful for run-to-run stability |\n| practical engineering iteration | `v2`, `v3`, `v4`, `v5`, `v6` | useful negative results, but confounded |\n| clean one-variable ablation | mostly not available | limited by time/submission budget |\n\nThe closest I have to isolated evidence is the repeated reference-set run of the same `v1` configuration discussed in Section 6.5. That checks stability rather than a component change: 9 of 10 reference problems were stable across runs, while the Norwegian problem changed.\n\nFor the version comparisons:\n\n- `v2` vs. `v1` is not isolated because it changes attempt count, early-stop threshold, and temperature.\n- `v3` vs. `v1` is not isolated because it changes prompt style, attempts, workers, batch size, and early stopping.\n- `v4` should not be interpreted as “only voting changed from `v1`.” It belongs to the V40 / 20-attempt family and adds convergence / ensemble voting and related routing logic.\n- `v5/v6` were intended to test the `top_p=0.8` direction, but because `top_p` was not actually passed into the completion call, this does not support a strong conclusion about `top_p`.\n\nSo the safe conclusions are:\n\n- the `v1`-style entropy-voting setup was the strongest practical configuration I found;\n- increasing attempts under the fixed wall-clock budget did not reliably improve score;\n- convergence-style voting was a strong negative engineering result in my local test;\n- run-to-run variance was real and concentrated mainly in the Norwegian reference problem;\n- stronger single-variable ablations would be needed to assign precise causal effects to prompt, temperature, `top_p`, or worker count.\n\nIf I were repeating the study with more time, I would run a proper ablation grid:\n\n| Experiment | Keep fixed | Change only |\n|---|---|---|\n| prompt ablation | N=8, T=1.0, same voting | verbose vs concise prompt |\n| temperature ablation | N=8, same prompt/voting | T=1.0 vs T=0.8 |\n| attempt-count ablation | same prompt/voting/T | N=8 vs N=12 vs N=20 |\n| voting ablation | same prompt/N/T | majority vs entropy-weighted vs convergence |\n| worker/batch ablation | same solver config | workers/batch-size only |\n\nThat would make attribution much cleaner than the constrained 7-day experiment I was able to run.\n"
        }
      ]
    },
    {
      "id": 3447425,
      "postDate": "2026-04-23T05:29:22.890Z",
      "content": "<p>looks like lot of efforts <a href=\"https://www.kaggle.com/heon29\" target=\"_blank\">@heon29</a> nice work!</p>",
      "rawMarkdown": "looks like lot of efforts @heon29 nice work!"
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-20T04:23:57Z",
  "competition_id": 118448,
  "competition_slug": "ai-mathematical-olympiad-progress-prize-3",
  "team_id": 15572431,
  "solution_url": ""
}