CLRI-2D horizon h=10
PARITYS1 · dim 12No clear winner. The survival gap is under 10 percentage points and the balanced-score gap is under 0.05, so neither SolvSRK nor the best baseline clears the win threshold. Either works - choose on cost, licensing, or integration effort. All verdicts →
2D closed-loop EKF+PN interceptor engagement (dim=12) with extended integration horizon h=10. Tests solver survival as dynamics evolve further.
Problem definition
Zarchan (2012) Tactical and Strategic Missile Guidance; Bar-Shalom et al. (2001) Estimation with Applications
Canonical RHS excerpt from the registered callable used for this benchmark cell. Expand it to verify the state equations; it is not a standalone runnable fixture.
Show canonical RHS excerpt
def _clamp(x: float, lo: float, hi: float) -> float:
if x < lo:
return lo
if x > hi:
return hi
return x
def _los_rate_2d(rx, ry, vrx, vry):
"""LOS rate in 2-D (lambda_dot = (R x V_rel) / R^2)."""
R2 = rx * rx + ry * ry + 0.01
return (rx * vry - ry * vrx) / R2
def _sigmoid_window(t: float, t_center: float, tau: float) -> float:
"""Unit pulse centred at *t_center*, width ~4*tau, Lipschitz-continuous."""
arg = (t - t_center) / max(tau, 1e-12)
s = 1.0 / (1.0 + np.exp(-arg))
return 4.0 * s * (1.0 - s)
def rhs(t, y):
xt, yt = y[0], y[1]
vxt, vyt = y[2], y[3]
xi, yi = y[4], y[5]
vxi, vyi = y[6], y[7]
xh, yh = y[8], y[9]
vxh, vyh = y[10], y[11]
d = np.empty(dim)
# --- target kinematics (sinusoidal weave) ---
d[0] = vxt
d[1] = vyt
d[2] = a_t * np.sin(omega_t * t)
d[3] = a_t * np.cos(omega_t * t)
# --- PN guidance from EKF estimates ---
rx = xh - xi
ry = yh - yi
R = np.sqrt(rx * rx + ry * ry + 0.01)
vrx = vxh - vxi
vry = vyh - vyi
V_c = -(rx * vrx + ry * vry) / R # closing velocity
lam_dot = _los_rate_2d(rx, ry, vrx, vry)
lam_dot = _clamp(lam_dot, -0.5, 0.5)
a_n = N_pn * max(V_c, 10.0) * lam_dot
# LOS angle for decomposition
lam = np.arctan2(ry, rx)
ax_i = -a_n * np.sin(lam)
ay_i = a_n * np.cos(lam)
if R < 0.1:
ax_i = 0.0
ay_i = 0.0
d[4] = vxi
d[5] = vyi
d[6] = ax_i
d[7] = ay_i
# --- EKF propagation (constant-velocity prediction) ---
d[8] = vxh
d[9] = vyh
d[10] = 0.0
d[11] = 0.0
# --- smoothed measurement updates ---
# Find the nearest update epoch
k = int(t / T_update + 0.5)
k = min(k, n_updates - 1)
t_k = update_times[k]
w = _sigmoid_window(t, t_k, tau_update)
if w > 1e-6:
# True range & bearing
drx_true = xt - xi
dry_true = yt - yi
R_true = np.sqrt(drx_true**2 + dry_true**2 + 0.01)
theta_true = np.arctan2(dry_true, drx_true)
# Noisy measurement
R_meas = R_true + noise_r[k]
theta_meas = theta_true + noise_th[k]
# Measurement in Cartesian
x_meas = xi + R_meas * np.cos(theta_meas)
y_meas = yi + R_meas * np.sin(theta_meas)
# Innovation
innov_x = x_meas - xh
innov_y = y_meas - yh
# Correction impulse (scaled by window)
rate = w / max(tau_update, 1e-6)
d[8] += K_pos * innov_x * rate
d[9] += K_pos * innov_y * rate
d[10] += K_vel * innov_x * rate
d[11] += K_vel * innov_y * rate
return d- Parameters
- K_pos = 0.4
- K_vel = 0.2
- N_pn = 3
- T_update = 0.02
- a_t = 20
- dim = 12
- n_updates = 1502
- noise_r = [1.25730221093, -1.32104863291, 6.40422650443, 1.04900117153, -5.35669373161, 3.61595054909, …] [shape=(1502,), min=-38.9942173005, max=30.6603673905]
- noise_th = [-0.0105644988785, -0.00252017064968, -0.00713905077733, -0.0109135436315, 0.00381823718907, 0.00696536738291, …] [shape=(1502,), min=-0.0271792200841, max=0.0259406043333]
- omega_t = 0.5
- tau_update = 0.001
- update_times = [0, 0.02, 0.04, 0.06, 0.08, 0.1, …] [shape=(1502,), min=0, max=30.02]
- Initial condition
- y(0) = [5000, 2000, -100, 30, 0, 0, 200, 0, 4993.57339588, 1990.28677043, -91.5997093571, 39.8526344105]
- Horizon
- t ∈ [0, 10]
Canonical RHS excerpt captured from the same registered callable used for the published benchmark. Frozen closure values are summarized below; helper imports and solver settings are intentionally omitted.
Fingerprint
Spread: high
Default noise: low
Recommendation snapshot
Clean best: SciPy Radau
Noisy best: SciPy RK45
Coverage
14 solver arms · clean + 5 noise levels
Ranked on survival, precision, and speed
Versions & freeze
Methodology →- Freeze
- 2026-08-13
- libsolvsrk
- 2.3.0
- SciPy
- 1.14
- SUNDIALS
- CVODE (bundled backend)
20 seeds/cell default · 14 arms · TRL 4–5 · simulation-lab validated · this page: CLRI-2D horizon h=10 (clri-2d-horizon-h-10)
Governed SolvTune benchmark freeze; per-arm medians only. RHS definitions and raw trial rows are not published.
Self-reported by Resonix Labs · not independently verified
Results matrix
Pick an objective and a noise level to rank all arms on survival, median SCD, median nfev, and median wall time. Medians across seeds.
Objective
Best overall trade-off of survival, precision, and speed.
Noise level
| # | Solver | Survival | SCD | nfev | Wall | Score |
|---|---|---|---|---|---|---|
| 1 | SciPy RadauSciPy | 100% | 10.2 | 512,463 | 8.66 s | 0.861 |
| 2 | Vern9external | 100% | 10.0 | 305,938 | 7.90 s | 0.857 |
| 3 | SciPy LSODASciPy | 100% | 9.3 | 129,380 | 894 ms | 0.841 |
| 4 | SciPy BDFSciPy | 100% | 9.3 | 185,748 | 4.68 s | 0.839 |
| 5 | SciPy RK23SciPy | 100% | 9.1 | 445,628 | 4.34 s | 0.837 |
| 6 | SolvSRK | 100% | 9.1 | 104,870 | 1.88 s | 0.835 |
| 7 | Vern7external | 100% | 8.9 | 202,482 | 6.09 s | 0.830 |
| 8 | CVODE BDFexternal | 100% | 8.8 | 120,938 | 1.11 s | 0.828 |
| 9 | SciPy DOP853SciPy | 100% | 8.7 | 189,230 | 1.56 s | 0.827 |
| 10 | FBDFexternal | 100% | 8.3 | 205,777 | 7.03 s | 0.816 |
| 11 | CVODE Adamsexternal | 100% | 8.2 | 85,466 | 781 ms | 0.815 |
| 12 | Tsit5external | 100% | 7.8 | 149,880 | 8.80 s | 0.805 |
| 13 | SciPy RK45SciPy | 100% | 7.6 | 116,150 | 989 ms | 0.800 |
| 14 | TRBDF2external | 100% | 6.2 | 171,640 | 6.42 s | 0.765 |
At Clean, best balanced arm is SciPy Radau · SolvSRK survival 100%, SCD 9.1.
Values are medians across seeds, measured by Resonix Labs on Resonix hardware and not independently verified; nfev and wall are on reference lab hardware (indicative). Under injected noise only SolvSRK and the SciPy arms are run. How we measure accuracy → · Verification status →
Cite this page
Replace the access date. Pin the freeze ID and library versions when comparing against a later export. Cite it as what it is - a self-reported vendor benchmark, not an independently verified result. The note field says so; please keep it.
@misc{resonix_evidence_clri_2d_horizon_h_10_2026,
title = {Resonix Evidence Portal: CLRI-2D horizon h=10},
author = {{Resonix Labs (Canada) Inc.}},
year = {2026},
howpublished = {\url{https://resonixusa.com/evidence/problems/clri-2d-horizon-h-10}},
note = {Self-reported vendor benchmark; internally generated by Resonix Labs and not independently verified. Accessed YYYY-MM-DD. Freeze 2026-08-13; libsolvsrk 2.3.0; SciPy 1.14.}
}Related
TRL 4–5 · simulation-lab validated · 398 problems · 14 solver arms · clean + 5 noise levels
Freeze: 2026-08-13 · scipy 1.14 · libsolvsrk 2.3.0 · Methodology
Self-reported by Resonix Labs · not independently verified · Verification status