{
  "id": 692656,
  "title": " Self-Consistency + TIR with Python-Verification-Weighted Voting for AIMO3",
  "content": "<h2>1. TL;DR</h2>\n<p>Two concrete, publicly verifiable contributions to the AIMO3 open-source lineage:</p>\n<p><strong>A. SC + TIR scaffold on top of parthenos's streaming baseline.</strong> I published <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><code>Self-Consistency Strategy</code></a> (notebook slug: <code>self-consistency-strategy</code>, V12, 170 upvotes). It merges <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\">parthenos's streaming-inference reflexion prompting notebook</a> (score 27) with <a href=\"https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool\" target=\"_blank\">shelterw's Python-tool line</a>, and adds what those notebooks lacked: (i) the <code>openai_harmony</code> chat template with <code>ReasoningEffort.HIGH</code>, (ii) a per-thread persistent Jupyter kernel (<code>BlockingKernelClient</code> + port-pool allocator), (iii) K=8 parallel self-consistency with in-stream <code>\\boxed{…}</code> scanning and a majority-threshold early-stop, (iv) a 16-thread OS-page-cache weight preloader that cuts vLLM startup from ~400 s to ~130 s. This notebook became the foundation ZaynYu forked into <a href=\"https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool\" target=\"_blank\"><code>[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool</code></a> (615 upvotes, Public LB 40).</p>\n<p><strong>B. Python-verification-weighted voting.</strong> In the ZaynYu → daniil1423 → my fork chain, the only non-trivial change I made to the voting logic was to weight each attempt's vote by whether it used the Python tool:</p>\n<ul>\n<li>base weight 1.0</li>\n<li>+0.5 if the attempt made ≥ 3 tool calls</li>\n<li>+0.25 if the attempt made ≥ 1 tool call</li>\n<li>−0.3 if &gt; 50% of its tool calls errored</li>\n</ul>\n<p>Tie-break key: <code>(weighted_votes, raw_votes, total_calls)</code>. This pushed my best same-code submission from the 35–40 band (ZaynYu) to 42/50 peak over n=25 V2 submissions (μ = 38.44, σ = 1.58).</p>\n<p>Neither contribution changes the ceiling by much — the ceiling is set by <code>gpt-oss-120b</code>'s pass@k on this problem set — but both are small, reproducible, and the scaffold in (A) is demonstrably load-bearing downstream.</p>\n<hr>\n<h2>2. Competition Setup</h2>\n<p>AIMO3 gives 50 IMO-style problems with integer answers in <code>[0, 99999]</code>. Each submission is scored twice; a problem earns 1.0 if both runs agree and are correct, 0.5 if one run is correct, and 0 otherwise. Inference runs offline on a single NVIDIA H100-85GB under a 5-hour wall-clock limit. Models must have been released before 2026-03-15.</p>\n<p>I used <code>gpt-oss-120b</code> (120B parameters, MXFP4 weights, ~65 GB VRAM) served via <code>vLLM==0.11.2</code>. The KV cache budget on 1×H100 with this model is about 15–16 GB, which constrains safe concurrent requests to roughly 8.</p>\n<h2>3. Lineage and Honest Attribution</h2>\n<p>This is the relevant portion of the public fork tree. Arrows point from upstream to downstream; numbers in parentheses are approximate Public LB peaks reported in each notebook's title or comments.</p>\n<pre><code>Kawchar Husain                                       (upstream prompt template)\n        │\n        ▼\nparthenos · aimo3-streaming-inference-reflexion-prompting (V1, 27)\n        │   streaming inference + reflexion prompting; no TIR; no Harmony\n        │\nshelterw · way-to-30-50-gpt-oss-w-python-tool          (parallel upstream: simple Python tool loop)\n        │\n        ▼\ncanqiang (me) · self-consistency-strategy (V12, 32)    ← Contribution A\n        │   + Harmony protocol (ReasoningEffort.HIGH)\n        │   + per-thread persistent Jupyter kernel pool\n        │   + K=8 parallel SC with in-stream \\boxed scanning + early-stop\n        │   + 16-thread OS-page-cache weight preloader\n        │\n        ▼\nZaynYu · [40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool (V26, 40)\n        │   + dynamic per-problem time budget\n        │   + class refactor (AIMO3Solver / AIMO3Sandbox / AIMO3Tool)\n        │   + refined system prompts (\"world-class IMO competitor\", \"Never guess\")\n        │\n        ▼\ndaniil1423 · entropy-trajectory-scoring (40)\n        │   + logprob/entropy-based trajectory scoring (I did not use this part)\n        │\n        ▼\ncanqiang (me) · fork of ETS (\"Weighted Voting with Python Verification\" V2, 42)   ← Contribution B\n            + python-call-count &amp; error-rate weighted voting\n            (kept the rest of the ETS/ZaynYu infrastructure unchanged)\n</code></pre>\n<p>Two things I want to be explicit about:</p>\n<ol>\n<li>The 42-score notebook was a <strong>private fork during the competition</strong> (I judged the delta over daniil1423 to be small enough that a separate public notebook during the competition was not obviously worth it). I plan to open-source it after the writeup period. The 170-vote notebook I published earlier is the SC+TIR scaffold (contribution A), not the 42-score fork.</li>\n<li>The DynamicTime budget, the AIMO3Solver class refactor, and the entropy-trajectory machinery are <strong>ZaynYu's and daniil1423's work</strong>, not mine. The only voting-logic delta I contributed is the four-rule weighting above.</li>\n</ol>\n<h2>4. System Overview</h2>\n<h3>4.1 Inference stack</h3>\n<ul>\n<li><code>gpt-oss-120b</code>, native MXFP4 weights, served by <code>vllm</code> 0.11.2.</li>\n<li><code>--kv-cache-dtype fp8_e4m3</code>, <code>--max-model-len 65536</code>, <code>--gpu-memory-utilization 0.96</code>, <code>--max-num-seqs 256</code>, <code>--async-scheduling</code>.</li>\n<li><code>openai_harmony</code> for the chat template. System message is constructed with <code>SystemContent.new().with_reasoning_effort(ReasoningEffort.HIGH).with_tools(python_tool.tool_config)</code>, which is the native format <code>gpt-oss-120b</code> was post-trained on.</li>\n<li>Sampling: <code>temperature=1.0</code>, <code>top_p=1.0</code>, <code>min_p=0.02</code>. Temperature is <strong>not</strong> a free knob for aligned models — <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b\" target=\"_blank\">techtech69's writeup</a> (85th, public 43) documents an 8-point drop when they went to 0.6. My ablations agree.</li>\n</ul>\n<h3>4.2 Per-problem loop</h3>\n<p>Each incoming problem is handled by <code>K=8</code> worker threads sharing a <code>ThreadPoolExecutor</code>. Each thread:</p>\n<ol>\n<li>Acquires one persistent <code>AIMO3Sandbox</code> (Jupyter kernel) from a pool.</li>\n<li>Runs up to 128 reasoning turns. Each turn calls vLLM with <code>stream=True, return_token_ids=True</code>, streams tokens while:<ul>\n<li>checking a shared <code>stop_event</code> and the per-problem deadline,</li>\n<li>scanning incoming text for <code>\\boxed{…}</code> and bailing out as soon as a valid integer in <code>[0, 99999]</code> is found.</li></ul></li>\n<li>If the model emitted a <code>python</code> tool call, the sandbox executes the code in a stateful kernel and the output is fed back as a new conversation message. <code>python_calls</code> and <code>python_errors</code> are tracked per attempt.</li>\n<li>When any 5/8 attempts agree on the same answer (<code>early_stop = 5</code>), the stop event fires and the remaining threads are cancelled.</li>\n</ol>\n<h3>4.3 Voting (my contribution B)</h3>\n<p>After the parallel sweep, votes are aggregated with four small rules on top of raw majority:</p>\n<pre><code># AIMO3Solver._select_answer, used in the 42-score fork of ETS V2\nfor result in detailed_results:\n    answer = result['Answer']\n    if answer is None:\n        continue\n    weight = 1.0\n    calls  = result['Python Calls']\n    errors = result['Python Errors']\n    if calls &gt;= 3:\n        weight += 0.5         # strong Python-verified answer\n    elif calls &gt;= 1:\n        weight += 0.25        # at least one Python check\n    if calls &gt; 0 and errors / calls &gt; 0.5:\n        weight -= 0.3         # high error rate → unreliable\n    stats[answer]['weighted_votes'] += weight\n    stats[answer]['votes']  += 1\n    stats[answer]['calls']  += calls\n    stats[answer]['errors'] += errors\n\n# Tie-break: weighted votes &gt; raw votes &gt; total Python calls\nreturn max(stats.items(),\n           key=lambda x: (x[1]['weighted_votes'],\n                          x[1]['votes'],\n                          x[1]['calls']))[0]\n</code></pre>\n<p>The intuition is trivial: if an answer was arrived at by an attempt that ran Python code several times and those calls mostly returned without an exception, it is more likely to be correct than an answer the model guessed without verification. The coefficients (0.25 / 0.5 / 0.3 / threshold 0.5) are not tuned; they are round numbers that fell out of the first thing I tried. The contribution is the <em>structure</em> of the weighting, not the specific values.</p>\n<h2>5. Reproducibility and the Noise Floor</h2>\n<p>Running the same notebook twice on Kaggle does <em>not</em> give the same score. This is not a subtle effect and it is not my claim — it is reported by both techtech69 and ZaynYu in their own writeups / comments. On vLLM, batched completion order depends on GPU scheduling, floating-point associativity perturbs the softmax, and downstream token sampling diverges.</p>\n<h3>5.1 Parthenos's upstream (no SC, no TIR): very noisy, centred low</h3>\n<p>From public comments on <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\">parthenos's <code>aimo3-streaming-inference-reflexion-prompting</code></a> V1 (author score 27):</p>\n<table>\n<thead>\n<tr>\n<th>Forker</th>\n<th>Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Poemcourt (copy, no changes)</td>\n<td>26</td>\n</tr>\n<tr>\n<td>Dipankar Mitra (copy, no changes)</td>\n<td>21</td>\n</tr>\n<tr>\n<td>CloudYU</td>\n<td>22</td>\n</tr>\n<tr>\n<td>Octavi Grau</td>\n<td>16</td>\n</tr>\n<tr>\n<td>Artem Goncharov</td>\n<td>18</td>\n</tr>\n<tr>\n<td>swordsman (after increasing timeout)</td>\n<td>22</td>\n</tr>\n</tbody>\n</table>\n<p>Many more hit \"Notebook threw exception\". Spread is roughly 16–26 against an author-reported 27.</p>\n<h3>5.2 My SC+TIR scaffold (contribution A): higher and tighter</h3>\n<p>From the comment on my <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><code>self-consistency-strategy</code></a>:</p>\n<blockquote>\n  <p><em>\"i scored 35 with no changes…\"</em> — cm391</p>\n</blockquote>\n<p>Author peak on that notebook was 32 on LB; the commenter got 35 with zero changes, and downstream forks that layered additional infrastructure (ZaynYu, daniil1423) reached 40+.</p>\n<h3>5.3 ZaynYu's fork of my scaffold: the best community reproduction data</h3>\n<p>ZaynYu's <a href=\"https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool\" target=\"_blank\"><code>[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool</code></a> (615 upvotes, 1,362 copies) has 57 comments and is the most-forked downstream child of my SC scaffold. A selection of the scores people reported, quoted literally from that comment thread:</p>\n<table>\n<thead>\n<tr>\n<th>Forker</th>\n<th>Variant</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V1 (direct copy)</td>\n<td>38</td>\n</tr>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V2</td>\n<td>35</td>\n</tr>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V10</td>\n<td>36</td>\n</tr>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V12</td>\n<td>36</td>\n</tr>\n<tr>\n<td>Siancy (\"Same as parthenos's, no modifications\")</td>\n<td>V1</td>\n<td>41</td>\n</tr>\n<tr>\n<td>THUNDER THUNDER</td>\n<td>V01</td>\n<td>40</td>\n</tr>\n<tr>\n<td>THUNDER THUNDER</td>\n<td>V02</td>\n<td>36</td>\n</tr>\n<tr>\n<td>Abhijeet Bhargava</td>\n<td>V01 / V03 / V05</td>\n<td>38 / 35 / 34</td>\n</tr>\n<tr>\n<td>chenjixuan666 (fork of Siancy)</td>\n<td>V01</td>\n<td>38</td>\n</tr>\n<tr>\n<td>parthenos (on ZaynYu's V15)</td>\n<td>—</td>\n<td>37</td>\n</tr>\n<tr>\n<td>Dipankar Mitra</td>\n<td>submitted twice</td>\n<td>33 / 33</td>\n</tr>\n</tbody>\n</table>\n<p>ZaynYu himself on his own notebook:</p>\n<blockquote>\n  <p><em>\"The score of the LB by running the same notebook is not guaranteed to be the same.\"</em></p>\n</blockquote>\n<p>So, empirically, the scaffold I contributed (A) sits downstream of parthenos's 16–26 band and supports a community reproduction band of roughly 34–41 on top of the same hardware.</p>\n<h3>5.4 My own V2 notebook (contribution B): 25 identical submissions</h3>\n<p>I submitted the same V2 code 25 times to measure the noise floor:</p>\n<ul>\n<li>n = 25</li>\n<li>min = 35</li>\n<li>max = 42</li>\n<li>mean = 38.44</li>\n<li>std  = 1.58</li>\n</ul>\n<p>A single run scoring 42 is well inside the tail; a single run scoring 35 is also inside the tail. This is why I frame the Python-weighted voting as \"pushed the ceiling up by ~2 points\", not \"solves more problems\". The voting change is not the dominant source of score; the model and the TIR loop are.</p>\n<h2>6. Ablations</h2>\n<p>Everything in this table is a single-submission LB score from my own submission list. They are not independent trials — each number is a draw from a noisy distribution with σ ≈ 1–2 on top of a ~35–42 base. I report them with that caveat.</p>\n<table>\n<thead>\n<tr>\n<th>Configuration</th>\n<th>Best</th>\n<th>Mean</th>\n<th>N</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Weighted Voting w/ Python Verification (V2, contribution B)</td>\n<td><strong>42</strong></td>\n<td>38.44</td>\n<td>25</td>\n<td>Peak and baseline for my work</td>\n</tr>\n<tr>\n<td>ans_verifys (verifier variant)</td>\n<td>41</td>\n<td>37.67</td>\n<td>6</td>\n<td>Different verification logic, similar spread</td>\n</tr>\n<tr>\n<td>entropy-trajectory-scoring (daniil1423's logprob-entropy scoring)</td>\n<td>39</td>\n<td>36.78</td>\n<td>9</td>\n<td>Without my weighted voting, entropy scoring alone</td>\n</tr>\n<tr>\n<td>Dual Entropy-Weighted Voting</td>\n<td>37</td>\n<td>35.71</td>\n<td>7</td>\n<td>Combining two entropy signals</td>\n</tr>\n<tr>\n<td>ZaynYu-style direct fork (36/40 variant)</td>\n<td>34</td>\n<td>32.67</td>\n<td>3</td>\n<td>Before my voting change</td>\n</tr>\n<tr>\n<td>self-consistency-strategy V12 (contribution A, public)</td>\n<td>32</td>\n<td>—</td>\n<td>2</td>\n<td>Before any voting change; scaffold only</td>\n</tr>\n<tr>\n<td>parthenos direct fork (streaming + reflexion, no TIR)</td>\n<td>26</td>\n<td>23</td>\n<td>2</td>\n<td>Upstream baseline</td>\n</tr>\n<tr>\n<td>improved-tir-solution</td>\n<td>25</td>\n<td>21</td>\n<td>3</td>\n<td>Different TIR formulation — didn't pay off</td>\n</tr>\n</tbody>\n</table>\n<p>The progression from parthenos → SC+TIR scaffold → ZaynYu's DynamicTime → weighted voting is visible across my own submissions, not just across the public fork tree.</p>\n<h2>7. What Did and Did Not Matter</h2>\n<h3>7.1 Worked</h3>\n<ul>\n<li><strong>Treating the sampler as an uncertain voter, not an oracle.</strong> <a href=\"https://arxiv.org/abs/2203.11171\" target=\"_blank\">Self-consistency</a> is old news, but on AIMO3 it is not optional: single-run accuracy is much noisier than multi-run agreement. This is the single biggest delta above parthenos's baseline.</li>\n<li><strong>Persistent Jupyter kernels.</strong> One kernel per thread, created once at notebook startup, reused across all 50 problems. Import overhead for each <code>sympy</code>/<code>numpy</code>/<code>mpmath</code> call disappears. <code>BlockingKernelClient</code> + a per-thread port allocator avoids collisions that bite you as soon as you try to scale past K=2.</li>\n<li><strong>Harmony's <code>ReasoningEffort.HIGH</code> + <code>min_p=0.02</code>.</strong> The model's native training format outperforms any hand-crafted prompt I tried, including \"step by step\" and \"think carefully\" variants. This is also what techtech69 reports.</li>\n<li><strong>OS-page-cache weight preloading.</strong> 16 threads reading every weight file in 1 GB chunks before <code>vllm</code> starts saves ~270 s of startup. Every second saved here is a second available to the hardest problems.</li>\n<li><strong>In-stream <code>\\boxed{…}</code> scanning.</strong> Once a valid integer appears in the stream, close the connection. Don't wait for the model to finish.</li>\n<li><strong>Weighted voting (my B).</strong> Small but measurable lift on the upper tail of the score distribution. On average maybe +1, on the best submission +2.</li>\n</ul>\n<h3>7.2 Didn't work, or not for me</h3>\n<ul>\n<li><strong>Prompt engineering beyond \"rigorous competitor, never guess, box your answer\".</strong> Every longer system prompt I tried either did nothing or slightly hurt.</li>\n<li><strong>Temperature below 1.0.</strong> Distribution collapses, loops, fewer solution paths. Confirmed by techtech69's −8 result at 0.6.</li>\n<li><strong>Pushing K past 8.</strong> KV cache is the binding constraint on 1×H100 with <code>gpt-oss-120b</code>. 16 and 24 concurrent attempts are preempted by vLLM and score catastrophically worse. techtech69 reports −22 at K=24; I observed the same pattern at smaller scale.</li>\n<li><strong>Low <code>base_problem_timeout</code> with higher K.</strong> 100 s is not enough tokens to finish a hard problem. You lose more to truncated outputs than you gain from additional samples.</li>\n<li><strong>Fine-grained entropy-based trajectory scoring.</strong> daniil1423's ETS scoring is clever but in my hands it did not clearly dominate simple weighted majority. Others (Potrhino, techtech69) report stronger results with entropy; this is a \"methodology ≠ my hands\" disclaimer rather than a claim about the method.</li>\n</ul>\n<h2>8. Limitations and Things I Got Wrong</h2>\n<ol>\n<li><strong>I did not run controlled ablations.</strong> Each row in §6 is one submission or a handful of identical resubmissions. To claim \"my weighted voting beats raw majority by X points\", I would need to run both variants against the same problem set under the same scheduler noise, many times. I have not. The noise floor (σ ≈ 1.6) is wide enough that the 42-peak could plausibly come from a lucky draw on the ZaynYu base alone.</li>\n<li><strong>I did not verify weight-coefficient sensitivity.</strong> <code>+0.5 / +0.25 / −0.3</code> with a 0.5 error-rate threshold is just the first thing I tried. I don't know whether <code>+0.3 / +0.15 / −0.2</code> would be better, worse, or identical within the noise.</li>\n<li><strong>I piggybacked heavily.</strong> Contribution B is <em>small</em> on top of ZaynYu and daniil1423. Without their infrastructure — DynamicTime, AIMO3Solver, the kernel pool with <code>queue.Queue</code>, the refined system prompts — the weighted-vote rule has nothing to rest on. The right way to read this writeup is \"I added two small bricks to a wall that other people built most of\", not \"I solved AIMO3 my way\".</li>\n</ol>\n<h2>9. What I'd Do Differently</h2>\n<ul>\n<li><strong>Record every submission's per-problem answers.</strong> Without the per-problem breakdown, I can't tell which of the 50 problems my weighted vote actually flipped versus which were noise. Next time I'd log every <code>(problem_id, attempt_i, answer, python_calls, python_errors, token_len)</code> tuple to a file that's in the submission output, so I can do real ablation offline.</li>\n<li><strong>Try Qwen3-Next-80B-A3B-Thinking with a 262 k context.</strong> <code>gpt-oss-120b</code> caps out at ~43–44 on this hardware because its per-attempt accuracy on hard problems is ~5%. Both techtech69's and the host's pass@n data strongly suggest the gain from switching models is larger than the gain from any more voting tricks.</li>\n</ul>\n<h2>10. Reproducibility</h2>\n<p><strong>Notebooks:</strong></p>\n<ul>\n<li>Scaffold (contribution A, open source): <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><code>canqiang/self-consistency-strategy</code></a> (V12, 170 upvotes).</li>\n<li>42-score variant (contribution B): a fork of <a href=\"https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring\" target=\"_blank\"><code>daniil1423/entropy-trajectory-scoring</code></a> with the <code>_select_answer</code> method replaced by the 20-line rule in §4.3. Currently private; I'll open-source it shortly.</li>\n</ul>\n<p><strong>Key configuration for the 42-score submission:</strong></p>\n<pre><code>class Config:\n    model_path               = '/kaggle/input/gpt-oss-120b/transformers/default/1'\n    served_model_name        = 'gpt-oss'\n    context_tokens           = 65536\n    kv_cache_dtype           = 'fp8_e4m3'\n    gpu_memory_utilization   = 0.96\n    batch_size               = 256\n\n    temperature              = 1.0\n    top_p                    = 1.0\n    min_p                    = 0.02\n    seed                     = 42\n    attempts                 = 8\n    workers                  = 16\n    early_stop               = 5\n    turns                    = 128\n\n    high_problem_timeout     = 900\n    base_problem_timeout     = 300\n    notebook_limit           = 17400\n    sandbox_timeout          = 3\n    jupyter_timeout          = 10\n</code></pre>\n<p><strong>Hardware:</strong> 1×H100 85GB, Kaggle competition runtime, 5h wall clock.</p>\n<p><strong>Expected variance:</strong> μ ≈ 38, σ ≈ 1.6 across identical-code submissions. A single run scoring in <code>[35, 42]</code> should be considered a successful reproduction.</p>\n<hr>\n<h2>11. Acknowledgements</h2>\n<p>Most of what is in this notebook is not mine. I want to name the people whose work I built on, in the order I inherited it:</p>\n<ul>\n<li><strong>Kawchar Husain</strong>, for the original prompt structure that parthenos forked from.</li>\n<li><strong><a href=\"https://www.kaggle.com/nihilisticneuralnet\" target=\"_blank\">parthenos (nihilisticneuralnet)</a></strong>, for publishing <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\"><code>aimo3-streaming-inference-reflexion-prompting</code></a> — the streaming-inference reflexion prompt scaffold that my SC+TIR notebook merges with shelterw's line.</li>\n<li><strong><a href=\"https://www.kaggle.com/shelterw\" target=\"_blank\">shelterw</a></strong>, for <a href=\"https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool\" target=\"_blank\"><code>[Way to 30+/50] GPT-OSS - w/ python tool</code></a>, the other upstream I merged into the SC notebook.</li>\n<li><strong><a href=\"https://www.kaggle.com/zaynyu\" target=\"_blank\">ZaynYu</a></strong>, for turning my SC+TIR scaffold into a class-structured solver with dynamic time budgeting and a proper sandbox pool — the infrastructure my weighted-voting fork runs on.</li>\n<li><strong><a href=\"https://www.kaggle.com/daniil1423\" target=\"_blank\">daniil1423</a></strong>, for the <a href=\"https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring\" target=\"_blank\">entropy-trajectory-scoring notebook</a> that my 42-score fork directly modifies.</li>\n<li><strong><a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b\" target=\"_blank\">techtech69</a></strong> and <strong><a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/potrhino-strategy-for-aimo3-adaptive-test-time-op\" target=\"_blank\">Potrhino</a></strong>, whose AIMO3 writeups on entropy-weighted voting and DeepConf-inspired pruning shaped how I now think about the \"voting as uncertainty estimator\" framing in §7.</li>\n</ul>\n<p>If you are one of these people and I have miscredited any part of your work, please tell me and I will correct this writeup.</p>\n<h2>12. References</h2>\n<p>Writeups / notebooks directly referenced above:</p>\n<ul>\n<li>techtech69, <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b\" target=\"_blank\"><em>Entropy-Weighted Majority Voting with gpt-oss-120b for AIMO3</em></a> (85th place, Public LB 43). Kaggle writeup.</li>\n<li>Potrhino, <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/potrhino-strategy-for-aimo3-adaptive-test-time-op\" target=\"_blank\"><em>Adaptive Test-Time Optimization for gpt-oss-120b</em></a> (91st place, Public LB 43). Kaggle writeup.</li>\n<li>parthenos (nihilisticneuralnet), <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\"><em>AIMO3: streaming-inference reflexion prompting</em></a> (V1).</li>\n<li>ShelterW, <a href=\"https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool\" target=\"_blank\"><em>[Way to 30+/50] GPT-OSS — w/ python tool</em></a>.</li>\n<li>canqiang (me), <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><em>Self-Consistency Strategy</em></a> (V12).</li>\n<li>ZaynYu, <a href=\"https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool\" target=\"_blank\"><em>[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool</em></a> (V26).</li>\n<li>daniil1423, <a href=\"https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring\" target=\"_blank\"><em>entropy-trajectory-scoring</em></a>.</li>\n</ul>\n<p>External methodology references:</p>\n<ul>\n<li>Wang et al., <a href=\"https://arxiv.org/abs/2203.11171\" target=\"_blank\"><em>Self-Consistency Improves Chain of Thought Reasoning in Language Models</em></a>, arXiv:2203.11171.</li>\n<li>Wei et al., <a href=\"https://arxiv.org/abs/2201.11903\" target=\"_blank\"><em>Chain-of-Thought Prompting Elicits Reasoning in Large Language Models</em></a>, arXiv:2201.11903.</li>\n<li>Lin &amp; Xu, <a href=\"https://arxiv.org/abs/2508.19201\" target=\"_blank\"><em>Understanding Tool-Integrated Reasoning</em></a>, arXiv:2508.19201.</li>\n<li>Fu et al., <a href=\"https://arxiv.org/abs/2508.15260\" target=\"_blank\"><em>Deep Think with Confidence</em></a>, arXiv:2508.15260.</li>\n<li>OpenAI, <a href=\"https://arxiv.org/abs/2508.10925\" target=\"_blank\"><em>gpt-oss-120b &amp; gpt-oss-20b Model Card</em></a>, arXiv:2508.10925.</li>\n<li>Kwon et al., <a href=\"https://arxiv.org/abs/2309.06180\" target=\"_blank\"><em>vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention</em></a>, SOSP 2023.</li>\n</ul>",
  "comments": [],
  "comment_count": 0,
  "messages": [
    {
      "id": 3444205,
      "postDate": "2026-04-17T13:19:37.670Z",
      "content": "<h2>1. TL;DR</h2>\n<p>Two concrete, publicly verifiable contributions to the AIMO3 open-source lineage:</p>\n<p><strong>A. SC + TIR scaffold on top of parthenos's streaming baseline.</strong> I published <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><code>Self-Consistency Strategy</code></a> (notebook slug: <code>self-consistency-strategy</code>, V12, 170 upvotes). It merges <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\">parthenos's streaming-inference reflexion prompting notebook</a> (score 27) with <a href=\"https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool\" target=\"_blank\">shelterw's Python-tool line</a>, and adds what those notebooks lacked: (i) the <code>openai_harmony</code> chat template with <code>ReasoningEffort.HIGH</code>, (ii) a per-thread persistent Jupyter kernel (<code>BlockingKernelClient</code> + port-pool allocator), (iii) K=8 parallel self-consistency with in-stream <code>\\boxed{…}</code> scanning and a majority-threshold early-stop, (iv) a 16-thread OS-page-cache weight preloader that cuts vLLM startup from ~400 s to ~130 s. This notebook became the foundation ZaynYu forked into <a href=\"https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool\" target=\"_blank\"><code>[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool</code></a> (615 upvotes, Public LB 40).</p>\n<p><strong>B. Python-verification-weighted voting.</strong> In the ZaynYu → daniil1423 → my fork chain, the only non-trivial change I made to the voting logic was to weight each attempt's vote by whether it used the Python tool:</p>\n<ul>\n<li>base weight 1.0</li>\n<li>+0.5 if the attempt made ≥ 3 tool calls</li>\n<li>+0.25 if the attempt made ≥ 1 tool call</li>\n<li>−0.3 if &gt; 50% of its tool calls errored</li>\n</ul>\n<p>Tie-break key: <code>(weighted_votes, raw_votes, total_calls)</code>. This pushed my best same-code submission from the 35–40 band (ZaynYu) to 42/50 peak over n=25 V2 submissions (μ = 38.44, σ = 1.58).</p>\n<p>Neither contribution changes the ceiling by much — the ceiling is set by <code>gpt-oss-120b</code>'s pass@k on this problem set — but both are small, reproducible, and the scaffold in (A) is demonstrably load-bearing downstream.</p>\n<hr>\n<h2>2. Competition Setup</h2>\n<p>AIMO3 gives 50 IMO-style problems with integer answers in <code>[0, 99999]</code>. Each submission is scored twice; a problem earns 1.0 if both runs agree and are correct, 0.5 if one run is correct, and 0 otherwise. Inference runs offline on a single NVIDIA H100-85GB under a 5-hour wall-clock limit. Models must have been released before 2026-03-15.</p>\n<p>I used <code>gpt-oss-120b</code> (120B parameters, MXFP4 weights, ~65 GB VRAM) served via <code>vLLM==0.11.2</code>. The KV cache budget on 1×H100 with this model is about 15–16 GB, which constrains safe concurrent requests to roughly 8.</p>\n<h2>3. Lineage and Honest Attribution</h2>\n<p>This is the relevant portion of the public fork tree. Arrows point from upstream to downstream; numbers in parentheses are approximate Public LB peaks reported in each notebook's title or comments.</p>\n<pre><code>Kawchar Husain                                       (upstream prompt template)\n        │\n        ▼\nparthenos · aimo3-streaming-inference-reflexion-prompting (V1, 27)\n        │   streaming inference + reflexion prompting; no TIR; no Harmony\n        │\nshelterw · way-to-30-50-gpt-oss-w-python-tool          (parallel upstream: simple Python tool loop)\n        │\n        ▼\ncanqiang (me) · self-consistency-strategy (V12, 32)    ← Contribution A\n        │   + Harmony protocol (ReasoningEffort.HIGH)\n        │   + per-thread persistent Jupyter kernel pool\n        │   + K=8 parallel SC with in-stream \\boxed scanning + early-stop\n        │   + 16-thread OS-page-cache weight preloader\n        │\n        ▼\nZaynYu · [40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool (V26, 40)\n        │   + dynamic per-problem time budget\n        │   + class refactor (AIMO3Solver / AIMO3Sandbox / AIMO3Tool)\n        │   + refined system prompts (\"world-class IMO competitor\", \"Never guess\")\n        │\n        ▼\ndaniil1423 · entropy-trajectory-scoring (40)\n        │   + logprob/entropy-based trajectory scoring (I did not use this part)\n        │\n        ▼\ncanqiang (me) · fork of ETS (\"Weighted Voting with Python Verification\" V2, 42)   ← Contribution B\n            + python-call-count &amp; error-rate weighted voting\n            (kept the rest of the ETS/ZaynYu infrastructure unchanged)\n</code></pre>\n<p>Two things I want to be explicit about:</p>\n<ol>\n<li>The 42-score notebook was a <strong>private fork during the competition</strong> (I judged the delta over daniil1423 to be small enough that a separate public notebook during the competition was not obviously worth it). I plan to open-source it after the writeup period. The 170-vote notebook I published earlier is the SC+TIR scaffold (contribution A), not the 42-score fork.</li>\n<li>The DynamicTime budget, the AIMO3Solver class refactor, and the entropy-trajectory machinery are <strong>ZaynYu's and daniil1423's work</strong>, not mine. The only voting-logic delta I contributed is the four-rule weighting above.</li>\n</ol>\n<h2>4. System Overview</h2>\n<h3>4.1 Inference stack</h3>\n<ul>\n<li><code>gpt-oss-120b</code>, native MXFP4 weights, served by <code>vllm</code> 0.11.2.</li>\n<li><code>--kv-cache-dtype fp8_e4m3</code>, <code>--max-model-len 65536</code>, <code>--gpu-memory-utilization 0.96</code>, <code>--max-num-seqs 256</code>, <code>--async-scheduling</code>.</li>\n<li><code>openai_harmony</code> for the chat template. System message is constructed with <code>SystemContent.new().with_reasoning_effort(ReasoningEffort.HIGH).with_tools(python_tool.tool_config)</code>, which is the native format <code>gpt-oss-120b</code> was post-trained on.</li>\n<li>Sampling: <code>temperature=1.0</code>, <code>top_p=1.0</code>, <code>min_p=0.02</code>. Temperature is <strong>not</strong> a free knob for aligned models — <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b\" target=\"_blank\">techtech69's writeup</a> (85th, public 43) documents an 8-point drop when they went to 0.6. My ablations agree.</li>\n</ul>\n<h3>4.2 Per-problem loop</h3>\n<p>Each incoming problem is handled by <code>K=8</code> worker threads sharing a <code>ThreadPoolExecutor</code>. Each thread:</p>\n<ol>\n<li>Acquires one persistent <code>AIMO3Sandbox</code> (Jupyter kernel) from a pool.</li>\n<li>Runs up to 128 reasoning turns. Each turn calls vLLM with <code>stream=True, return_token_ids=True</code>, streams tokens while:<ul>\n<li>checking a shared <code>stop_event</code> and the per-problem deadline,</li>\n<li>scanning incoming text for <code>\\boxed{…}</code> and bailing out as soon as a valid integer in <code>[0, 99999]</code> is found.</li></ul></li>\n<li>If the model emitted a <code>python</code> tool call, the sandbox executes the code in a stateful kernel and the output is fed back as a new conversation message. <code>python_calls</code> and <code>python_errors</code> are tracked per attempt.</li>\n<li>When any 5/8 attempts agree on the same answer (<code>early_stop = 5</code>), the stop event fires and the remaining threads are cancelled.</li>\n</ol>\n<h3>4.3 Voting (my contribution B)</h3>\n<p>After the parallel sweep, votes are aggregated with four small rules on top of raw majority:</p>\n<pre><code># AIMO3Solver._select_answer, used in the 42-score fork of ETS V2\nfor result in detailed_results:\n    answer = result['Answer']\n    if answer is None:\n        continue\n    weight = 1.0\n    calls  = result['Python Calls']\n    errors = result['Python Errors']\n    if calls &gt;= 3:\n        weight += 0.5         # strong Python-verified answer\n    elif calls &gt;= 1:\n        weight += 0.25        # at least one Python check\n    if calls &gt; 0 and errors / calls &gt; 0.5:\n        weight -= 0.3         # high error rate → unreliable\n    stats[answer]['weighted_votes'] += weight\n    stats[answer]['votes']  += 1\n    stats[answer]['calls']  += calls\n    stats[answer]['errors'] += errors\n\n# Tie-break: weighted votes &gt; raw votes &gt; total Python calls\nreturn max(stats.items(),\n           key=lambda x: (x[1]['weighted_votes'],\n                          x[1]['votes'],\n                          x[1]['calls']))[0]\n</code></pre>\n<p>The intuition is trivial: if an answer was arrived at by an attempt that ran Python code several times and those calls mostly returned without an exception, it is more likely to be correct than an answer the model guessed without verification. The coefficients (0.25 / 0.5 / 0.3 / threshold 0.5) are not tuned; they are round numbers that fell out of the first thing I tried. The contribution is the <em>structure</em> of the weighting, not the specific values.</p>\n<h2>5. Reproducibility and the Noise Floor</h2>\n<p>Running the same notebook twice on Kaggle does <em>not</em> give the same score. This is not a subtle effect and it is not my claim — it is reported by both techtech69 and ZaynYu in their own writeups / comments. On vLLM, batched completion order depends on GPU scheduling, floating-point associativity perturbs the softmax, and downstream token sampling diverges.</p>\n<h3>5.1 Parthenos's upstream (no SC, no TIR): very noisy, centred low</h3>\n<p>From public comments on <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\">parthenos's <code>aimo3-streaming-inference-reflexion-prompting</code></a> V1 (author score 27):</p>\n<table>\n<thead>\n<tr>\n<th>Forker</th>\n<th>Score</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Poemcourt (copy, no changes)</td>\n<td>26</td>\n</tr>\n<tr>\n<td>Dipankar Mitra (copy, no changes)</td>\n<td>21</td>\n</tr>\n<tr>\n<td>CloudYU</td>\n<td>22</td>\n</tr>\n<tr>\n<td>Octavi Grau</td>\n<td>16</td>\n</tr>\n<tr>\n<td>Artem Goncharov</td>\n<td>18</td>\n</tr>\n<tr>\n<td>swordsman (after increasing timeout)</td>\n<td>22</td>\n</tr>\n</tbody>\n</table>\n<p>Many more hit \"Notebook threw exception\". Spread is roughly 16–26 against an author-reported 27.</p>\n<h3>5.2 My SC+TIR scaffold (contribution A): higher and tighter</h3>\n<p>From the comment on my <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><code>self-consistency-strategy</code></a>:</p>\n<blockquote>\n  <p><em>\"i scored 35 with no changes…\"</em> — cm391</p>\n</blockquote>\n<p>Author peak on that notebook was 32 on LB; the commenter got 35 with zero changes, and downstream forks that layered additional infrastructure (ZaynYu, daniil1423) reached 40+.</p>\n<h3>5.3 ZaynYu's fork of my scaffold: the best community reproduction data</h3>\n<p>ZaynYu's <a href=\"https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool\" target=\"_blank\"><code>[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool</code></a> (615 upvotes, 1,362 copies) has 57 comments and is the most-forked downstream child of my SC scaffold. A selection of the scores people reported, quoted literally from that comment thread:</p>\n<table>\n<thead>\n<tr>\n<th>Forker</th>\n<th>Variant</th>\n<th>Public LB</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V1 (direct copy)</td>\n<td>38</td>\n</tr>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V2</td>\n<td>35</td>\n</tr>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V10</td>\n<td>36</td>\n</tr>\n<tr>\n<td>Tong Hui Kang</td>\n<td>V12</td>\n<td>36</td>\n</tr>\n<tr>\n<td>Siancy (\"Same as parthenos's, no modifications\")</td>\n<td>V1</td>\n<td>41</td>\n</tr>\n<tr>\n<td>THUNDER THUNDER</td>\n<td>V01</td>\n<td>40</td>\n</tr>\n<tr>\n<td>THUNDER THUNDER</td>\n<td>V02</td>\n<td>36</td>\n</tr>\n<tr>\n<td>Abhijeet Bhargava</td>\n<td>V01 / V03 / V05</td>\n<td>38 / 35 / 34</td>\n</tr>\n<tr>\n<td>chenjixuan666 (fork of Siancy)</td>\n<td>V01</td>\n<td>38</td>\n</tr>\n<tr>\n<td>parthenos (on ZaynYu's V15)</td>\n<td>—</td>\n<td>37</td>\n</tr>\n<tr>\n<td>Dipankar Mitra</td>\n<td>submitted twice</td>\n<td>33 / 33</td>\n</tr>\n</tbody>\n</table>\n<p>ZaynYu himself on his own notebook:</p>\n<blockquote>\n  <p><em>\"The score of the LB by running the same notebook is not guaranteed to be the same.\"</em></p>\n</blockquote>\n<p>So, empirically, the scaffold I contributed (A) sits downstream of parthenos's 16–26 band and supports a community reproduction band of roughly 34–41 on top of the same hardware.</p>\n<h3>5.4 My own V2 notebook (contribution B): 25 identical submissions</h3>\n<p>I submitted the same V2 code 25 times to measure the noise floor:</p>\n<ul>\n<li>n = 25</li>\n<li>min = 35</li>\n<li>max = 42</li>\n<li>mean = 38.44</li>\n<li>std  = 1.58</li>\n</ul>\n<p>A single run scoring 42 is well inside the tail; a single run scoring 35 is also inside the tail. This is why I frame the Python-weighted voting as \"pushed the ceiling up by ~2 points\", not \"solves more problems\". The voting change is not the dominant source of score; the model and the TIR loop are.</p>\n<h2>6. Ablations</h2>\n<p>Everything in this table is a single-submission LB score from my own submission list. They are not independent trials — each number is a draw from a noisy distribution with σ ≈ 1–2 on top of a ~35–42 base. I report them with that caveat.</p>\n<table>\n<thead>\n<tr>\n<th>Configuration</th>\n<th>Best</th>\n<th>Mean</th>\n<th>N</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Weighted Voting w/ Python Verification (V2, contribution B)</td>\n<td><strong>42</strong></td>\n<td>38.44</td>\n<td>25</td>\n<td>Peak and baseline for my work</td>\n</tr>\n<tr>\n<td>ans_verifys (verifier variant)</td>\n<td>41</td>\n<td>37.67</td>\n<td>6</td>\n<td>Different verification logic, similar spread</td>\n</tr>\n<tr>\n<td>entropy-trajectory-scoring (daniil1423's logprob-entropy scoring)</td>\n<td>39</td>\n<td>36.78</td>\n<td>9</td>\n<td>Without my weighted voting, entropy scoring alone</td>\n</tr>\n<tr>\n<td>Dual Entropy-Weighted Voting</td>\n<td>37</td>\n<td>35.71</td>\n<td>7</td>\n<td>Combining two entropy signals</td>\n</tr>\n<tr>\n<td>ZaynYu-style direct fork (36/40 variant)</td>\n<td>34</td>\n<td>32.67</td>\n<td>3</td>\n<td>Before my voting change</td>\n</tr>\n<tr>\n<td>self-consistency-strategy V12 (contribution A, public)</td>\n<td>32</td>\n<td>—</td>\n<td>2</td>\n<td>Before any voting change; scaffold only</td>\n</tr>\n<tr>\n<td>parthenos direct fork (streaming + reflexion, no TIR)</td>\n<td>26</td>\n<td>23</td>\n<td>2</td>\n<td>Upstream baseline</td>\n</tr>\n<tr>\n<td>improved-tir-solution</td>\n<td>25</td>\n<td>21</td>\n<td>3</td>\n<td>Different TIR formulation — didn't pay off</td>\n</tr>\n</tbody>\n</table>\n<p>The progression from parthenos → SC+TIR scaffold → ZaynYu's DynamicTime → weighted voting is visible across my own submissions, not just across the public fork tree.</p>\n<h2>7. What Did and Did Not Matter</h2>\n<h3>7.1 Worked</h3>\n<ul>\n<li><strong>Treating the sampler as an uncertain voter, not an oracle.</strong> <a href=\"https://arxiv.org/abs/2203.11171\" target=\"_blank\">Self-consistency</a> is old news, but on AIMO3 it is not optional: single-run accuracy is much noisier than multi-run agreement. This is the single biggest delta above parthenos's baseline.</li>\n<li><strong>Persistent Jupyter kernels.</strong> One kernel per thread, created once at notebook startup, reused across all 50 problems. Import overhead for each <code>sympy</code>/<code>numpy</code>/<code>mpmath</code> call disappears. <code>BlockingKernelClient</code> + a per-thread port allocator avoids collisions that bite you as soon as you try to scale past K=2.</li>\n<li><strong>Harmony's <code>ReasoningEffort.HIGH</code> + <code>min_p=0.02</code>.</strong> The model's native training format outperforms any hand-crafted prompt I tried, including \"step by step\" and \"think carefully\" variants. This is also what techtech69 reports.</li>\n<li><strong>OS-page-cache weight preloading.</strong> 16 threads reading every weight file in 1 GB chunks before <code>vllm</code> starts saves ~270 s of startup. Every second saved here is a second available to the hardest problems.</li>\n<li><strong>In-stream <code>\\boxed{…}</code> scanning.</strong> Once a valid integer appears in the stream, close the connection. Don't wait for the model to finish.</li>\n<li><strong>Weighted voting (my B).</strong> Small but measurable lift on the upper tail of the score distribution. On average maybe +1, on the best submission +2.</li>\n</ul>\n<h3>7.2 Didn't work, or not for me</h3>\n<ul>\n<li><strong>Prompt engineering beyond \"rigorous competitor, never guess, box your answer\".</strong> Every longer system prompt I tried either did nothing or slightly hurt.</li>\n<li><strong>Temperature below 1.0.</strong> Distribution collapses, loops, fewer solution paths. Confirmed by techtech69's −8 result at 0.6.</li>\n<li><strong>Pushing K past 8.</strong> KV cache is the binding constraint on 1×H100 with <code>gpt-oss-120b</code>. 16 and 24 concurrent attempts are preempted by vLLM and score catastrophically worse. techtech69 reports −22 at K=24; I observed the same pattern at smaller scale.</li>\n<li><strong>Low <code>base_problem_timeout</code> with higher K.</strong> 100 s is not enough tokens to finish a hard problem. You lose more to truncated outputs than you gain from additional samples.</li>\n<li><strong>Fine-grained entropy-based trajectory scoring.</strong> daniil1423's ETS scoring is clever but in my hands it did not clearly dominate simple weighted majority. Others (Potrhino, techtech69) report stronger results with entropy; this is a \"methodology ≠ my hands\" disclaimer rather than a claim about the method.</li>\n</ul>\n<h2>8. Limitations and Things I Got Wrong</h2>\n<ol>\n<li><strong>I did not run controlled ablations.</strong> Each row in §6 is one submission or a handful of identical resubmissions. To claim \"my weighted voting beats raw majority by X points\", I would need to run both variants against the same problem set under the same scheduler noise, many times. I have not. The noise floor (σ ≈ 1.6) is wide enough that the 42-peak could plausibly come from a lucky draw on the ZaynYu base alone.</li>\n<li><strong>I did not verify weight-coefficient sensitivity.</strong> <code>+0.5 / +0.25 / −0.3</code> with a 0.5 error-rate threshold is just the first thing I tried. I don't know whether <code>+0.3 / +0.15 / −0.2</code> would be better, worse, or identical within the noise.</li>\n<li><strong>I piggybacked heavily.</strong> Contribution B is <em>small</em> on top of ZaynYu and daniil1423. Without their infrastructure — DynamicTime, AIMO3Solver, the kernel pool with <code>queue.Queue</code>, the refined system prompts — the weighted-vote rule has nothing to rest on. The right way to read this writeup is \"I added two small bricks to a wall that other people built most of\", not \"I solved AIMO3 my way\".</li>\n</ol>\n<h2>9. What I'd Do Differently</h2>\n<ul>\n<li><strong>Record every submission's per-problem answers.</strong> Without the per-problem breakdown, I can't tell which of the 50 problems my weighted vote actually flipped versus which were noise. Next time I'd log every <code>(problem_id, attempt_i, answer, python_calls, python_errors, token_len)</code> tuple to a file that's in the submission output, so I can do real ablation offline.</li>\n<li><strong>Try Qwen3-Next-80B-A3B-Thinking with a 262 k context.</strong> <code>gpt-oss-120b</code> caps out at ~43–44 on this hardware because its per-attempt accuracy on hard problems is ~5%. Both techtech69's and the host's pass@n data strongly suggest the gain from switching models is larger than the gain from any more voting tricks.</li>\n</ul>\n<h2>10. Reproducibility</h2>\n<p><strong>Notebooks:</strong></p>\n<ul>\n<li>Scaffold (contribution A, open source): <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><code>canqiang/self-consistency-strategy</code></a> (V12, 170 upvotes).</li>\n<li>42-score variant (contribution B): a fork of <a href=\"https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring\" target=\"_blank\"><code>daniil1423/entropy-trajectory-scoring</code></a> with the <code>_select_answer</code> method replaced by the 20-line rule in §4.3. Currently private; I'll open-source it shortly.</li>\n</ul>\n<p><strong>Key configuration for the 42-score submission:</strong></p>\n<pre><code>class Config:\n    model_path               = '/kaggle/input/gpt-oss-120b/transformers/default/1'\n    served_model_name        = 'gpt-oss'\n    context_tokens           = 65536\n    kv_cache_dtype           = 'fp8_e4m3'\n    gpu_memory_utilization   = 0.96\n    batch_size               = 256\n\n    temperature              = 1.0\n    top_p                    = 1.0\n    min_p                    = 0.02\n    seed                     = 42\n    attempts                 = 8\n    workers                  = 16\n    early_stop               = 5\n    turns                    = 128\n\n    high_problem_timeout     = 900\n    base_problem_timeout     = 300\n    notebook_limit           = 17400\n    sandbox_timeout          = 3\n    jupyter_timeout          = 10\n</code></pre>\n<p><strong>Hardware:</strong> 1×H100 85GB, Kaggle competition runtime, 5h wall clock.</p>\n<p><strong>Expected variance:</strong> μ ≈ 38, σ ≈ 1.6 across identical-code submissions. A single run scoring in <code>[35, 42]</code> should be considered a successful reproduction.</p>\n<hr>\n<h2>11. Acknowledgements</h2>\n<p>Most of what is in this notebook is not mine. I want to name the people whose work I built on, in the order I inherited it:</p>\n<ul>\n<li><strong>Kawchar Husain</strong>, for the original prompt structure that parthenos forked from.</li>\n<li><strong><a href=\"https://www.kaggle.com/nihilisticneuralnet\" target=\"_blank\">parthenos (nihilisticneuralnet)</a></strong>, for publishing <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\"><code>aimo3-streaming-inference-reflexion-prompting</code></a> — the streaming-inference reflexion prompt scaffold that my SC+TIR notebook merges with shelterw's line.</li>\n<li><strong><a href=\"https://www.kaggle.com/shelterw\" target=\"_blank\">shelterw</a></strong>, for <a href=\"https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool\" target=\"_blank\"><code>[Way to 30+/50] GPT-OSS - w/ python tool</code></a>, the other upstream I merged into the SC notebook.</li>\n<li><strong><a href=\"https://www.kaggle.com/zaynyu\" target=\"_blank\">ZaynYu</a></strong>, for turning my SC+TIR scaffold into a class-structured solver with dynamic time budgeting and a proper sandbox pool — the infrastructure my weighted-voting fork runs on.</li>\n<li><strong><a href=\"https://www.kaggle.com/daniil1423\" target=\"_blank\">daniil1423</a></strong>, for the <a href=\"https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring\" target=\"_blank\">entropy-trajectory-scoring notebook</a> that my 42-score fork directly modifies.</li>\n<li><strong><a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b\" target=\"_blank\">techtech69</a></strong> and <strong><a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/potrhino-strategy-for-aimo3-adaptive-test-time-op\" target=\"_blank\">Potrhino</a></strong>, whose AIMO3 writeups on entropy-weighted voting and DeepConf-inspired pruning shaped how I now think about the \"voting as uncertainty estimator\" framing in §7.</li>\n</ul>\n<p>If you are one of these people and I have miscredited any part of your work, please tell me and I will correct this writeup.</p>\n<h2>12. References</h2>\n<p>Writeups / notebooks directly referenced above:</p>\n<ul>\n<li>techtech69, <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b\" target=\"_blank\"><em>Entropy-Weighted Majority Voting with gpt-oss-120b for AIMO3</em></a> (85th place, Public LB 43). Kaggle writeup.</li>\n<li>Potrhino, <a href=\"https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/potrhino-strategy-for-aimo3-adaptive-test-time-op\" target=\"_blank\"><em>Adaptive Test-Time Optimization for gpt-oss-120b</em></a> (91st place, Public LB 43). Kaggle writeup.</li>\n<li>parthenos (nihilisticneuralnet), <a href=\"https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting\" target=\"_blank\"><em>AIMO3: streaming-inference reflexion prompting</em></a> (V1).</li>\n<li>ShelterW, <a href=\"https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool\" target=\"_blank\"><em>[Way to 30+/50] GPT-OSS — w/ python tool</em></a>.</li>\n<li>canqiang (me), <a href=\"https://www.kaggle.com/code/canqiang/self-consistency-strategy\" target=\"_blank\"><em>Self-Consistency Strategy</em></a> (V12).</li>\n<li>ZaynYu, <a href=\"https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool\" target=\"_blank\"><em>[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool</em></a> (V26).</li>\n<li>daniil1423, <a href=\"https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring\" target=\"_blank\"><em>entropy-trajectory-scoring</em></a>.</li>\n</ul>\n<p>External methodology references:</p>\n<ul>\n<li>Wang et al., <a href=\"https://arxiv.org/abs/2203.11171\" target=\"_blank\"><em>Self-Consistency Improves Chain of Thought Reasoning in Language Models</em></a>, arXiv:2203.11171.</li>\n<li>Wei et al., <a href=\"https://arxiv.org/abs/2201.11903\" target=\"_blank\"><em>Chain-of-Thought Prompting Elicits Reasoning in Large Language Models</em></a>, arXiv:2201.11903.</li>\n<li>Lin &amp; Xu, <a href=\"https://arxiv.org/abs/2508.19201\" target=\"_blank\"><em>Understanding Tool-Integrated Reasoning</em></a>, arXiv:2508.19201.</li>\n<li>Fu et al., <a href=\"https://arxiv.org/abs/2508.15260\" target=\"_blank\"><em>Deep Think with Confidence</em></a>, arXiv:2508.15260.</li>\n<li>OpenAI, <a href=\"https://arxiv.org/abs/2508.10925\" target=\"_blank\"><em>gpt-oss-120b &amp; gpt-oss-20b Model Card</em></a>, arXiv:2508.10925.</li>\n<li>Kwon et al., <a href=\"https://arxiv.org/abs/2309.06180\" target=\"_blank\"><em>vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention</em></a>, SOSP 2023.</li>\n</ul>",
      "rawMarkdown": "## 1. TL;DR\n\nTwo concrete, publicly verifiable contributions to the AIMO3 open-source lineage:\n\n**A. SC + TIR scaffold on top of parthenos's streaming baseline.** I published [`Self-Consistency Strategy`](https://www.kaggle.com/code/canqiang/self-consistency-strategy) (notebook slug: `self-consistency-strategy`, V12, 170 upvotes). It merges [parthenos's streaming-inference reflexion prompting notebook](https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting) (score 27) with [shelterw's Python-tool line](https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool), and adds what those notebooks lacked: (i) the `openai_harmony` chat template with `ReasoningEffort.HIGH`, (ii) a per-thread persistent Jupyter kernel (`BlockingKernelClient` + port-pool allocator), (iii) K=8 parallel self-consistency with in-stream `\\boxed{…}` scanning and a majority-threshold early-stop, (iv) a 16-thread OS-page-cache weight preloader that cuts vLLM startup from ~400 s to ~130 s. This notebook became the foundation ZaynYu forked into [`[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool`](https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool) (615 upvotes, Public LB 40).\n\n**B. Python-verification-weighted voting.** In the ZaynYu → daniil1423 → my fork chain, the only non-trivial change I made to the voting logic was to weight each attempt's vote by whether it used the Python tool:\n\n- base weight 1.0\n- +0.5 if the attempt made ≥ 3 tool calls\n- +0.25 if the attempt made ≥ 1 tool call\n- −0.3 if > 50% of its tool calls errored\n\nTie-break key: `(weighted_votes, raw_votes, total_calls)`. This pushed my best same-code submission from the 35–40 band (ZaynYu) to 42/50 peak over n=25 V2 submissions (μ = 38.44, σ = 1.58).\n\nNeither contribution changes the ceiling by much — the ceiling is set by `gpt-oss-120b`'s pass@k on this problem set — but both are small, reproducible, and the scaffold in (A) is demonstrably load-bearing downstream.\n\n---\n\n## 2. Competition Setup\n\nAIMO3 gives 50 IMO-style problems with integer answers in `[0, 99999]`. Each submission is scored twice; a problem earns 1.0 if both runs agree and are correct, 0.5 if one run is correct, and 0 otherwise. Inference runs offline on a single NVIDIA H100-85GB under a 5-hour wall-clock limit. Models must have been released before 2026-03-15.\n\nI used `gpt-oss-120b` (120B parameters, MXFP4 weights, ~65 GB VRAM) served via `vLLM==0.11.2`. The KV cache budget on 1×H100 with this model is about 15–16 GB, which constrains safe concurrent requests to roughly 8.\n\n## 3. Lineage and Honest Attribution\n\nThis is the relevant portion of the public fork tree. Arrows point from upstream to downstream; numbers in parentheses are approximate Public LB peaks reported in each notebook's title or comments.\n\n```\nKawchar Husain                                       (upstream prompt template)\n        │\n        ▼\nparthenos · aimo3-streaming-inference-reflexion-prompting (V1, 27)\n        │   streaming inference + reflexion prompting; no TIR; no Harmony\n        │\nshelterw · way-to-30-50-gpt-oss-w-python-tool          (parallel upstream: simple Python tool loop)\n        │\n        ▼\ncanqiang (me) · self-consistency-strategy (V12, 32)    ← Contribution A\n        │   + Harmony protocol (ReasoningEffort.HIGH)\n        │   + per-thread persistent Jupyter kernel pool\n        │   + K=8 parallel SC with in-stream \\boxed scanning + early-stop\n        │   + 16-thread OS-page-cache weight preloader\n        │\n        ▼\nZaynYu · [40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool (V26, 40)\n        │   + dynamic per-problem time budget\n        │   + class refactor (AIMO3Solver / AIMO3Sandbox / AIMO3Tool)\n        │   + refined system prompts (\"world-class IMO competitor\", \"Never guess\")\n        │\n        ▼\ndaniil1423 · entropy-trajectory-scoring (40)\n        │   + logprob/entropy-based trajectory scoring (I did not use this part)\n        │\n        ▼\ncanqiang (me) · fork of ETS (\"Weighted Voting with Python Verification\" V2, 42)   ← Contribution B\n            + python-call-count & error-rate weighted voting\n            (kept the rest of the ETS/ZaynYu infrastructure unchanged)\n```\n\nTwo things I want to be explicit about:\n\n1. The 42-score notebook was a **private fork during the competition** (I judged the delta over daniil1423 to be small enough that a separate public notebook during the competition was not obviously worth it). I plan to open-source it after the writeup period. The 170-vote notebook I published earlier is the SC+TIR scaffold (contribution A), not the 42-score fork.\n2. The DynamicTime budget, the AIMO3Solver class refactor, and the entropy-trajectory machinery are **ZaynYu's and daniil1423's work**, not mine. The only voting-logic delta I contributed is the four-rule weighting above.\n\n## 4. System Overview\n\n### 4.1 Inference stack\n\n- `gpt-oss-120b`, native MXFP4 weights, served by `vllm` 0.11.2.\n- `--kv-cache-dtype fp8_e4m3`, `--max-model-len 65536`, `--gpu-memory-utilization 0.96`, `--max-num-seqs 256`, `--async-scheduling`.\n- `openai_harmony` for the chat template. System message is constructed with `SystemContent.new().with_reasoning_effort(ReasoningEffort.HIGH).with_tools(python_tool.tool_config)`, which is the native format `gpt-oss-120b` was post-trained on.\n- Sampling: `temperature=1.0`, `top_p=1.0`, `min_p=0.02`. Temperature is **not** a free knob for aligned models — [techtech69's writeup](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b) (85th, public 43) documents an 8-point drop when they went to 0.6. My ablations agree.\n\n### 4.2 Per-problem loop\n\nEach incoming problem is handled by `K=8` worker threads sharing a `ThreadPoolExecutor`. Each thread:\n\n1. Acquires one persistent `AIMO3Sandbox` (Jupyter kernel) from a pool.\n2. Runs up to 128 reasoning turns. Each turn calls vLLM with `stream=True, return_token_ids=True`, streams tokens while:\n   - checking a shared `stop_event` and the per-problem deadline,\n   - scanning incoming text for `\\boxed{…}` and bailing out as soon as a valid integer in `[0, 99999]` is found.\n3. If the model emitted a `python` tool call, the sandbox executes the code in a stateful kernel and the output is fed back as a new conversation message. `python_calls` and `python_errors` are tracked per attempt.\n4. When any 5/8 attempts agree on the same answer (`early_stop = 5`), the stop event fires and the remaining threads are cancelled.\n\n### 4.3 Voting (my contribution B)\n\nAfter the parallel sweep, votes are aggregated with four small rules on top of raw majority:\n\n```python\n# AIMO3Solver._select_answer, used in the 42-score fork of ETS V2\nfor result in detailed_results:\n    answer = result['Answer']\n    if answer is None:\n        continue\n    weight = 1.0\n    calls  = result['Python Calls']\n    errors = result['Python Errors']\n    if calls >= 3:\n        weight += 0.5         # strong Python-verified answer\n    elif calls >= 1:\n        weight += 0.25        # at least one Python check\n    if calls > 0 and errors / calls > 0.5:\n        weight -= 0.3         # high error rate → unreliable\n    stats[answer]['weighted_votes'] += weight\n    stats[answer]['votes']  += 1\n    stats[answer]['calls']  += calls\n    stats[answer]['errors'] += errors\n\n# Tie-break: weighted votes > raw votes > total Python calls\nreturn max(stats.items(),\n           key=lambda x: (x[1]['weighted_votes'],\n                          x[1]['votes'],\n                          x[1]['calls']))[0]\n```\n\nThe intuition is trivial: if an answer was arrived at by an attempt that ran Python code several times and those calls mostly returned without an exception, it is more likely to be correct than an answer the model guessed without verification. The coefficients (0.25 / 0.5 / 0.3 / threshold 0.5) are not tuned; they are round numbers that fell out of the first thing I tried. The contribution is the *structure* of the weighting, not the specific values.\n\n## 5. Reproducibility and the Noise Floor\n\nRunning the same notebook twice on Kaggle does *not* give the same score. This is not a subtle effect and it is not my claim — it is reported by both techtech69 and ZaynYu in their own writeups / comments. On vLLM, batched completion order depends on GPU scheduling, floating-point associativity perturbs the softmax, and downstream token sampling diverges.\n\n### 5.1 Parthenos's upstream (no SC, no TIR): very noisy, centred low\n\nFrom public comments on [parthenos's `aimo3-streaming-inference-reflexion-prompting`](https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting) V1 (author score 27):\n\n| Forker | Score |\n|---|---|\n| Poemcourt (copy, no changes) | 26 |\n| Dipankar Mitra (copy, no changes) | 21 |\n| CloudYU | 22 |\n| Octavi Grau | 16 |\n| Artem Goncharov | 18 |\n| swordsman (after increasing timeout) | 22 |\n\nMany more hit \"Notebook threw exception\". Spread is roughly 16–26 against an author-reported 27.\n\n### 5.2 My SC+TIR scaffold (contribution A): higher and tighter\n\nFrom the comment on my [`self-consistency-strategy`](https://www.kaggle.com/code/canqiang/self-consistency-strategy):\n\n> *\"i scored 35 with no changes…\"* — cm391\n\nAuthor peak on that notebook was 32 on LB; the commenter got 35 with zero changes, and downstream forks that layered additional infrastructure (ZaynYu, daniil1423) reached 40+.\n\n### 5.3 ZaynYu's fork of my scaffold: the best community reproduction data\n\nZaynYu's [`[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool`](https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool) (615 upvotes, 1,362 copies) has 57 comments and is the most-forked downstream child of my SC scaffold. A selection of the scores people reported, quoted literally from that comment thread:\n\n| Forker | Variant | Public LB |\n|---|---|---|\n| Tong Hui Kang | V1 (direct copy) | 38 |\n| Tong Hui Kang | V2 | 35 |\n| Tong Hui Kang | V10 | 36 |\n| Tong Hui Kang | V12 | 36 |\n| Siancy (\"Same as parthenos's, no modifications\") | V1 | 41 |\n| THUNDER THUNDER | V01 | 40 |\n| THUNDER THUNDER | V02 | 36 |\n| Abhijeet Bhargava | V01 / V03 / V05 | 38 / 35 / 34 |\n| chenjixuan666 (fork of Siancy) | V01 | 38 |\n| parthenos (on ZaynYu's V15) | — | 37 |\n| Dipankar Mitra | submitted twice | 33 / 33 |\n\nZaynYu himself on his own notebook:\n\n> *\"The score of the LB by running the same notebook is not guaranteed to be the same.\"*\n\nSo, empirically, the scaffold I contributed (A) sits downstream of parthenos's 16–26 band and supports a community reproduction band of roughly 34–41 on top of the same hardware.\n\n### 5.4 My own V2 notebook (contribution B): 25 identical submissions\n\nI submitted the same V2 code 25 times to measure the noise floor:\n\n- n = 25\n- min = 35\n- max = 42\n- mean = 38.44\n- std  = 1.58\n\nA single run scoring 42 is well inside the tail; a single run scoring 35 is also inside the tail. This is why I frame the Python-weighted voting as \"pushed the ceiling up by ~2 points\", not \"solves more problems\". The voting change is not the dominant source of score; the model and the TIR loop are.\n\n## 6. Ablations\n\nEverything in this table is a single-submission LB score from my own submission list. They are not independent trials — each number is a draw from a noisy distribution with σ ≈ 1–2 on top of a ~35–42 base. I report them with that caveat.\n\n| Configuration | Best | Mean | N | Notes |\n|---|---:|---:|---:|---|\n| Weighted Voting w/ Python Verification (V2, contribution B) | **42** | 38.44 | 25 | Peak and baseline for my work |\n| ans_verifys (verifier variant) | 41 | 37.67 | 6 | Different verification logic, similar spread |\n| entropy-trajectory-scoring (daniil1423's logprob-entropy scoring) | 39 | 36.78 | 9 | Without my weighted voting, entropy scoring alone |\n| Dual Entropy-Weighted Voting | 37 | 35.71 | 7 | Combining two entropy signals |\n| ZaynYu-style direct fork (36/40 variant) | 34 | 32.67 | 3 | Before my voting change |\n| self-consistency-strategy V12 (contribution A, public) | 32 | — | 2 | Before any voting change; scaffold only |\n| parthenos direct fork (streaming + reflexion, no TIR) | 26 | 23 | 2 | Upstream baseline |\n| improved-tir-solution | 25 | 21 | 3 | Different TIR formulation — didn't pay off |\n\nThe progression from parthenos → SC+TIR scaffold → ZaynYu's DynamicTime → weighted voting is visible across my own submissions, not just across the public fork tree.\n\n## 7. What Did and Did Not Matter\n\n### 7.1 Worked\n\n- **Treating the sampler as an uncertain voter, not an oracle.** [Self-consistency](https://arxiv.org/abs/2203.11171) is old news, but on AIMO3 it is not optional: single-run accuracy is much noisier than multi-run agreement. This is the single biggest delta above parthenos's baseline.\n- **Persistent Jupyter kernels.** One kernel per thread, created once at notebook startup, reused across all 50 problems. Import overhead for each `sympy`/`numpy`/`mpmath` call disappears. `BlockingKernelClient` + a per-thread port allocator avoids collisions that bite you as soon as you try to scale past K=2.\n- **Harmony's `ReasoningEffort.HIGH` + `min_p=0.02`.** The model's native training format outperforms any hand-crafted prompt I tried, including \"step by step\" and \"think carefully\" variants. This is also what techtech69 reports.\n- **OS-page-cache weight preloading.** 16 threads reading every weight file in 1 GB chunks before `vllm` starts saves ~270 s of startup. Every second saved here is a second available to the hardest problems.\n- **In-stream `\\boxed{…}` scanning.** Once a valid integer appears in the stream, close the connection. Don't wait for the model to finish.\n- **Weighted voting (my B).** Small but measurable lift on the upper tail of the score distribution. On average maybe +1, on the best submission +2.\n\n### 7.2 Didn't work, or not for me\n\n- **Prompt engineering beyond \"rigorous competitor, never guess, box your answer\".** Every longer system prompt I tried either did nothing or slightly hurt.\n- **Temperature below 1.0.** Distribution collapses, loops, fewer solution paths. Confirmed by techtech69's −8 result at 0.6.\n- **Pushing K past 8.** KV cache is the binding constraint on 1×H100 with `gpt-oss-120b`. 16 and 24 concurrent attempts are preempted by vLLM and score catastrophically worse. techtech69 reports −22 at K=24; I observed the same pattern at smaller scale.\n- **Low `base_problem_timeout` with higher K.** 100 s is not enough tokens to finish a hard problem. You lose more to truncated outputs than you gain from additional samples.\n- **Fine-grained entropy-based trajectory scoring.** daniil1423's ETS scoring is clever but in my hands it did not clearly dominate simple weighted majority. Others (Potrhino, techtech69) report stronger results with entropy; this is a \"methodology ≠ my hands\" disclaimer rather than a claim about the method.\n\n## 8. Limitations and Things I Got Wrong\n\n1. **I did not run controlled ablations.** Each row in §6 is one submission or a handful of identical resubmissions. To claim \"my weighted voting beats raw majority by X points\", I would need to run both variants against the same problem set under the same scheduler noise, many times. I have not. The noise floor (σ ≈ 1.6) is wide enough that the 42-peak could plausibly come from a lucky draw on the ZaynYu base alone.\n2. **I did not verify weight-coefficient sensitivity.** `+0.5 / +0.25 / −0.3` with a 0.5 error-rate threshold is just the first thing I tried. I don't know whether `+0.3 / +0.15 / −0.2` would be better, worse, or identical within the noise.\n3. **I piggybacked heavily.** Contribution B is *small* on top of ZaynYu and daniil1423. Without their infrastructure — DynamicTime, AIMO3Solver, the kernel pool with `queue.Queue`, the refined system prompts — the weighted-vote rule has nothing to rest on. The right way to read this writeup is \"I added two small bricks to a wall that other people built most of\", not \"I solved AIMO3 my way\".\n\n## 9. What I'd Do Differently\n\n- **Record every submission's per-problem answers.** Without the per-problem breakdown, I can't tell which of the 50 problems my weighted vote actually flipped versus which were noise. Next time I'd log every `(problem_id, attempt_i, answer, python_calls, python_errors, token_len)` tuple to a file that's in the submission output, so I can do real ablation offline.\n- **Try Qwen3-Next-80B-A3B-Thinking with a 262 k context.** `gpt-oss-120b` caps out at ~43–44 on this hardware because its per-attempt accuracy on hard problems is ~5%. Both techtech69's and the host's pass@n data strongly suggest the gain from switching models is larger than the gain from any more voting tricks.\n\n## 10. Reproducibility\n\n**Notebooks:**\n\n- Scaffold (contribution A, open source): [`canqiang/self-consistency-strategy`](https://www.kaggle.com/code/canqiang/self-consistency-strategy) (V12, 170 upvotes).\n- 42-score variant (contribution B): a fork of [`daniil1423/entropy-trajectory-scoring`](https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring) with the `_select_answer` method replaced by the 20-line rule in §4.3. Currently private; I'll open-source it shortly.\n\n**Key configuration for the 42-score submission:**\n\n```python\nclass Config:\n    model_path               = '/kaggle/input/gpt-oss-120b/transformers/default/1'\n    served_model_name        = 'gpt-oss'\n    context_tokens           = 65536\n    kv_cache_dtype           = 'fp8_e4m3'\n    gpu_memory_utilization   = 0.96\n    batch_size               = 256\n\n    temperature              = 1.0\n    top_p                    = 1.0\n    min_p                    = 0.02\n    seed                     = 42\n    attempts                 = 8\n    workers                  = 16\n    early_stop               = 5\n    turns                    = 128\n\n    high_problem_timeout     = 900\n    base_problem_timeout     = 300\n    notebook_limit           = 17400\n    sandbox_timeout          = 3\n    jupyter_timeout          = 10\n```\n\n**Hardware:** 1×H100 85GB, Kaggle competition runtime, 5h wall clock.\n\n**Expected variance:** μ ≈ 38, σ ≈ 1.6 across identical-code submissions. A single run scoring in `[35, 42]` should be considered a successful reproduction.\n\n---\n\n## 11. Acknowledgements\n\nMost of what is in this notebook is not mine. I want to name the people whose work I built on, in the order I inherited it:\n\n- **Kawchar Husain**, for the original prompt structure that parthenos forked from.\n- **[parthenos (nihilisticneuralnet)](https://www.kaggle.com/nihilisticneuralnet)**, for publishing [`aimo3-streaming-inference-reflexion-prompting`](https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting) — the streaming-inference reflexion prompt scaffold that my SC+TIR notebook merges with shelterw's line.\n- **[shelterw](https://www.kaggle.com/shelterw)**, for [`[Way to 30+/50] GPT-OSS - w/ python tool`](https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool), the other upstream I merged into the SC notebook.\n- **[ZaynYu](https://www.kaggle.com/zaynyu)**, for turning my SC+TIR scaffold into a class-structured solver with dynamic time budgeting and a proper sandbox pool — the infrastructure my weighted-voting fork runs on.\n- **[daniil1423](https://www.kaggle.com/daniil1423)**, for the [entropy-trajectory-scoring notebook](https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring) that my 42-score fork directly modifies.\n- **[techtech69](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b)** and **[Potrhino](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/potrhino-strategy-for-aimo3-adaptive-test-time-op)**, whose AIMO3 writeups on entropy-weighted voting and DeepConf-inspired pruning shaped how I now think about the \"voting as uncertainty estimator\" framing in §7.\n\nIf you are one of these people and I have miscredited any part of your work, please tell me and I will correct this writeup.\n\n## 12. References\n\nWriteups / notebooks directly referenced above:\n\n- techtech69, [*Entropy-Weighted Majority Voting with gpt-oss-120b for AIMO3*](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/entropy-weighted-majority-voting-with-gpt-oss-120b) (85th place, Public LB 43). Kaggle writeup.\n- Potrhino, [*Adaptive Test-Time Optimization for gpt-oss-120b*](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/potrhino-strategy-for-aimo3-adaptive-test-time-op) (91st place, Public LB 43). Kaggle writeup.\n- parthenos (nihilisticneuralnet), [*AIMO3: streaming-inference reflexion prompting*](https://www.kaggle.com/code/nihilisticneuralnet/aimo3-streaming-inference-reflexion-prompting) (V1).\n- ShelterW, [*[Way to 30+/50] GPT-OSS — w/ python tool*](https://www.kaggle.com/code/shelterw/way-to-30-50-gpt-oss-w-python-tool).\n- canqiang (me), [*Self-Consistency Strategy*](https://www.kaggle.com/code/canqiang/self-consistency-strategy) (V12).\n- ZaynYu, [*[40/50] GPT-OSS-120B TIR+DynamicTime+KernelPool*](https://www.kaggle.com/code/zaynyu/40-50-gpt-oss-120b-tir-dynamictime-kernelpool) (V26).\n- daniil1423, [*entropy-trajectory-scoring*](https://www.kaggle.com/code/daniil1423/entropy-trajectory-scoring).\n\nExternal methodology references:\n\n- Wang et al., [*Self-Consistency Improves Chain of Thought Reasoning in Language Models*](https://arxiv.org/abs/2203.11171), arXiv:2203.11171.\n- Wei et al., [*Chain-of-Thought Prompting Elicits Reasoning in Large Language Models*](https://arxiv.org/abs/2201.11903), arXiv:2201.11903.\n- Lin & Xu, [*Understanding Tool-Integrated Reasoning*](https://arxiv.org/abs/2508.19201), arXiv:2508.19201.\n- Fu et al., [*Deep Think with Confidence*](https://arxiv.org/abs/2508.15260), arXiv:2508.15260.\n- OpenAI, [*gpt-oss-120b & gpt-oss-20b Model Card*](https://arxiv.org/abs/2508.10925), arXiv:2508.10925.\n- Kwon et al., [*vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention*](https://arxiv.org/abs/2309.06180), SOSP 2023.\n",
      "votes": 4
    }
  ],
  "complete": true,
  "source": "live",
  "fetched_at": "2026-10-20T04:20:37Z",
  "competition_id": 118448,
  "competition_slug": "ai-mathematical-olympiad-progress-prize-3",
  "team_id": 14841586,
  "solution_url": "/competitions/ai-mathematical-olympiad-progress-prize-3/writeups/self-consistency-tir-with-python-verification"
}