HEAD: T2 planner objective - timing_weight 2.0 + split_days 3 - CV 1541.3
Browse fileslam2sp3 from the T2 planner lane: scale timing curves x2 inside
optimize_days' objective (new BATTERYSWAP_TIMING_WEIGHT dial, default
2.0) and SPLIT_DAYS default 7->3. Refuses cheap trip-merges that drag
swaps off timing-optimal days: late -3.5, early -1.2, mobility +0.8.
bgkf paired vs 1545.4 champion: -4.11 +/- 1.41 (2.9sigma), 25W/4L,
Wilcoxon 8.8e-6, count-flat (battery sets cell-identical); dose-response
plateau on both dials; survives 35-arm multiplicity. New-mechanism tier
(2sigma + controls) PASSED. Deployment parity: cand ft2a10 cell-exact
(diff 0.0) vs the lane measurement; timing_weight=1.0 legacy path
bit-exact vs pre-T2 reference (ft2a10_sp7 control). End-to-end pseudo-
split rehearsal clean (static held-out branch, 0 warnings, 38s).
Also: phases 63-64 records (public conversion 1575.31 at 4c93883;
five-lane T2 campaign - timing/order/hazard axes closed with structure,
counts lane report-only incl. warmup-gated alpha 1488.0 for a possible
public trigger) + the five t2_*.md lane reports.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- EXPERIMENTS.md +72 -0
- agent_reports_bgkf/t2_counts.md +180 -0
- agent_reports_bgkf/t2_hazard.md +97 -0
- agent_reports_bgkf/t2_order.md +109 -0
- agent_reports_bgkf/t2_planner.md +120 -0
- agent_reports_bgkf/t2_timing.md +126 -0
- batteryswap_example/cv.py +10 -4
- batteryswap_example/models_cv.py +3 -2
- batteryswap_example/submit.py +10 -1
|
@@ -3319,3 +3319,75 @@ rehearsal measured 922-device splits = the safe 2x regime); alpha 1.0 best
|
|
| 3319 |
at EVERY scale with recall +7pts held (third independent support for the
|
| 3320 |
296f8f2 public A/B); runtime 3.4s/scenario at 4x - no budget risk. Full
|
| 3321 |
tables: agent_reports_bgkf/c3_findings.md.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3319 |
at EVERY scale with recall +7pts held (third independent support for the
|
| 3320 |
296f8f2 public A/B); runtime 3.4s/scenario at 4x - no budget risk. Full
|
| 3321 |
tables: agent_reports_bgkf/c3_findings.md.
|
| 3322 |
+
|
| 3323 |
+
## Phase 63 - PUBLIC CONVERSION: head 4c93883 measured 1575.31 (deadline day); wave T all dead
|
| 3324 |
+
|
| 3325 |
+
The user triggered public scoring on head 4c93883 (CV 1545.4; values
|
| 3326 |
+
lb(vm7)@alpha1.0, order .50 logbag + .30 wiener + .20 gapHGB,
|
| 3327 |
+
value-preserving): **public 1575.31**, -86.1 vs the 3c7b883 champion's
|
| 3328 |
+
1661.45. Components invert to exact integers (clean run, default
|
| 3329 |
+
settings, 48 scenarios): 644 swaps (13.4/scen, was 580 at alpha .8),
|
| 3330 |
+
5009 late-days (104.4/scen, was ~121), 19716 early-days. CV->public
|
| 3331 |
+
transfer +29.9 (~2%): bgkf v5 priced the whole stack (ft2 ordering +
|
| 3332 |
+
alpha 1.0 + gap-HGB + weight tweaks) correctly - the first
|
| 3333 |
+
locally-validated intervention stack to survive public after three
|
| 3334 |
+
pre-bgkf refutations. PRIVATE SELECTION: 4c93883 (hedge slot, if any:
|
| 3335 |
+
3c7b883).
|
| 3336 |
+
|
| 3337 |
+
Wave T (post-ship, 13 arms, paired vs 1545.4): ALL DEAD - the champion
|
| 3338 |
+
is a local optimum on every axis touched. Wiener THRESH 2.40 beats
|
| 3339 |
+
2.38/2.42 (+39/+45 - the labeled barrier is also the ordering-optimal
|
| 3340 |
+
barrier); K_SHRINK 6 vs 3/12 flat/+9; gap-weight .15 shelf +30/+29;
|
| 3341 |
+
gapHGB seed-bag +34 at 2.0sig (seed-0 is favorable; do NOT "stabilize"
|
| 3342 |
+
it away) and lr .03 +12; rank-shape transforms pow2/sqrt/logit
|
| 3343 |
+
+4/+42/+58 (linear pct-rank blending confirmed); GAP4 inside the logbag
|
| 3344 |
+
order-primary +123 at 2.3sig (gap features only work as a separate
|
| 3345 |
+
voice); RankNet 4th source at .10 +22. Driver /tmp/c9/run.py (volatile).
|
| 3346 |
+
|
| 3347 |
+
## Phase 64 - T2 five-lane subagent campaign on the 1545.4 champion: one adoption (lam2sp3 planner objective), four axes closed with structure
|
| 3348 |
+
|
| 3349 |
+
Five parallel lanes, each paired vs the champion on bgkf (reports:
|
| 3350 |
+
agent_reports_bgkf/t2_{timing,planner,order,counts,hazard}.md):
|
| 3351 |
+
|
| 3352 |
+
- TIMING: closed. Early cost decomposed - 74% imputed-EOL false positives
|
| 3353 |
+
(never die in-window), 19% real deaths beyond the window, 7% genuine
|
| 3354 |
+
early timing; planner packing is 0.6%. Every date shift trades early
|
| 3355 |
+
for late at slope >=0.86; best arms 1.0sig AND count-coupled. EARLY is
|
| 3356 |
+
a selection problem, not a dates problem.
|
| 3357 |
+
- PLANNER: **ADOPTED lam2sp3** - timing curves x2 inside optimize_days'
|
| 3358 |
+
objective (new TIMING_WEIGHT dial) + SPLIT_DAYS 7->3. -4.11 +/- 1.41
|
| 3359 |
+
(2.9sig), 25W/4L, Wilcoxon 8.8e-6, count-flat with battery sets
|
| 3360 |
+
cell-identical; dose-response plateau on both dials; additivity checks;
|
| 3361 |
+
survives ~35-arm multiplicity (sign p 1e-4). Mechanism: refuses cheap
|
| 3362 |
+
trip-merges that drag swaps off timing-optimal days (late -3.5, early
|
| 3363 |
+
-1.2, mobility +0.8). Also: plan-phase scheduling is SATURATED past its
|
| 3364 |
+
own surrogate optimum (exact enumeration is +5.1 WORSE - shallow search
|
| 3365 |
+
is an accidental regularizer; closes the CP-SAT question for good);
|
| 3366 |
+
of 232/scen "ops" cost only 78 is schedulable, 154 rides on missed
|
| 3367 |
+
swaps (recall in disguise).
|
| 3368 |
+
- ORDER: closed. Boundary cascade fails structurally (cutoffs are n~2-3,
|
| 3369 |
+
the band IS the confident top; +147 at 2.6sig); per-building rank
|
| 3370 |
+
normalization catastrophic (+549/+939, 7-8sig) - global pooled ranking
|
| 3371 |
+
is load-bearing; prob-space blending loses to rank-space (+76). The
|
| 3372 |
+
rank-gap-1-10 frontier is unreachable by aggregation on this table.
|
| 3373 |
+
- COUNTS (all report-only): flat alpha 1.1-1.5 dead (podium-posture 1.4
|
| 3374 |
+
is a 1.0sig coin-flip, median-worse); calibrated counts REFUTED with a
|
| 3375 |
+
count-matched control (+67.5 at 3.4sig - allocation failure); risk-N
|
| 3376 |
+
refuted. Headline: warmup-gated alpha 1.4 (s_0-7 only) -> 1488.0,
|
| 3377 |
+
-57.4 +/- 22.0 (2.6sig nominal, post-hoc block, 8-scenario support,
|
| 3378 |
+
count-coupled) - candidate for a public trigger, user's call.
|
| 3379 |
+
- HAZARD: closed for the deadline. dth3 crash fixed; discrete-time
|
| 3380 |
+
hazard HGB is a standalone statistical peer of the 3-way blend
|
| 3381 |
+
(h_alone 1537.0, 25W/22L) with its edge at COLD-START origins
|
| 3382 |
+
(censored-pool training; warmup -178/cell) - converges with the counts
|
| 3383 |
+
lane on warmup as the only exploitable block; unresolvable at 2sig on
|
| 3384 |
+
8 cells of +/-800 scatter. AFT-lite dead on arrival.
|
| 3385 |
+
|
| 3386 |
+
SHIP (lam2sp3): submit.py TIMING_WEIGHT (default 2.0, env
|
| 3387 |
+
BATTERYSWAP_TIMING_WEIGHT) + SPLIT_DAYS default 7->3; models_cv.py
|
| 3388 |
+
plan_tsroute.timing_weight attr (default 1.0 = old path bit-exact,
|
| 3389 |
+
verified: ft2a10_sp7 control cell-diff 0.0 vs pre-T2 reference);
|
| 3390 |
+
cv.py run_bgkf split_days/timing_weight hooks, ft2a10/head track the
|
| 3391 |
+
deployed dials. Verified: cand ft2a10 = 1541.3, cell-exact (0.0) vs the
|
| 3392 |
+
lane's lam2sp3 measurement; paired -4.11 +/- 1.41 (2.9sig) 25W/4L
|
| 3393 |
+
p8.8e-6, swaps flat 2.27. New champion CV 1541.3.
|
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# T2 COUNTS — count/appetite response surface at the new ordering (campaign 5-agent, 2026-08-23)
|
| 2 |
+
|
| 3 |
+
Champion (4c93883, untouched): submit.Ft2RUL = values/counts logbag(vm7),
|
| 4 |
+
ORDER .50 lb + .30 wienerFHT + .20 gapHGB (value-preserving), planner alpha
|
| 5 |
+
1.0. Ref /tmp/cv_bgkfcand_ft2a10.csv, SCORE 1545.4. All work in /tmp/c13/
|
| 6 |
+
(run.py, diag.py, table.py, per-arm CSVs); repo untouched, monkeypatch only.
|
| 7 |
+
Every arm below runs the LITERAL deployed class (mc.MODELS['@deployed'] =
|
| 8 |
+
submit.Ft2RUL, exactly cv.main()'s lazy registration), so the alpha arms
|
| 9 |
+
score what a public trigger would run at that alpha.
|
| 10 |
+
|
| 11 |
+
**ALL RESULTS REPORT-ONLY (count-coupled — public evidence 4x that no local
|
| 12 |
+
split prices the public tail; the user + a public trigger decide).**
|
| 13 |
+
|
| 14 |
+
Parity gate: a100 (alpha 1.0 rerun) reproduces the ref BIT-EXACTLY (max
|
| 15 |
+
per-origin |delta| = 0.0). Predictions are deterministic, so alpha arms share
|
| 16 |
+
identical predictions — every delta below is a pure count effect.
|
| 17 |
+
|
| 18 |
+
## (a) Alpha sweep — THE DECISION TABLE
|
| 19 |
+
|
| 20 |
+
48 paired all-building scenario totals vs champion; late/early in DAYS/scen
|
| 21 |
+
(cost/10 and cost/0.5). "pub est" = swaps ratio x champion's public
|
| 22 |
+
13.4/scen (podium sits at 15-17.6 with 60-70 late-days/scen).
|
| 23 |
+
|
| 24 |
+
| alpha | swaps/scen | pub est | SCORE | delta±SE | W/L | late-d/scen | early-d/scen | wilcoxon |
|
| 25 |
+
|------:|-----------:|--------:|-------:|:--------------|:--------|------------:|-------------:|---------:|
|
| 26 |
+
| 0.90 | 10.23 | 12.1 | 1613.1 | +67.6±27.7 (2.4sig) | 15W/14L | 105.4 | 637 | .075 |
|
| 27 |
+
| 1.00 | 11.33 | 13.4 | 1545.4 | champion | — | 94.9 | 728 | — |
|
| 28 |
+
| 1.10 | 12.15 | 14.4 | 1540.5 | -4.9±17.1 (0.3sig) | 8W/17L | 90.8 | 807 | .771 |
|
| 29 |
+
| 1.15 | 12.60 | 14.9 | 1563.7 | +18.2±22.8 (0.8sig) | 7W/27L | 89.9 | 857 | .121 |
|
| 30 |
+
| 1.20 | 12.98 | 15.4 | 1567.1 | +21.7±28.7 (0.8sig) | 10W/28L | 88.0 | 900 | .148 |
|
| 31 |
+
| 1.30 | 13.77 | 16.3 | 1542.7 | -2.7±33.7 (0.1sig) | 15W/27L | 82.3 | 968 | .748 |
|
| 32 |
+
| 1.40 | 14.85 | 17.6 | 1501.9 | -43.6±43.0 (1.0sig) | 18W/25L | 73.7 | 1060 | .530 |
|
| 33 |
+
| 1.50 | 15.75 | 18.6 | 1546.7 | +1.3±47.7 (0.0sig) | 18W/26L | 72.2 | 1172 | .995 |
|
| 34 |
+
|
| 35 |
+
Reading:
|
| 36 |
+
|
| 37 |
+
* The axis is ONE-SIDED. Down (0.9) is clearly bad: +67.6 (2.4sig), +10.5
|
| 38 |
+
late-days/scen — consistent with the public 0.8->1.0 conversion
|
| 39 |
+
(1661->1575). Up (1.1-1.5) is flat within noise: every mean is inside
|
| 40 |
+
~1sig, and W/L is NEGATIVE for every up-arm (the MEDIAN scenario worsens
|
| 41 |
+
~+17; a few tail scenarios win big). SE grows with alpha (17 -> 48).
|
| 42 |
+
* Mean minimum sits at 1.4 (-43.6) but bounces back at 1.5 (+1.3) — the
|
| 43 |
+
minimum is a tail artifact, not a stable optimum. Wilcoxon never comes
|
| 44 |
+
close for any up-arm.
|
| 45 |
+
* Marginal exchange rate along the grid (late-days saved / early-days bought
|
| 46 |
+
per added swap): 1.0->1.1: 5.1/97; 1.1->1.15: 1.9/108; 1.15->1.2: 5.1/116;
|
| 47 |
+
1.2->1.3: 7.3/85; 1.3->1.4: 7.9/86 (marginal cost -37.7/swap). Returns do
|
| 48 |
+
NOT diminish out to 1.4 — deep order positions still contain catchable
|
| 49 |
+
deaths. The ordering is good deeper than the count reaches; the count level
|
| 50 |
+
is the binding constraint (in one specific era — see (d)).
|
| 51 |
+
|
| 52 |
+
## (b) Calibrated counts (logcal values under the champion order) — REFUTED
|
| 53 |
+
|
| 54 |
+
LogcalFt2 = champion Ft2RUL order, values/counts = CalibratedClassifierCV
|
| 55 |
+
(sigmoid, cv=5) logistic on the same FEATURES+vmin7_rank. logcal's expected
|
| 56 |
+
count runs 1.135x logbag's (mean per-fleet sum(p42) 2.302 vs 2.028 — the
|
| 57 |
+
"miscalibrated" logbag UNDER-counts by its own lights, consistent with the
|
| 58 |
+
alpha-up flatness).
|
| 59 |
+
|
| 60 |
+
| arm | alpha | eff. appetite | swaps/scen | SCORE | delta±SE | W/L | wilcoxon |
|
| 61 |
+
|-----|------:|--------------:|-----------:|------:|:---------|:----|---------:|
|
| 62 |
+
| cal10 | 1.00 | ~1.14 | 12.94 | 1585.0 | +39.5±24.4 (1.6sig) | 10W/34L | .011 |
|
| 63 |
+
| cal110 | 1.10 | ~1.25 | 13.77 | 1611.5 | +66.0±24.0 (2.7sig) | 10W/38L | .002 |
|
| 64 |
+
| cal088 | 0.881 | ~1.00 (count-matched control) | 11.77 | 1612.9 | +67.5±20.0 (3.4sig) | 8W/35L | .000 |
|
| 65 |
+
|
| 66 |
+
cal088 is the decisive control: at CHAMPION-MATCHED total appetite
|
| 67 |
+
(alpha = 1/1.135), pure per-scenario reallocation by the calibrated count is
|
| 68 |
+
+67.5 (3.4sig worse, 8W/35L). Anatomy: only 43/240 cells change count
|
| 69 |
+
(+28/-15) and it hurts both ways — dropped swaps un-catch deaths (s28/f0:
|
| 70 |
+
-1 swap -> +430 late) and added swaps land in the nearend block (+2.3
|
| 71 |
+
swaps/scen there, already swap-rich) instead of warmup. Compare cal10
|
| 72 |
+
(+39.5 at 12.94 swaps) vs pure alpha at the same appetite (a115/a120 ~+20):
|
| 73 |
+
the calibrated count is worse than flat-scaling at every appetite level.
|
| 74 |
+
ANSWER: no — a calibrated expected count does NOT beat alpha-scaling the
|
| 75 |
+
miscalibrated one; logbag's per-scenario count profile is better-aligned
|
| 76 |
+
with catchability than the calibrated profile. Axis closed on local
|
| 77 |
+
evidence.
|
| 78 |
+
|
| 79 |
+
## (c) Risk-shaped N (N = sum(p42) + beta*sqrt(sum(p42(1-p42)))) — REFUTED
|
| 80 |
+
|
| 81 |
+
Buffer is large relative to the sum (mean 1.122 on mean sum 2.028), so beta
|
| 82 |
+
acts like a big, fleet-size-dependent alpha bump.
|
| 83 |
+
|
| 84 |
+
| arm | beta | swaps/scen | SCORE | delta±SE | W/L | wilcoxon |
|
| 85 |
+
|-----|-----:|-----------:|------:|:---------|:----|---------:|
|
| 86 |
+
| rb05 | 0.5 | 13.60 | 1585.0 | +39.6±31.1 (1.3sig) | 11W/31L | .043 |
|
| 87 |
+
| rb10 | 1.0 | 16.21 | 1554.8 | +9.3±51.1 (0.2sig) | 19W/28L | .741 |
|
| 88 |
+
|
| 89 |
+
rb05 is significantly worse than champion AND worse than plain a130 at the
|
| 90 |
+
same swap level (13.60 vs 13.77 swaps: +39.6 vs -2.7) — the sqrt buffer
|
| 91 |
+
allocates the extra appetite ANTI-proportionally to where it pays (small
|
| 92 |
+
fleets get the biggest relative bump; the warmup gains of (d) are not
|
| 93 |
+
fleet-size-shaped). Principled-looking, measurably worse than flat alpha.
|
| 94 |
+
Axis closed on local evidence.
|
| 95 |
+
|
| 96 |
+
## (d) Diagnostics — best arm a140 (best mean), plus the structure behind it
|
| 97 |
+
|
| 98 |
+
Per-cell (240 fold x origin) paired diagnostics, a140 vs champion:
|
| 99 |
+
|
| 100 |
+
* corr(count delta, cost delta) = +0.01 over all cells, +0.14 on the 151
|
| 101 |
+
changed cells (past reallocation-masquerade red flag: 0.76). Same for all
|
| 102 |
+
alpha arms (|corr| <= 0.13). No masquerade signature — these are real
|
| 103 |
+
count effects, cleanly separated by the value-preserving order.
|
| 104 |
+
* +169 swaps total -> 1018 late-days saved (6.0/swap = 60 cost) vs 15953
|
| 105 |
+
early-days bought (94.4/swap = 47 cost) + fees/travel. Conversion: 48/151
|
| 106 |
+
changed cells cut late cost (sum -10236); 103 were dead swaps (sum +8145).
|
| 107 |
+
At a110 the same picture: 12/39 convert, 5.1 late-days/swap, 97
|
| 108 |
+
early-days/swap — every alpha step trades at roughly cost-neutral, which
|
| 109 |
+
is WHY the surface is flat.
|
| 110 |
+
* Failure anatomy at high alpha: the marginal swap can cascade through
|
| 111 |
+
mobility constraints, not just early cost — s23/f3 at a130: one added swap
|
| 112 |
+
-> daily_limit +100, weekly_limit +100, overtime +49, travel +21 (cell
|
| 113 |
+
+369 with zero late change).
|
| 114 |
+
* THE STRUCTURE: the entire mean gain lives in the WARMUP block (s_0-7),
|
| 115 |
+
exactly where plan_tsroute's comment documents sum(p42) undercounting
|
| 116 |
+
(~4x) and where the champion holds 172 late-days/scen with only 9
|
| 117 |
+
swaps/scen (panel: 89 late-days at 11 swaps; nearend: 24 at 16.3).
|
| 118 |
+
|
| 119 |
+
| block (dcost/scen) | a110 | a130 | a140 |
|
| 120 |
+
|--------------------|-----:|-----:|-----:|
|
| 121 |
+
| warmup s_0-7 | -101.0 | -270.5 | -344.3 |
|
| 122 |
+
| panel s_8-41 | +16.7 | +58.0 | +17.8 |
|
| 123 |
+
| nearend s42-47 | +0.4 | +10.6 | +9.7 |
|
| 124 |
+
|
| 125 |
+
Warmup consistency at a130: 6/8 origins win, 4/5 folds negative; at a140
|
| 126 |
+
5/5 folds negative (fold1-heavy: -1852 of -2755). Panel harm equally
|
| 127 |
+
consistent (4/5 folds positive).
|
| 128 |
+
|
| 129 |
+
### Post-hoc synthesis: warmup-gated alpha (NOT a pre-registered arm)
|
| 130 |
+
|
| 131 |
+
Because predictions are deterministic, mixing per-origin rows is
|
| 132 |
+
measurement-EXACT (identical to running an origin-conditional alpha; the
|
| 133 |
+
scenario time is plan-time-known, so the rule is deployable, no forward
|
| 134 |
+
read). Gate = alpha_up on s_0-7 only, champion 1.0 elsewhere:
|
| 135 |
+
|
| 136 |
+
| warmup alpha | SCORE | delta±SE | W/L (48) | wilcoxon | swaps/scen |
|
| 137 |
+
|-------------:|------:|:---------|:---------|---------:|-----------:|
|
| 138 |
+
| 1.1 | 1528.6 | -16.8±11.1 (1.5sig) | 3W/1L | — | 11.50 |
|
| 139 |
+
| 1.2 | 1512.4 | -33.0±19.5 (1.7sig) | 5W/2L | .109 | 11.69 |
|
| 140 |
+
| 1.3 | 1500.3 | -45.1±21.7 (2.1sig) | 6W/1L | .047 | 11.85 |
|
| 141 |
+
| 1.4 | 1488.0 | -57.4±22.0 (2.6sig) | 7W/1L | .016 | 12.00 |
|
| 142 |
+
| 1.5 | 1493.8 | -51.6±23.3 (2.2sig) | 7W/1L | .039 | 12.15 |
|
| 143 |
+
|
| 144 |
+
Monotone dose-response to 1.4, then pullback. CAVEATS, all of them: (1) the
|
| 145 |
+
block was selected AFTER seeing where alpha paid — the sigmas are inflated
|
| 146 |
+
by selection (though the mechanism — warmup count undercoverage — was
|
| 147 |
+
documented in plan_tsroute's comments long before this run); (2) only 8
|
| 148 |
+
scenarios carry the whole effect, fold1-heavy; (3) count-coupled and a NEW
|
| 149 |
+
mechanism (origin-conditional appetite), so under the tiered bar it needs
|
| 150 |
+
2sig + controls AND stays report-only regardless. Controls it does pass:
|
| 151 |
+
fold-consistency (5/5 at 1.4), specificity (surgical — 40/48 scenarios are
|
| 152 |
+
bit-identical to champion, which also caps public downside to the warmup
|
| 153 |
+
scenarios' contribution), no-masquerade (cellcorr ~0).
|
| 154 |
+
|
| 155 |
+
## Recommendation (confidence in brackets)
|
| 156 |
+
|
| 157 |
+
1. DO NOT spend a public trigger on flat alpha 1.1-1.3: means are inside
|
| 158 |
+
1sig, medians worsen, wilcoxon never bites [high confidence the local
|
| 159 |
+
surface is flat there]. Same verdict, stronger, for calibrated counts and
|
| 160 |
+
risk-shaped N — both refuted with controls, close those axes [high].
|
| 161 |
+
2. Flat alpha 1.4 is the only whole-surface point with a notable mean
|
| 162 |
+
(-43.6) and it maps to exactly the podium's public swap posture (~17.6/
|
| 163 |
+
scen), but it is 1.0sig, 18W/25L, tail-driven, and 1.5 bounces back
|
| 164 |
+
[low confidence it transfers; a public trigger on it is a coin-flip with
|
| 165 |
+
bounded upside ~-40].
|
| 166 |
+
3. The one result worth the user's attention: WARMUP-GATED alpha 1.3-1.4
|
| 167 |
+
(s_0-7 only). Locally -45 to -57 (2.1-2.6sig even before discounting
|
| 168 |
+
selection), monotone dose-response, mechanism-backed (documented warmup
|
| 169 |
+
undercount), surgical (+0.5-0.7 swaps/scen, 40/48 scenarios untouched).
|
| 170 |
+
If the user wants to spend a public trigger on the count axis, this is
|
| 171 |
+
the highest-EV candidate — but it is post-hoc, 8-scenario-supported, and
|
| 172 |
+
count-coupled, so it is strictly the user's call [moderate confidence the
|
| 173 |
+
sign transfers publicly; low-moderate in the magnitude].
|
| 174 |
+
4. If any alpha change ships, the alpha-0.9 result (+67.6, 2.4sig) is the
|
| 175 |
+
guardrail: never below 1.0.
|
| 176 |
+
|
| 177 |
+
Artifacts: /tmp/c13/run.py (driver; arms run: a090-a150, cal10/cal088/
|
| 178 |
+
cal110, rb05/rb10), /tmp/c13/diag.py (per-cell diagnostics),
|
| 179 |
+
/tmp/c13/table.py (decision table), /tmp/c13/cv_bgkfcand_c13_*.csv (240-cell
|
| 180 |
+
outputs per arm), lane logs /tmp/c13/lane*.log.
|
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# T2-HAZARD: censored survival models as order sources (2026-08-23)
|
| 2 |
+
|
| 3 |
+
Mission: the one model family never measured — a PROPER censored survival
|
| 4 |
+
model in the champion's order blend. The previous attempt (dth3) crashed
|
| 5 |
+
(KeyError 'duration') before producing a number: it fed a hazard model the
|
| 6 |
+
plain closed-pair table, which has no duration/event columns. Fixed here by
|
| 7 |
+
rebuilding the censored pool inside fit exactly the way `run_bgkf._fit`
|
| 8 |
+
does for its own hazard kinds (`mc.censored_pairs(t, t.origin.max())`
|
| 9 |
+
filtered to the fold's train devices — deployment-legal: a foreign fleet's
|
| 10 |
+
labels were all known when the submission was built). Pool per fold ~57k
|
| 11 |
+
pairs, ~6.3k deaths.
|
| 12 |
+
|
| 13 |
+
Driver: /tmp/c14/run.py. Paired vs /tmp/cv_bgkfcand_ft2a10.csv
|
| 14 |
+
(champion 4c93883, SCORE 1545.4, swaps 2.27). Values are always
|
| 15 |
+
logbag(vm7)@alpha1.0; arms change ORDER only (value-preserving blend hook,
|
| 16 |
+
composite registered as blend partner at weight 1.0; weights round(x,12)).
|
| 17 |
+
Replication guard h_champ (= .50 lb + .30 wiener + .20 gapHGB rebuilt
|
| 18 |
+
inside the composite): SCORE 1545.4, -0.0 vs ref, swaps 2.27 — exact.
|
| 19 |
+
|
| 20 |
+
## Models built (sklearn only)
|
| 21 |
+
|
| 22 |
+
- **DiscHazHGB** (discrete-time hazard): person-period expansion of the
|
| 23 |
+
censored pool into (pair, bucket) rows, buckets
|
| 24 |
+
(0-7,7-14,14-21,21-28,28-42,42-63,63-84] days. Target = died in bucket
|
| 25 |
+
given alive at its start; censored pairs contribute only fully observed
|
| 26 |
+
buckets as negatives. ONE HistGB classifier (depth 3, lr .06, 250 iters,
|
| 27 |
+
l2 1.0, early_stopping off), bucket midpoint as an extra feature
|
| 28 |
+
(~350k person-period rows/fold). Order source:
|
| 29 |
+
P(die<=42d) = 1 - prod_{k<5}(1-h_k).
|
| 30 |
+
- **AFTLite** (GBM-AFT): HistGB regressor on log(days-to-death), observed
|
| 31 |
+
deaths only, IPCW sample weights 1/G(t-) from a Kaplan-Meier of the
|
| 32 |
+
censoring distribution (G clipped at 0.05). Order source: -pred log-days.
|
| 33 |
+
- **WienerHybrid**: confidence-gated mixture for the .30 slot — wiener rank
|
| 34 |
+
where wnr_n >= 3 (96.5% of rows), DiscHazHGB rank where wnr_n < 3 (3.5%).
|
| 35 |
+
|
| 36 |
+
## Results (48 paired all-building scenario totals vs 1545.4)
|
| 37 |
+
|
| 38 |
+
| arm | order | SCORE | delta±SE | sig | W/L | wilcoxon | swaps |
|
| 39 |
+
|---|---|---|---|---|---|---|---|
|
| 40 |
+
| h_champ | .50lb/.30wn/.20gap (guard) | 1545.4 | -0.0±0.0 | - | 1W/0L | - | 2.27 |
|
| 41 |
+
| h_dh450 | .25/.15/.10 + .50 dh | 1527.9 | -17.6±35.3 | 0.5 | 23W/21L | 0.408 | 2.26 |
|
| 42 |
+
| h_alone | 1.0 dh (diagnostic) | 1537.0 | -8.4±50.9 | 0.2 | 25W/22L | 0.749 | 2.26 |
|
| 43 |
+
| h_dh425 | .40/.24/.16 + .20 dh | 1537.5 | -7.9±16.8 | 0.5 | 18W/12L | 0.339 | 2.27 |
|
| 44 |
+
| h_hyb30 | hybrid in .30 slot | 1550.7 | +5.3±5.9 | 0.9 | 4W/1L | - | 2.27 |
|
| 45 |
+
| h_dh4 | .45/.27/.18 + .10 dh | 1553.3 | +7.9±15.8 | 0.5 | 12W/8L | 0.841 | 2.27 |
|
| 46 |
+
| h_aft4 | .45/.27/.18 + .10 aft | 1569.8 | +24.4±21.3 | 1.1 | 12W/15L | 0.239 | 2.28 |
|
| 47 |
+
| h_dh20 | dh replaces gapHGB @.20 | 1571.2 | +25.7±20.4 | 1.3 | 11W/16L | 0.413 | 2.28 |
|
| 48 |
+
| h_dhg20 | dh+GAP4 replaces gap @.20 | 1585.5 | +40.1±22.6 | 1.8 | 9W/15L | 0.079 | 2.29 |
|
| 49 |
+
| h_dh30 | dh replaces wiener @.30 (control) | 1610.9 | +65.5±30.2 | 2.2 | 21W/21L | 0.137 | 2.25 |
|
| 50 |
+
| h_aft20 | aft replaces gapHGB @.20 | 1614.3 | +68.9±34.5 | 2.0 | 9W/28L | 0.010 | 2.27 |
|
| 51 |
+
|
| 52 |
+
Block structure (delta per scenario): the hazard's entire nominal win
|
| 53 |
+
lives in the 8 WARMUP scenarios (s_0-7, cold-start origins) — h_alone
|
| 54 |
+
-178/cell, h_dh450 -82, h_dh425 -54 — while the 34-cell panel is flat to
|
| 55 |
+
slightly worse (h_alone +31, h_dh425 +0.5). Per-cell scatter is violent
|
| 56 |
+
(h_alone swings -879..+815; the one-rank-tie ~539 phenomenon), which is
|
| 57 |
+
why 48 cells cannot resolve a family that only separates on 8 of them.
|
| 58 |
+
|
| 59 |
+
## Findings
|
| 60 |
+
|
| 61 |
+
1. **The discrete-time hazard is a genuine standalone PEER of the tuned
|
| 62 |
+
3-way champion order** (h_alone 1537.0, -8.4±50.9, 25W/22L) — the first
|
| 63 |
+
single model to match the blend. Its edge is cold-start: the censored
|
| 64 |
+
pool trains on open-window pairs the closed-label models discard.
|
| 65 |
+
2. **But it does not convert into a blend win.** Hedge curve over hazard
|
| 66 |
+
weight: .10 -> +7.9, .20 -> -7.9, .50 -> -17.6, 1.0 -> -8.4; everything
|
| 67 |
+
0.2-0.5 sigma, wilcoxon never below 0.3. Its ranks overlap too much
|
| 68 |
+
with lb+wiener+gap on the panel, and its private information (warmup)
|
| 69 |
+
is only 8 of 48 cells.
|
| 70 |
+
3. Slot substitutions all fail: it cannot replace gapHGB (+25.7) and
|
| 71 |
+
certainly not wiener (+65.5, the expected control) — both incumbent
|
| 72 |
+
sources earn their slots.
|
| 73 |
+
4. AFT-lite (IPCW log-days regression) is strictly worse everywhere
|
| 74 |
+
(+24.4 as 4th, +68.9 in the .20 slot with wilcoxon p=0.010 AGAINST)
|
| 75 |
+
— dead on arrival.
|
| 76 |
+
5. WienerHybrid gate (wnr_n<3) touches 3.5% of rows -> a wash (+5.3±5.9).
|
| 77 |
+
6. All arms count-flat as designed (swaps 2.25-2.29 vs 2.27; count rule
|
| 78 |
+
untouched, residual variation is window-boundary scheduling).
|
| 79 |
+
|
| 80 |
+
## Verdict
|
| 81 |
+
|
| 82 |
+
Best candidate: **h_dh450** (order .25 lb / .15 wiener / .10 gap / .50
|
| 83 |
+
discrete-hazard), SCORE 1527.9, -17.6±35.3 (0.5 sigma), 23W/21L, wilcoxon
|
| 84 |
+
0.408, swaps 2.26. Tier: NEW mechanism -> needs >=2 sigma paired.
|
| 85 |
+
**FAILS the bar by a wide margin — do not ship.** No arm in the family
|
| 86 |
+
reaches even 1 sigma in the winning direction.
|
| 87 |
+
|
| 88 |
+
Depth assessment: the family is MEASURED now, not dead-by-crash — it is a
|
| 89 |
+
peer, not an improvement. The only residual thread with any evidence is
|
| 90 |
+
the warmup/cold-start block, where the hazard is consistently and
|
| 91 |
+
strongly better; but that is 8 cells, the public fleet's origin mix is
|
| 92 |
+
unknowable, and warmup-targeted mechanisms are exactly the count/era
|
| 93 |
+
territory the public board has burned us on. Recommend closing the
|
| 94 |
+
survival-model axis for this competition (deadline today); if the code
|
| 95 |
+
outlives the deadline, the one idea worth carrying forward is
|
| 96 |
+
censored-pool training as a COLD-START specialist gate, not as a blended
|
| 97 |
+
order source.
|
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# T2 ORDERING agent — radical ordering arms vs the 1545.4 champion (c12)
|
| 2 |
+
|
| 3 |
+
Campaign: 5-agent improvement wave, 2026-08-23 (deadline day).
|
| 4 |
+
Champion (head 4c93883, untouched): values/counts = logbag(vm7)@alpha1.0;
|
| 5 |
+
ORDER = .50 rank(logbag) + .30 rank(WienerFHT) + .20 rank(gapHGB d2 lr.06
|
| 6 |
+
it300 l2=1 s0 on FEATURES+vmin7_rank+GAP4). CV bgkf 1545.4.
|
| 7 |
+
|
| 8 |
+
Driver: `/tmp/c12/run.py` (exact copy of the /tmp/c9 pattern: load_table
|
| 9 |
+
monkeypatch for GAP4, mc.MODELS registration, blend=(name,1.0) with
|
| 10 |
+
p_star=1.0, paired vs `/tmp/cv_bgkfcand_ft2a10.csv`). No tracked file was
|
| 11 |
+
edited; nothing committed. Per-arm CSVs: `/tmp/cv_bgkfcand_c12_t_*.csv`.
|
| 12 |
+
|
| 13 |
+
**Driver validation**: `t_champ` (in-driver replica of the 3-way order)
|
| 14 |
+
reproduced the reference **bit-exactly** — all 48 scenario deltas < 0.01,
|
| 15 |
+
SCORE 1545.4, swaps 2.27. Paired deltas below are therefore pure mechanism
|
| 16 |
+
effects, not harness drift.
|
| 17 |
+
|
| 18 |
+
## Results (paired over 48 all-building scenario totals)
|
| 19 |
+
|
| 20 |
+
| arm | mechanism | SCORE | delta±SE | sig | W/L | wilcoxon | swaps |
|
| 21 |
+
|---|---|---|---|---|---|---|---|
|
| 22 |
+
| t_champ | replica (validation) | 1545.4 | +0.0±0.0 | - | 0W/0L | - | 2.27 |
|
| 23 |
+
| t_gbm4_10 | 4th source gbm @.10 (.45/.27/.18/.10) | 1547.9 | +2.5±15.3 | 0.2σ | 13W/9L | p0.824 | 2.27 |
|
| 24 |
+
| t_cs50 | imminence-weighted gapHGB, w=1+50/d | 1552.0 | +6.5±20.1 | 0.3σ | 11W/8L | p0.936 | 2.28 |
|
| 25 |
+
| t_log4_05 | 4th source logistic @.05 | 1559.0 | +13.6±9.6 | 1.4σ | 8W/3L | p0.831 | 2.27 |
|
| 26 |
+
| t_plat16 | plateau demotion beta=.16 (dwell>=40d specialist) | 1564.4 | +18.9±31.0 | 0.6σ | 12W/19L | p0.444 | 2.29 |
|
| 27 |
+
| t_gbm4_05 | 4th source gbm @.05 (.475/.285/.19/.05) | 1573.3 | +27.9±14.2 | 2.0σ loss | 6W/6L | p0.204 | 2.27 |
|
| 28 |
+
| t_cs20 | imminence-weighted gapHGB, w=1+20/d | 1578.1 | +32.7±22.3 | 1.5σ | 10W/11L | p0.211 | 2.27 |
|
| 29 |
+
| t_plat08 | plateau demotion beta=.08 | 1578.6 | +33.2±25.6 | 1.3σ | 11W/18L | p0.137 | 2.28 |
|
| 30 |
+
| t_iso | isotonic-calibrated probability blend .5/.3/.2 | 1621.1 | +75.6±37.4 | 2.0σ loss | 15W/27L | p0.037 | 2.28 |
|
| 31 |
+
| t_casc10 | boundary cascade k=10 (specialist re-rank of cutoff band) | 1692.9 | +147.4±56.5 | 2.6σ loss | 17W/31L | p0.015 | 2.29 |
|
| 32 |
+
| t_casc10p | cascade k=10, protect all but last 2 included | 1700.2 | +154.8±59.7 | 2.6σ loss | 16W/32L | p0.010 | 2.29 |
|
| 33 |
+
| t_casc20 | boundary cascade k=20 | 1701.5 | +156.0±61.5 | 2.5σ loss | 19W/28L | p0.050 | 2.28 |
|
| 34 |
+
| t_bldgpct | per-building pct-rank of each source | 2094.4 | +549.0±73.7 | 7.4σ loss | 5W/40L | p0.000 | 2.23 |
|
| 35 |
+
| t_bldgz | per-building z-score of each source | 2484.7 | +939.3±115.1 | 8.2σ loss | 8W/40L | p0.000 | 2.25 |
|
| 36 |
+
|
| 37 |
+
Swaps ~2.27 everywhere (order-only, count-flat by construction; the ±0.02
|
| 38 |
+
wiggle is ec-top-up interaction with which devices carry the top values).
|
| 39 |
+
|
| 40 |
+
## Autopsy
|
| 41 |
+
|
| 42 |
+
- **Boundary cascade (a) — the most promising idea on paper — fails hard,
|
| 43 |
+
and the failure is structural, not a tuning miss.** The loss is pure late
|
| 44 |
+
cost (+134/origin late, +9 early; worst cells s21 +1127, s8 +899, s33
|
| 45 |
+
+797). Test fleets in bgkf have cutoff n ≈ 2-3, so the band
|
| 46 |
+
[max(0,n-k), n+k) IS the whole confident top of the order: the specialist
|
| 47 |
+
gets authority over near-certain deaths, not just the ambiguous fringe,
|
| 48 |
+
and one demoted sure-death costs ~500+. Protecting all but the last 2
|
| 49 |
+
included (t_casc10p) did not help (+154.8) — the damage comes from the
|
| 50 |
+
below-cutoff side too: specialist promotions displace true deaths sitting
|
| 51 |
+
at positions n..n+2 that the champion had right. The train-side band
|
| 52 |
+
replica (per-origin, in-sample champion scores, cutoff ~8-15 on ~340-
|
| 53 |
+
device train fleets) evidently does not transfer to 90-device test fleets
|
| 54 |
+
with cutoff 2-3.
|
| 55 |
+
- **Per-building normalization (c) is catastrophic (+549/+939).** In bgkf
|
| 56 |
+
the test buildings are planned as one fleet, and cross-building rank
|
| 57 |
+
allocation is exactly what the global blend gets right: with ~18 devices
|
| 58 |
+
per building, forcing each building's top device to rank 1.0 hands
|
| 59 |
+
inclusion slots to healthy buildings' least-healthy devices. The global
|
| 60 |
+
pooled rank is load-bearing; do not revisit within-building rescaling of
|
| 61 |
+
order sources.
|
| 62 |
+
- **Probability-space blending (d) loses to rank-space (+75.6, 2.0σ, late-
|
| 63 |
+
driven).** Isotonic calibration on a ~25%-building holdout collapses the
|
| 64 |
+
order signal into a few steps (ties broken back toward champion order at
|
| 65 |
+
1e-9), and the .5/.3/.2 mix in probability units over-weights whichever
|
| 66 |
+
source is most confident rather than most discriminative. Rank blending
|
| 67 |
+
is the better aggregation for this planner; consistent with the earlier
|
| 68 |
+
death of rank transforms (pow2/sqrt/logit, c9).
|
| 69 |
+
- **Cost-sensitive gapHGB (b) is a wash at best** (c=50 +6.5±20.1; c=20
|
| 70 |
+
+32.7±22.3). Non-monotone in c and high per-scenario churn (s17 +545 /
|
| 71 |
+
s36 -512 at c=50): imminence weighting reshuffles the gap-HGB's ranking
|
| 72 |
+
noise without moving mean cost. No dial between 20 and 50 is worth the
|
| 73 |
+
cell.
|
| 74 |
+
- **4th sources (e): closest to zero but never negative.** gbm@.10 +2.5±15.3
|
| 75 |
+
(13W/9L, a pure wash), gbm@.05 +27.9��14.2 (a 2.0σ LOSS on only 12 changed
|
| 76 |
+
scenarios — small-weight rank flips are asymmetric-bad), logistic@.05
|
| 77 |
+
+13.6±9.6. The .50/.30/.20 3-way already spans the useful model diversity;
|
| 78 |
+
a 4th correlated source only adds rank jitter at the razor-thin cutoff.
|
| 79 |
+
- **Plateau demotion (f, own idea) doesn't pay** (+33.2 at beta=.08, +18.9
|
| 80 |
+
at beta=.16, both more L than W). Demoting low-specialist plateau
|
| 81 |
+
dwellers (days_below_245>=40, 11.75% in-window death rate) does swap some
|
| 82 |
+
false includes out, but the devices promoted in their place die no more
|
| 83 |
+
often — the champion's plateau false-includes are apparently already the
|
| 84 |
+
least-bad choices in those fleets. Interesting detail: bigger beta hurt
|
| 85 |
+
LESS (s16 -654, s17 -531 wins at beta=.16), but the sign never flips.
|
| 86 |
+
|
| 87 |
+
## Verdict
|
| 88 |
+
|
| 89 |
+
**No adoptable candidate.** Best arm t_gbm4_10 (+2.5±15.3, 0.2σ) is a wash,
|
| 90 |
+
not a win; every structurally-new mechanism (cascade, per-building
|
| 91 |
+
normalization, isotonic prob-blend, cost-sensitive specialist, plateau
|
| 92 |
+
specialist) is a measured LOSS, three of them at >=2σ in the wrong
|
| 93 |
+
direction. Nothing meets any tier (new mechanisms need >=2σ paired WINS;
|
| 94 |
+
count-flat tweaks need 1.5σ — none is even below zero on the mean).
|
| 95 |
+
|
| 96 |
+
Takeaway for the wall: the champion's .50/.30/.20 global-rank blend is a
|
| 97 |
+
genuine local optimum across six structurally different ordering axes, not
|
| 98 |
+
just the weight simplex. The missed-death frontier (rank gap 1-10 below a
|
| 99 |
+
cutoff of 2-3 per fold-fleet) is not recoverable by re-ranking machinery
|
| 100 |
+
trained on the same feature table — every attempt to move devices across
|
| 101 |
+
the cutoff moves at least as many true deaths out as in. If the frontier is
|
| 102 |
+
to move, it needs new information (features/labels), not new order
|
| 103 |
+
aggregation.
|
| 104 |
+
|
| 105 |
+
DEAD (add to the do-not-retest list): boundary-cascade specialists (any k,
|
| 106 |
+
any protection), within-building rank/z normalization of order sources,
|
| 107 |
+
isotonic/probability-space blending of the 3 sources, imminence-weighted
|
| 108 |
+
gapHGB (c 20-50), gbm/logistic 4th sources at .05-.10, plateau-specialist
|
| 109 |
+
demotion (beta .08-.16, dwell 40d).
|
|
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# T2 planner lane — schedule the SAME swap set better (2026-08-23)
|
| 2 |
+
|
| 3 |
+
Reference: champion head 4c93883 (`ft2a10` = submit.Ft2RUL, alpha 1.0),
|
| 4 |
+
SCORE 1545.4 on bgkf (/tmp/cv_bgkfcand_ft2a10.csv). Harness: /tmp/c11/
|
| 5 |
+
(cache.py captures the champion's per-cell predictions through a real
|
| 6 |
+
`cv.run_bgkf(kind='@deployed')` run — parity vs the reference CSV exact,
|
| 7 |
+
max per-cell diff 1.1e-13 — then every arm re-plans the IDENTICAL
|
| 8 |
+
prediction set, so deltas are pure scheduling). Count-flat is enforced by
|
| 9 |
+
construction AND asserted per cell: the in-window battery SET of every arm
|
| 10 |
+
equals the champion's in every one of the 240 cells (dswaps_max 0
|
| 11 |
+
everywhere). No forward reads: arms only see model curves + the mobility
|
| 12 |
+
simulator; true eol enters only through the evaluator.
|
| 13 |
+
|
| 14 |
+
## Ops-cost decomposition of the champion on bgkf (per scenario, 48 means)
|
| 15 |
+
|
| 16 |
+
| component | total | PLAN phase | EMERGENCY phase |
|
| 17 |
+
|---|---|---|---|
|
| 18 |
+
| late_swap | 949.4 | 26.7 | 922.7 |
|
| 19 |
+
| early_swap | 364.0 | 364.0 | 0.0 |
|
| 20 |
+
| overtime | 62.5 | 30.9 | 31.6 |
|
| 21 |
+
| daily_limit | 64.6 | 4.2 | 60.4 |
|
| 22 |
+
| weekly_limit | 35.4 | 0.0 | 35.4 |
|
| 23 |
+
| travel | 47.9 | 28.3 | 19.5 |
|
| 24 |
+
| building_change | 11.4 | 7.3 | 4.1 |
|
| 25 |
+
| room_change | 6.4 | 4.6 | 1.8 |
|
| 26 |
+
| battery_swap | 3.9 | 2.8 | 1.1 |
|
| 27 |
+
|
| 28 |
+
(Phase split measured by re-evaluating each champion plan with the missed
|
| 29 |
+
batteries' eol set to NaT, which deletes the evaluator's emergency loop;
|
| 30 |
+
diff = emergency cost. Scripts: /tmp/c11/diag.py, csvs in /tmp/c11/.)
|
| 31 |
+
|
| 32 |
+
**Headline structure: of the 232/scen ops cost, only 78.1/scen is
|
| 33 |
+
plan-phase (schedulable at fixed swap set); 153.9/scen rides on the ~4.3
|
| 34 |
+
missed swaps/scen (emergency queue: one forced base-round-trip per miss,
|
| 35 |
+
plus the daily/weekly-limit and overtime hits those trips trigger). The
|
| 36 |
+
"ops" target is two-thirds prediction cost in disguise.** The optimizer's
|
| 37 |
+
problem is also tiny: 2.27 chosen/cell, group count 0-6 (85 cells with 1
|
| 38 |
+
group, 81 with 2, 44 with 3).
|
| 39 |
+
|
| 40 |
+
## Arms (all paired on 48 origin-sums vs 1545.4; swaps 2.27 = count-flat everywhere)
|
| 41 |
+
|
| 42 |
+
| arm | SCORE | delta±SE | sig | W/L | wilcoxon | note |
|
| 43 |
+
|---|---|---|---|---|---|---|
|
| 44 |
+
| nn (NN day-route order) | 1545.4 | -0.03±0.15 | 0.2 | 5/5 | 1.000 | dial dead |
|
| 45 |
+
| cons (constructive start) | 1549.7 | +4.29±4.78 | 0.9 | 4/9 | .348 | worse |
|
| 46 |
+
| srch8 (restarts 8, iters 200) | 1549.7 | +4.22±4.52 | 0.9 | 8/8 | .876 | MORE search = worse |
|
| 47 |
+
| exh3 (exact enum ≤3 groups) | 1550.5 | +5.09±4.86 | 1.0 | 11/16 | .413 | EXACT optimum of own objective = worse |
|
| 48 |
+
| exh3nn | 1550.3 | +4.89±4.86 | 1.0 | 14/17 | .499 | " |
|
| 49 |
+
| split1/2/4/5/14 | 1544.0–1547.4 | -1.5..+1.9 | ≤1.2 | — | — | split3 -1.47 is a lone spike at λ=1 |
|
| 50 |
+
| lam05 / lam075 (timing×λ) | 1545.7/1545.4 | +0.25/-0.06 | ≤0.4 | — | — | λ<1 dead |
|
| 51 |
+
| lam15 / lam2 / lam25 / lam3 / lam4 | 1544.2/1542.7/1543.4/1543.5/1543.7 | -1.19/-2.71/-1.98/-1.95/-1.75 | 1.2/2.2/1.7/1.5/1.4 | —/14:3/—/—/— | .123/.006/—/—/— | clean U, min at λ=2 |
|
| 52 |
+
| lam6 / lam10 / lam100 | 1546.0/1549.3/1564.2 | +0.6/+3.9/+18.7 | — | — | — | over-weighting blows up |
|
| 53 |
+
| wkres20/wkres16/dayres16 (planner-side limit reserve) | 1545.1–1546.9 | -0.3..+1.5 | ≤1.1 | — | — | dead (plan-phase weekly is already 0) |
|
| 54 |
+
| shift+1/+2/+3 (global later) | 1551.8/1561.9/1574.5 | +6.4/+16.5/+29.0 | 3-4σ | — | — | control: placement already calibrated |
|
| 55 |
+
| shift-1 (global earlier) | 1542.9 | -2.55±1.20 | 2.1 | 27/21 | .090 | mean-carried, rank-test fails — report-only |
|
| 56 |
+
| **lam2sp3 (λ=2, split_days=3)** | **1541.3** | **-4.11±1.41** | **2.9** | **25/4** | **8.8e-6** | **BEST** |
|
| 57 |
+
| lam2sp2 / lam2sp4 / lam2sp5 | 1543.0/1541.8/1542.0 | -2.45/-3.63/-3.43 | 2.4/2.6/2.4 | 23:7/22:7/21:6 | .003/.0004/.001 | plateau, not a spike |
|
| 58 |
+
| lam25sp3 / lam15sp3 / lam3sp3 | 1542.4/1542.9/1542.3 | -2.98/-2.51/-3.09 | 2.2/2.1/2.1 | — | .025/.006/.070 | plateau |
|
| 59 |
+
|
| 60 |
+
## The two findings
|
| 61 |
+
|
| 62 |
+
**1. The plan-phase schedule is SATURATED — and past the optimum of its own
|
| 63 |
+
objective.** The champion's local search (restarts 2, iters 60) sits at or
|
| 64 |
+
near the exact optimum of its surrogate objective (model timing curves +
|
| 65 |
+
exact mobility sim): exhaustive enumeration for ≤3-group cells (94% of
|
| 66 |
+
non-empty cells) finds only surrogate slack whose conversion makes TRUE
|
| 67 |
+
cost +5.1/scen WORSE (srch8 +4.2, cons +4.3 the same — they pick up +2.1
|
| 68 |
+
daily_limit AND +2.1 weekly_limit of real penalties the surrogate can't
|
| 69 |
+
see, cross-phase stacking with the emergency queue). The shallow search is
|
| 70 |
+
an accidental regularizer against surrogate error. **This closes the
|
| 71 |
+
CP-SAT open question: a date-only repack at FIXED swap set can only
|
| 72 |
+
optimize the same surrogate (true eol is not plan-time information), and
|
| 73 |
+
exact search of that surrogate already loses. The prior CP-SAT hybrid's
|
| 74 |
+
-96 was count-carried, as recall said.** ortools 9.15 is importable but a
|
| 75 |
+
CP-SAT arm is pointless — exhaustive enum is a stronger solver than CP-SAT
|
| 76 |
+
on the identical objective and it is negative.
|
| 77 |
+
|
| 78 |
+
**2. The one real win is the opposite of the mission's intent: protect
|
| 79 |
+
TIMING from mobility-motivated compromises.** `lam2sp3` = weight the
|
| 80 |
+
timing curves ×2 inside optimize_days' objective (λ·timing + mobility) and
|
| 81 |
+
split building groups at 3-day instead of 7-day buckets. Delta -4.11±1.41
|
| 82 |
+
(2.9σ), 25W/4L, Wilcoxon 8.8e-6, sign-test p=1e-4 (survives ~35-arm
|
| 83 |
+
multiplicity). Component mechanism: late -3.54, early -1.21, bought with
|
| 84 |
+
+0.41 travel +0.35 building_change (it declines cheap trip-merges that
|
| 85 |
+
drag a swap off its timing-optimal day). Controls: 5%-trimmed mean still
|
| 86 |
+
-2.37, median nonzero -3.42; panel block alone -2.52 at 19W/3L (warmup
|
| 87 |
+
-6.0, nearend -10.7); negative in 4/5 folds (fold 3 ~0 with only 2 nonzero
|
| 88 |
+
cells); worst scenario +2.5; dose-response clean on both dials (λ row at
|
| 89 |
+
sp3: 1.5/-2.5, 2/-4.1, 2.5/-3.0, 3/-3.1; split row at λ2: 2/-2.45,
|
| 90 |
+
3/-4.11, 4/-3.63, 5/-3.43, 7/-2.71). Count-flat by construction and
|
| 91 |
+
asserted set-identical per cell; prediction-flat by construction (cached
|
| 92 |
+
champion predictions).
|
| 93 |
+
|
| 94 |
+
## Tier verdict
|
| 95 |
+
|
| 96 |
+
- **lam2sp3, -4.11±1.41 (2.9σ)**: λ is a NEW knob (the objective weighting
|
| 97 |
+
does not exist in shipped code) → new-mechanism bar, ≥2σ + controls.
|
| 98 |
+
It clears 2σ with strong rank support, additivity (lam2 -2.71 + sp3 ≈
|
| 99 |
+
combo), a plateau in both dials, and fold spread. Caveats for the main
|
| 100 |
+
session: (a) selected max of a plateau whose center is ≈ -3.5, so
|
| 101 |
+
expect that rather than -4.1; (b) effect size is ~0.3% of SCORE — small
|
| 102 |
+
against public noise; (c) shipping needs a submit.py plan-path edit:
|
| 103 |
+
SPLIT_DAYS 7→3 (existing knob) + scaling curves ×2 before the
|
| 104 |
+
optimize_days call (one line in plan_tsroute, e.g. a
|
| 105 |
+
plan_tsroute.timing_weight attr defaulting 1.0). Conservative
|
| 106 |
+
validated-dial-only alternative: none reaches 1.5σ (split3 alone is a
|
| 107 |
+
lone spike; all pure-search dials are flat-to-negative).
|
| 108 |
+
- **lam2 alone, -2.71±1.24 (2.2σ, 14W/3L, p .006)**: single new knob, no
|
| 109 |
+
split change; cleaner story, smaller win.
|
| 110 |
+
- **shift-1, -2.55 (2.1σ)**: rank-test fails (27W/21L, p .09) — report-only.
|
| 111 |
+
- Everything aimed at the literal ops components (search depth, NN
|
| 112 |
+
routing, constructive starts, limit reserves) is flat or negative:
|
| 113 |
+
plan-phase ops (78/scen) is already priced exactly by mobility_cost and
|
| 114 |
+
is mostly irreducible travel/overtime physics of visiting remote dying
|
| 115 |
+
batteries. The remaining 154/scen ops is emergency-driven — a RECALL
|
| 116 |
+
problem, not a scheduling one.
|
| 117 |
+
|
| 118 |
+
Artifacts: /tmp/c11/{cache,lib,diag,arms}.py, arm CSVs /tmp/c11/arm_*.csv,
|
| 119 |
+
stats /tmp/c11/arm_stats.csv, logs /tmp/c11/arms*.log. Repo untouched
|
| 120 |
+
(monkeypatch only; best.pickle untouched).
|
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# T2 TIMING — early-cost decomposition + swap-date arms (campaign 5-agent, 2026-08-23)
|
| 2 |
+
|
| 3 |
+
Champion (4c93883, untouched): values/counts logbag(vm7) @ alpha 1.0, ORDER
|
| 4 |
+
.50 lb + .30 wienerFHT + .20 gapHGB, value-preserving. Ref CSV
|
| 5 |
+
/tmp/cv_bgkfcand_ft2a10.csv, SCORE 1545.4. All work in /tmp/c10/ (decomp.py,
|
| 6 |
+
run.py); repo untouched, monkeypatch only.
|
| 7 |
+
|
| 8 |
+
## Step 1 — where the EARLY cost actually comes from
|
| 9 |
+
|
| 10 |
+
Instrumented champion rerun (/tmp/c10/decomp.py): bit-exact reproduction
|
| 11 |
+
(max per-scenario |delta| vs ref = 0.0; reconstructed early-days 728.0/scen
|
| 12 |
+
= recorded). Per-swap capture: planned day vs cost-curve argmin (the
|
| 13 |
+
planner's solo-optimal day) vs effective EOL (observed, or evaluator-imputed
|
| 14 |
+
end_time+unobserved_eol_days). Swap-level CSV: /tmp/c10/decomp_swaps.csv.
|
| 15 |
+
|
| 16 |
+
Mechanics first: plan_tsroute does NOT use a single day quantile. The
|
| 17 |
+
CHAMPION day_q=0.05 argument is ignored; placement = argmin of the
|
| 18 |
+
expected-cost curves built in mc.cost_curves from the FULL 4-quantile
|
| 19 |
+
DayQuantiles CDF (piecewise linear through day_q{.05,.20,.50,.80}) +
|
| 20 |
+
survivor branch priced against imputed EOL, then optimize_days perturbs for
|
| 21 |
+
mobility/limits.
|
| 22 |
+
|
| 23 |
+
CV early = 364.0/scen (728 early-days, 11.33 swaps/scen). Decomposition:
|
| 24 |
+
|
| 25 |
+
| bucket | swaps/plan | early cost/scen | share |
|
| 26 |
+
|------------------------------------------|-----------:|----------------:|------:|
|
| 27 |
+
| imputed-EOL false positives (no EOL on file; priced vs end+30d, ~123 early-days each) | 0.88 | 268.5 | 74% |
|
| 28 |
+
| real deaths beyond the window (mean EOL day ~89, zero in-window late risk) | 0.35 | 70.3 | 19% |
|
| 29 |
+
| in-window deaths swapped early (true timing error) | 1.04 | 25.2 | 7% |
|
| 30 |
+
|
| 31 |
+
**Timing model vs planner packing: packing is nil.** Of 34,944 total
|
| 32 |
+
early-days only 219 (0.6%, ~2.3/scen) come from optimize_days moving a swap
|
| 33 |
+
off its solo cost-curve argmin (median move 0 days, p5..p95 = -4..+2).
|
| 34 |
+
Everything else is placement-given-predictions.
|
| 35 |
+
|
| 36 |
+
**And the true-timing slice is not conservative — it is already
|
| 37 |
+
late-risky.** In-window deaths: planner places at mean day 6.7 vs true mean
|
| 38 |
+
EOL 15.7 (deliberate 20:1 hedging — cost_curves swaps at ~F(d)=0.048 of the
|
| 39 |
+
predicted CDF), but 15.3% of in-window deaths are swapped LATE vs the 4.8%
|
| 40 |
+
the hedge targets: the DayQuantiles left tail is too OPTIMISTIC, not too
|
| 41 |
+
early. Late side confirms: 949.4/scen late = 922.7 unswapped-death
|
| 42 |
+
emergencies (selection misses) + only 26.7 swapped-too-late.
|
| 43 |
+
|
| 44 |
+
Naive EV check (swap set + realized days held fixed, shift dates +k):
|
| 45 |
+
uniform +2/+5/+8 = net +16.5/+63.0/+130.4 per scen (late at 10/day
|
| 46 |
+
overwhelms early savings at 0.5/day); plateau-only (rel_close<=.10) +6/+10 =
|
| 47 |
+
+22.0/+56.5. The 20:1 asymmetry means one overtaken in-window death cancels
|
| 48 |
+
20 days of early savings, and 24% of early-swapped in-window deaths have a
|
| 49 |
+
margin of <= 5 days.
|
| 50 |
+
|
| 51 |
+
Oracle ceiling for pure-timing gains: ~147/scen (push every never-dying
|
| 52 |
+
swap to day 42 + swap every in-window death exactly on its EOL) — but that
|
| 53 |
+
requires an oracle for WHICH devices die in-window, i.e. it is a selection
|
| 54 |
+
problem, not a dates problem.
|
| 55 |
+
|
| 56 |
+
## Step 2 — arms (all value/order/count-preserving; only day_q columns or
|
| 57 |
+
## cost-curve pricing change; blend=('champ',1.0) is the champion order)
|
| 58 |
+
|
| 59 |
+
Driver /tmp/c10/run.py (c9 pattern: load_table gap-cols monkeypatch,
|
| 60 |
+
mc.MODELS registration, cv.run_bgkf(kind=<arm>, variant='vm7',
|
| 61 |
+
blend=('champ',1.0), p_star=1.0), paired stats vs ref, ref asserted 1545.4).
|
| 62 |
+
champ0 = plain-logbag primary + champion order (reproduction control).
|
| 63 |
+
|
| 64 |
+
Arms: shift(k) = +k days on all four day_q columns (global calibration
|
| 65 |
+
curve); qmap(s) = quantile-level remap, model level L read as truth level
|
| 66 |
+
L*s (CDF pushed right, multiplicative); wnrday = wiener first-passage day
|
| 67 |
+
quantiles replace DayQuantiles for wnr_n>=3 devices; gap(k) = +k days for
|
| 68 |
+
plateau devices only (rel_close<=0.15, 65% of swaps / 69% of early-days,
|
| 69 |
+
justified by: plateau in-window deaths die later, day 18.4 vs 10.2, and are
|
| 70 |
+
swapped more too-early, 10.2d vs 6.8d); lint(v) = internal LATE price v
|
| 71 |
+
instead of 10 in cost_curves (placement hedges less); cblend3 =
|
| 72 |
+
cost_curves blend=0.3 (low-p42 CDF pulled toward uniform — pre-existing
|
| 73 |
+
mechanism, default off). All paired vs ref over the 48 scenario totals.
|
| 74 |
+
|
| 75 |
+
| arm | SCORE | delta±SE | sig | W/L | wcx | swaps | dEarly | dLate |
|
| 76 |
+
|-----------|--------|--------------|-----|--------|-------|-------|--------|--------|
|
| 77 |
+
| champ0 | 1545.4 | -0.0± 0.0 | — | — | — | 2.27 | 0.0 | 0.0 |
|
| 78 |
+
| t_shift2 | 1563.3 | +17.9± 6.0 | 3.0 | 16/32 | .000 | 2.26 | -11.1 | +24.8 |
|
| 79 |
+
| t_shift5 | 1601.6 | +56.2±13.7 | 4.1 | 14/34 | .000 | 2.20 | -31.9 | +87.5 |
|
| 80 |
+
| t_shift8 | 1671.2 | +125.8±18.2 | 6.9 | 7/41 | .000 | 2.14 | -50.2 | +175.6 |
|
| 81 |
+
| t_qmap13 | 1545.0 | -0.4± 9.0 | 0.0 | 32/16 | .277 | 2.19 | -13.9 | +12.7 |
|
| 82 |
+
| t_qmap16 | 1538.8 | -6.6± 6.8 | 1.0 | 29/18 | .437 | 2.15 | -24.4 | +21.5 |
|
| 83 |
+
| t_qmap25 | 1575.8 | +30.4±10.7 | 2.8 | 18/30 | .012 | 2.08 | -46.4 | +80.6 |
|
| 84 |
+
| t_wnrday | 1659.5 | +114.0±20.4 | 5.6 | 10/38 | .000 | 2.35 | +19.4 | +89.2 |
|
| 85 |
+
| t_gap6 | 1565.0 | +19.6±10.9 | 1.8 | 23/25 | .218 | 2.20 | -26.8 | +49.6 |
|
| 86 |
+
| t_gap10 | 1618.8 | +73.4±18.3 | 4.0 | 16/32 | .000 | 2.14 | -42.5 | +118.8 |
|
| 87 |
+
| t_lint7 | 1539.0 | -6.5± 6.3 | 1.0 | 30/18 | .198 | 2.17 | -19.9 | +17.1 |
|
| 88 |
+
| t_lint8 | 1548.8 | +3.4± 8.4 | 0.4 | 31/15 | .516 | 2.21 | -11.5 | +14.0 |
|
| 89 |
+
| t_cblend3 | 1550.1 | +4.6± 4.7 | 1.0 | 13/34 | .181 | 2.27 | +4.4 | -3.8 |
|
| 90 |
+
|
| 91 |
+
(dEarly/dLate = mean per-scenario change in early_swap / late_swap cost.)
|
| 92 |
+
|
| 93 |
+
Pareto: every rightward move of the dates trades early for late at a slope
|
| 94 |
+
of 0.86–3.5 cost-units of late per unit of early saved; only qmap16 and
|
| 95 |
+
lint7 sit slightly below 1.0 and net ~-6.5, both 1.0sig only. The dose-
|
| 96 |
+
response is a shallow noise-level basin around the champion (qmap13 -0.4,
|
| 97 |
+
qmap16 -6.6, qmap25 +30; lint7 -6.5, lint8 +3.4): no dip to harvest.
|
| 98 |
+
Note the W/L shape of the near-zero arms (29-32W / 15-18L yet insignificant
|
| 99 |
+
Wilcoxon and ~0 mean): many small wins from FEWER swaps, occasional large
|
| 100 |
+
losses when a shifted date lets a death be overtaken — the classic
|
| 101 |
+
count-coupled signature (phase-56 lesson).
|
| 102 |
+
|
| 103 |
+
Count-coupling: all timing arms except cblend3 move the swaps column
|
| 104 |
+
(2.27 -> 2.08–2.35) because plan_tsroute's ec break-even top-up reads the
|
| 105 |
+
same cost curves the shift modifies (curves.min vs 0.8*park). The two
|
| 106 |
+
"winners" therefore fail count-flatness on top of failing the sigma bar.
|
| 107 |
+
|
| 108 |
+
## Verdict
|
| 109 |
+
|
| 110 |
+
- No adoptable candidate. Best arms t_qmap16 (-6.6±6.8, 1.0sig, swaps 2.15)
|
| 111 |
+
and t_lint7 (-6.5±6.3, 1.0sig, swaps 2.17): below the 1.5sigma tier bar
|
| 112 |
+
AND count-coupled (report-only per tier rules regardless of sigma).
|
| 113 |
+
- The EARLY cost is NOT a timing problem. 93% of it is selection (74%
|
| 114 |
+
imputed-EOL false positives at ~123 early-days each + 19% real deaths far
|
| 115 |
+
beyond the window); only 7% (25.2/scen) is dying devices swapped early,
|
| 116 |
+
and that slice is already late-risky (15.3% of in-window deaths swapped
|
| 117 |
+
late vs the 4.8% the 20:1 hedge targets). Planner packing contributes
|
| 118 |
+
0.6% of early-days — nothing to fix there.
|
| 119 |
+
- Recommendation for the campaign: EARLY reduction must come from the
|
| 120 |
+
ORDER/selection axis (fewer never-dying devices inside the top-N and the
|
| 121 |
+
ec top-up), not from swap dates. The timing axis is mapped and closed:
|
| 122 |
+
global shifts, quantile remaps, wiener dates, gap-conditioned shifts, and
|
| 123 |
+
internal price recalibration all lose or wash.
|
| 124 |
+
|
| 125 |
+
Artifacts: /tmp/c10/run.py (driver), /tmp/c10/decomp.py + decomp_swaps.csv
|
| 126 |
+
(per-swap decomposition), /tmp/cv_bgkfcand_c10_*.csv (per-cell arm CSVs).
|
|
@@ -176,7 +176,8 @@ VARIANTS = {'base': _base, 'ranks_add': _ranks_add, 'vrel': _vrel,
|
|
| 176 |
# --------------------------------------------------------------------------
|
| 177 |
|
| 178 |
def run_bgkf(dataset_path=Path('dataset'), kind=None, variant='base',
|
| 179 |
-
blend=None, n_folds=N_FOLDS, origins=range(48), p_star=None
|
|
|
|
| 180 |
"""THE SCORE. Per fold: one fit on the TRAIN buildings' full closed-pair
|
| 181 |
history (deployment-exact for a held-out fleet), then per scenario the
|
| 182 |
TEST buildings are planned as a standalone fleet under submit.py's
|
|
@@ -201,7 +202,8 @@ def run_bgkf(dataset_path=Path('dataset'), kind=None, variant='base',
|
|
| 201 |
p = mc.plan_tsroute
|
| 202 |
p.alpha = CHAMPION['p_star'] if p_star is None else p_star
|
| 203 |
p.ec_margin, p.ec_pmax = CHAMPION['ec_margin'], CHAMPION['ec_pmax']
|
| 204 |
-
p.split_days = CHAMPION['split_days']
|
|
|
|
| 205 |
p.floor_scale, p.recent_deaths = CHAMPION['floor_scale'], 0.0
|
| 206 |
|
| 207 |
def _fit(k_, train):
|
|
@@ -323,10 +325,14 @@ CANDIDATES = {
|
|
| 323 |
# ft2a10 / head = THE CURRENT MODEL: runs the literal deployed class
|
| 324 |
# (submit.Ft2RUL - lazily registered in main()), so these labels always
|
| 325 |
# score exactly what a public trigger would run. Older forms kept below.
|
| 326 |
-
'ft2a10': dict(kind='@deployed', variant='base', p_star=1.0
|
|
|
|
| 327 |
'ft2a10_w20': dict(variant='vm7', blend=('wiener', 0.20), p_star=1.0),
|
| 328 |
'ft2a10_w25': dict(variant='vm7', blend=('wiener', 0.25), p_star=1.0),
|
| 329 |
-
'head': dict(kind='@deployed', variant='base', p_star=1.0
|
|
|
|
|
|
|
|
|
|
| 330 |
}
|
| 331 |
|
| 332 |
|
|
|
|
| 176 |
# --------------------------------------------------------------------------
|
| 177 |
|
| 178 |
def run_bgkf(dataset_path=Path('dataset'), kind=None, variant='base',
|
| 179 |
+
blend=None, n_folds=N_FOLDS, origins=range(48), p_star=None,
|
| 180 |
+
split_days=None, timing_weight=None):
|
| 181 |
"""THE SCORE. Per fold: one fit on the TRAIN buildings' full closed-pair
|
| 182 |
history (deployment-exact for a held-out fleet), then per scenario the
|
| 183 |
TEST buildings are planned as a standalone fleet under submit.py's
|
|
|
|
| 202 |
p = mc.plan_tsroute
|
| 203 |
p.alpha = CHAMPION['p_star'] if p_star is None else p_star
|
| 204 |
p.ec_margin, p.ec_pmax = CHAMPION['ec_margin'], CHAMPION['ec_pmax']
|
| 205 |
+
p.split_days = CHAMPION['split_days'] if split_days is None else split_days
|
| 206 |
+
p.timing_weight = 1.0 if timing_weight is None else timing_weight
|
| 207 |
p.floor_scale, p.recent_deaths = CHAMPION['floor_scale'], 0.0
|
| 208 |
|
| 209 |
def _fit(k_, train):
|
|
|
|
| 325 |
# ft2a10 / head = THE CURRENT MODEL: runs the literal deployed class
|
| 326 |
# (submit.Ft2RUL - lazily registered in main()), so these labels always
|
| 327 |
# score exactly what a public trigger would run. Older forms kept below.
|
| 328 |
+
'ft2a10': dict(kind='@deployed', variant='base', p_star=1.0,
|
| 329 |
+
split_days=3, timing_weight=2.0),
|
| 330 |
'ft2a10_w20': dict(variant='vm7', blend=('wiener', 0.20), p_star=1.0),
|
| 331 |
'ft2a10_w25': dict(variant='vm7', blend=('wiener', 0.25), p_star=1.0),
|
| 332 |
+
'head': dict(kind='@deployed', variant='base', p_star=1.0,
|
| 333 |
+
split_days=3, timing_weight=2.0),
|
| 334 |
+
# pre-T2 plan path (split 7, weight 1) kept for paired A/B:
|
| 335 |
+
'ft2a10_sp7': dict(kind='@deployed', variant='base', p_star=1.0),
|
| 336 |
}
|
| 337 |
|
| 338 |
|
|
@@ -1508,8 +1508,8 @@ def plan_tsroute(pred, included, locations, start_time, day_q,
|
|
| 1508 |
for g, m in curves.groupby(key)}
|
| 1509 |
travel_hours = travel_costs.set_index(['from', 'to'])['hours'].unstack()
|
| 1510 |
|
| 1511 |
-
day_of = optimize_days(groups, curves
|
| 1512 |
-
settings, start_time)
|
| 1513 |
|
| 1514 |
offs = key.map(day_of).astype(float)
|
| 1515 |
days = start_time + pd.to_timedelta(offs.values, unit='D')
|
|
@@ -1530,6 +1530,7 @@ def plan_tsroute(pred, included, locations, start_time, day_q,
|
|
| 1530 |
|
| 1531 |
plan_tsroute.alpha = 0.8
|
| 1532 |
plan_tsroute.split_days = 0
|
|
|
|
| 1533 |
plan_tsroute.p_be = 0.0
|
| 1534 |
plan_tsroute.floor_day = 0
|
| 1535 |
plan_tsroute.p_conf = 0.5
|
|
|
|
| 1508 |
for g, m in curves.groupby(key)}
|
| 1509 |
travel_hours = travel_costs.set_index(['from', 'to'])['hours'].unstack()
|
| 1510 |
|
| 1511 |
+
day_of = optimize_days(groups, curves * plan_tsroute.timing_weight,
|
| 1512 |
+
locations, travel_hours, settings, start_time)
|
| 1513 |
|
| 1514 |
offs = key.map(day_of).astype(float)
|
| 1515 |
days = start_time + pd.to_timedelta(offs.values, unit='D')
|
|
|
|
| 1530 |
|
| 1531 |
plan_tsroute.alpha = 0.8
|
| 1532 |
plan_tsroute.split_days = 0
|
| 1533 |
+
plan_tsroute.timing_weight = 1.0 # scales timing curves in optimize_days' objective
|
| 1534 |
plan_tsroute.p_be = 0.0
|
| 1535 |
plan_tsroute.floor_day = 0
|
| 1536 |
plan_tsroute.p_conf = 0.5
|
|
@@ -371,7 +371,15 @@ EC_PMAX = float(os.environ.get('BATTERYSWAP_EC_PMAX', '25'))
|
|
| 371 |
# Phase 14: let the day search split a building across days by best-day
|
| 372 |
# bucket (7d) instead of forcing one visit day per building. Panel 1679.2 vs
|
| 373 |
# 1702.0, selected in 100% of random AND blocked half-splits.
|
| 374 |
-
SPLIT_DAYS = int(os.environ.get('BATTERYSWAP_SPLIT_DAYS', '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
# Phase 17: cold-start inclusion floor. While the training set has seen fewer
|
| 376 |
# than FLOOR_GATE unique deaths, sum(p42) undercounts prevalence ~4x and the
|
| 377 |
# count rule parks visibly-dying batteries (warm-up block s_0-s_7: 46% of the
|
|
@@ -723,6 +731,7 @@ def adaptive_split_plans(split, split_path, log=print, deadline=None):
|
|
| 723 |
plan_tsroute.ec_margin = EC_MARGIN
|
| 724 |
plan_tsroute.ec_pmax = EC_PMAX
|
| 725 |
plan_tsroute.split_days = SPLIT_DAYS
|
|
|
|
| 726 |
plan_tsroute.floor_scale = FLOOR_SCALE
|
| 727 |
plan_tsroute.recent_deaths = 0.0
|
| 728 |
if FLOOR_SCALE > 0 and train_uniq < FLOOR_GATE:
|
|
|
|
| 371 |
# Phase 14: let the day search split a building across days by best-day
|
| 372 |
# bucket (7d) instead of forcing one visit day per building. Panel 1679.2 vs
|
| 373 |
# 1702.0, selected in 100% of random AND blocked half-splits.
|
| 374 |
+
SPLIT_DAYS = int(os.environ.get('BATTERYSWAP_SPLIT_DAYS', '3'))
|
| 375 |
+
# T2 planner lane (2026-08-23): weight the timing curves x2 inside
|
| 376 |
+
# optimize_days' objective and split buildings at 3d (not 7d) buckets -
|
| 377 |
+
# together they refuse cheap trip-merges that drag a swap off its
|
| 378 |
+
# timing-optimal day (late -3.5, early -1.2, bought with +0.8 mobility).
|
| 379 |
+
# bgkf -4.11 +/- 1.41 (2.9sigma, 25W/4L, Wilcoxon 8.8e-6), count-flat with
|
| 380 |
+
# battery sets cell-identical; dose-response plateau on both dials.
|
| 381 |
+
# TIMING_WEIGHT=1 + SPLIT_DAYS=7 restores the old plan path exactly.
|
| 382 |
+
TIMING_WEIGHT = float(os.environ.get('BATTERYSWAP_TIMING_WEIGHT', '2.0'))
|
| 383 |
# Phase 17: cold-start inclusion floor. While the training set has seen fewer
|
| 384 |
# than FLOOR_GATE unique deaths, sum(p42) undercounts prevalence ~4x and the
|
| 385 |
# count rule parks visibly-dying batteries (warm-up block s_0-s_7: 46% of the
|
|
|
|
| 731 |
plan_tsroute.ec_margin = EC_MARGIN
|
| 732 |
plan_tsroute.ec_pmax = EC_PMAX
|
| 733 |
plan_tsroute.split_days = SPLIT_DAYS
|
| 734 |
+
plan_tsroute.timing_weight = TIMING_WEIGHT
|
| 735 |
plan_tsroute.floor_scale = FLOOR_SCALE
|
| 736 |
plan_tsroute.recent_deaths = 0.0
|
| 737 |
if FLOOR_SCALE > 0 and train_uniq < FLOOR_GATE:
|