Thibaut Forest Claude Opus 5 (1M context) commited on
Commit
3d2958f
·
1 Parent(s): a354f2b

Phase 18: limit-aware constructive initializer rejected; limit tail is a correct trade

Browse files
Files changed (2) hide show
  1. EXPERIMENTS.md +21 -0
  2. batteryswap_example/models_cv.py +22 -0
EXPERIMENTS.md CHANGED
@@ -565,6 +565,27 @@ break-even top-up, censoring-aware pricing, building day-splitting - already
565
  serve, and whose panel deltas systematically understate their deployment
566
  value. Champion unchanged: panel 1679.2, all-48 Docker 2146.9.
567
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  ## Test-look ledger
569
 
570
  8 looks total (now historical - see protocol change above); look 9 = the
 
565
  serve, and whose panel deltas systematically understate their deployment
566
  value. Champion unchanged: panel 1679.2, all-48 Docker 2146.9.
567
 
568
+ ## Phase 18 - limit-aware constructive initializer (rejected; the limit tail is a correct trade)
569
+
570
+ Last item of the phase-17 plan: greedy urgency-ordered construction (each
571
+ group placed on the day minimizing exact partial timing+mobility cost) as an
572
+ additional best-of-starts candidate in optimize_days, targeting the
573
+ overtime/limit bucket (~172/origin, spikes 500-850 at s_21/23/33-38).
574
+
575
+ Panel: **1692.3 vs 1679.2** (+13.1), champion selected 88.5% random / 75%
576
+ blocked. Three findings close the direction: (1) 28/34 byte-ties - the
577
+ argmin-start climb already finds these optima; (2) the limit spikes are
578
+ UNTOUCHED (s_21 781, s_23 832 identical) - with exact limit pricing in the
579
+ objective, the optimizer genuinely prefers paying penalties because deaths
580
+ cluster in time and spreading costs more in timing than it saves in limits;
581
+ (3) where the constructive start did win the search objective (s_34/s_35),
582
+ realized cost got WORSE (+215/+226) - at the margin, deeper search harvests
583
+ model-curve error rather than real savings. The knob
584
+ (optimize_days.constructive) stays available, default off.
585
+
586
+ This completes the phase-17 plan: all five directions adjudicated and
587
+ rejected. Champion unchanged: panel 1679.2, all-48 Docker 2146.9.
588
+
589
  ## Test-look ledger
590
 
591
  8 looks total (now historical - see protocol change above); look 9 = the
batteryswap_example/models_cv.py CHANGED
@@ -1306,11 +1306,32 @@ def optimize_days(groups, curves, locations, travel_hours, settings, start_time,
1306
  cand, s = climb(start)
1307
  if s < best_score:
1308
  best, best_score = cand, s
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1309
  return best
1310
 
1311
 
1312
  optimize_days.restarts = 2
1313
  optimize_days.iters = 60
 
1314
 
1315
 
1316
  def plan_ecroute(pred, included, locations, start_time, day_q,
@@ -1680,6 +1701,7 @@ def walk_forward(table, scenario_ctx, origins, configs):
1680
  EMERGENCY_DAY = cfg.get('emergency_day', WINDOW_DAYS + 3)
1681
  optimize_days.restarts = int(cfg.get('restarts', 2))
1682
  optimize_days.iters = int(cfg.get('iters', 60))
 
1683
  included = pred.index[pred['p42'] >= cfg['p_star']]
1684
  kwargs = {}
1685
  if cfg['planner'] in ('ecroute', 'tsroute', 'tspig', 'tspig2', 'tscut'):
 
1306
  cand, s = climb(start)
1307
  if s < best_score:
1308
  best, best_score = cand, s
1309
+
1310
+ if optimize_days.constructive:
1311
+ # limit-aware constructive start (phase 18): the argmin start piles
1312
+ # urgent groups into the same days/weeks and the +-10d shift moves may
1313
+ # not escape the resulting overtime/limit basin. Greedily place groups
1314
+ # in urgency order, each on the day minimizing the EXACT partial cost
1315
+ # (timing + real mobility incl. limit penalties), then climb from it.
1316
+ cons = {}
1317
+ for g in sorted(groups, key=base.get):
1318
+ best_d, best_s = None, np.inf
1319
+ for dcand in range(0, WINDOW_DAYS + 1):
1320
+ trial = dict(cons, **{g: dcand})
1321
+ s = (sum(curves.at[b, trial[gg]] for gg in trial for b in groups[gg])
1322
+ + mobility({gg: trial[gg] for gg in trial}))
1323
+ if s < best_s:
1324
+ best_d, best_s = dcand, s
1325
+ cons[g] = best_d
1326
+ cand, s = climb(cons)
1327
+ if s < best_score:
1328
+ best, best_score = cand, s
1329
  return best
1330
 
1331
 
1332
  optimize_days.restarts = 2
1333
  optimize_days.iters = 60
1334
+ optimize_days.constructive = False
1335
 
1336
 
1337
  def plan_ecroute(pred, included, locations, start_time, day_q,
 
1701
  EMERGENCY_DAY = cfg.get('emergency_day', WINDOW_DAYS + 3)
1702
  optimize_days.restarts = int(cfg.get('restarts', 2))
1703
  optimize_days.iters = int(cfg.get('iters', 60))
1704
+ optimize_days.constructive = bool(cfg.get('constructive', False))
1705
  included = pred.index[pred['p42'] >= cfg['p_star']]
1706
  kwargs = {}
1707
  if cfg['planner'] in ('ecroute', 'tsroute', 'tspig', 'tspig2', 'tscut'):