5-body synthetic observations for Jupiter, Saturn, Uranus, and a known Neptune, spanning 1781-1846 (66 annual observations). These serve as the ground truth against which all experiments are evaluated.
A full-budget solve establishes the reference point: how well does the optimizer recover Neptune with clean synthetic data and the full 66-year baseline?
Baseline: a = 30.070 AU (true: 30.07 AU)
l = 132.00 deg
RMS = 0.00 arcsec
converged = True
Observation noise tolerance
19th-century transit instruments achieved ~1 arcsec precision on a good night. How much noise can the solver tolerate before the prediction degrades? We inject Gaussian noise at σ = 0, 1, 2, and 5 arcsec and run 10 independent trials at each level.
On this exact synthetic benchmark, RMS is not the informative quantity: once the solver has enough baseline to identify Neptune, several truncation windows drive the fit essentially to zero. The more interesting question is the 1846 localization problem: whether each truncated fit still localizes Neptune’s sky longitude well enough to point a telescope in the right part of the sky.
By 1800, the synthetic benchmark already contains enough information to localize Neptune. The small 1810 deviation is a negligible optimizer-level wobble, not evidence that additional observations are harmful.
cutoff=1800 n= 19 a=30.07 AU lambda_1846=273.01 deg error_1846= 0.00 deg
cutoff=1810 n= 29 a=30.01 AU lambda_1846=273.17 deg error_1846= 0.16 deg
cutoff=1820 n= 39 a=30.07 AU lambda_1846=273.01 deg error_1846= 0.00 deg
cutoff=1830 n= 49 a=30.07 AU lambda_1846=273.01 deg error_1846= 0.00 deg
cutoff=1840 n= 59 a=30.07 AU lambda_1846=273.01 deg error_1846= 0.00 deg
Bode’s Law prior bias
Bode’s Law predicted Neptune at ~38.8 AU (actual: 30.07 AU). If Le Verrier had restricted his search to a Bode-consistent range, would the solver still converge? We compare three bound choices: modern (25–35 AU), Bode (35–45 AU), and agnostic (20–50 AU).
Code
logger.info("Running Bode's Law prior experiment ...")bode_trials = run_bode_experiment( jd_times, truth_longs, start_jd, jupiter_sv, saturn_sv, uranus_sv, priors=('modern', 'bode', 'agnostic'),)for t in bode_trials:print(f' prior={t.prior_name:8s} a in {t.a_bounds} 'f'found a={t.result.neptune.a:.2f} AU 'f'l={np.degrees(t.result.neptune.l_rad):.1f} deg')def _build_bode(bode_trials, *, theme="light"):return plot_bode_comparison(bode_trials, theme=theme)display(dual_render(_build_bode, bode_trials, alt="Effect of Bode's Law prior on Neptune recovery"))
prior=modern a in (25.0, 35.0) found a=30.07 AU l=132.0 deg
prior=bode a in (35.0, 45.0) found a=35.00 AU l=141.0 deg
prior=agnostic a in (20.0, 50.0) found a=30.07 AU l=132.0 deg
Residuals: before and after Neptune
A direct visualization of the problem Neptune solves. The main panel uses a shared y-axis so the scale contrast is visible at a glance; the zoomed inset shows the post-fit residual structure after the best-fit Neptune is added.