SSM-Clock—Sensitivity & Error Distributions (3.3–3.4)

3.3 Sensitivity (small, practical sweeps)

What to expect (qualitative)

  • Raise K (multistart): PASS-rate non-decreasing; runtime + small.
  • Raise S (stack count): stronger alias suppression; runtime x S.
  • Shrink grid (2 -> 1 min): slightly tighter means; runtime ~2x coarse.
  • Increase coarse_stride (1 -> 4): much faster coarse scan; tiny risk unless noise very high.
  • Wider refine bracket: marginal benefit; try only after K and S.

Repro mini-sweeps (each is safe and targeted)

More multistart (robustness up; small cost)

python ssm_clock_longbench_v2.py --period_sets "1,7,29.5306,365.2422" --seeds 200 --noise_list "6" ^
  --grid_step_min 2.0 --stack 5 --stack_dt_days 0.5 --multistart_k 9 --refine brent --refine_steps 80 --bracket_mult 2

More stacking (alias suppression up; cost x S)

python ssm_clock_longbench_v2.py --period_sets "1,7,29.5306,365.2422" --seeds 200 --noise_list "6" ^
  --grid_step_min 2.0 --stack 7 --stack_dt_days 0.5 --multistart_k 7 --refine brent --refine_steps 80 --bracket_mult 2

Faster coarse (stride) with same accuracy in practice

python ssm_clock_longbench_v2.py --period_sets "1,7,29.5306,365.2422" --seeds 200 --noise_list "6" ^
  --grid_step_min 2.0 --stack 5 --stack_dt_days 0.5 --multistart_k 7 --refine brent --refine_steps 80 --bracket_mult 2 --coarse_stride 4

Rule of thumb (v1.1)
If a tough scenario under-shoots 95%, go in this order:

K up  ->  S up  ->  grid down  ->  coarse_stride down  ->  refine bracket/steps up


3.4 Error distributions (ASCII mini-gallery, optional)

Purpose. Show shape (tight near zero; modest tail at 6 deg).

Tiny helper to print an ASCII histogram from per-seed errors

# Save as: notes/acceptance_err_hist.py
import csv, math, sys
IN = r"notes\longbench_detail.csv"   # per-seed dump; see note below
NB = 24                              # number of bins
B  = [0]*(NB+1)

with open(IN, "r", encoding="utf-8-sig") as f:
    rd = csv.DictReader(f)
    xs = [float(r["err_min"]) for r in rd]  # minutes
mx = max(xs) if xs else 1.0
for x in xs:
    k = min(NB, int(NB * x / mx))
    B[k]+=1

m = max(B) if B else 1
for i,b in enumerate(B):
    edge = i*mx/NB
    bar  = "#"*max(1, int(40*b/m))
    print(f"{edge:6.1f} min | {bar}")

Run the bench with per-seed dump, then plot

python ssm_clock_longbench_v2.py --period_sets "1,7,29.5306,365.2422" --seeds 200 --noise_list "6" ^
  --grid_step_min 2.0 --stack 5 --stack_dt_days 0.5 --multistart_k 7 --refine brent --refine_steps 80 --bracket_mult 2 ^
  --emit_detail "notes\\longbench_detail.csv"

python notes\acceptance_err_hist.py

Notes

  • The --emit_detail flag/function should write per-seed errors as CSV with a column err_min in minutes (if your script uses a different flag or column name, adapt accordingly).
  • For 2 deg noise, expect a very sharp pile-up near 0–6 min.
  • For 6 deg noise, expect a wider but compact spread with most mass under ~20 min.

Navigation

Back: SSM-Clock—Acceptance Dataset & Core Results (3.1–3.2)
Next: SSM-Clock—PASS Policy (3.5)