Dual Simultaneous Engagement (dim=40)
BOUNDARYS2 · dim 40Partial / unstable. SolvSRK survives more than 0% but less than 90% of runs at the comparison noise level, without being beaten by a baseline there. Usable with margin and monitoring; validate on your own configuration. All verdicts →
Two independent 3D engagements coupled through a shared radar resource scheduler. Tests SolvSRK at dim=40 with weak cross-coupling through sensor allocation.
Problem definition
Blackman & Popoli (1999) Ch. 7; Bar-Shalom et al. (2001) Ch. 11
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 _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):
d = np.empty(dim)
# ============== Engagement 1 ==============
xt1, yt1, zt1 = y[0], y[1], y[2]
vxt1, vyt1, vzt1 = y[3], y[4], y[5]
xi1, yi1, zi1 = y[6], y[7], y[8]
vxi1, vyi1, vzi1 = y[9], y[10], y[11]
xh1, yh1, zh1 = y[12], y[13], y[14]
vxh1, vyh1, vzh1 = y[15], y[16], y[17]
# Target 1: 3-D weave
d[0] = vxt1
d[1] = vyt1
d[2] = vzt1
d[3] = a_t1 * np.sin(omega_t1 * t)
d[4] = a_t1 * np.cos(omega_t1 * t)
d[5] = a_t1 * 0.3 * np.sin(0.7 * omega_t1 * t)
# Interceptor 1: PN
rx1 = xh1 - xi1
ry1 = yh1 - yi1
rz1 = zh1 - zi1
vrx1 = vxh1 - vxi1
vry1 = vyh1 - vyi1
vrz1 = vzh1 - vzi1
a_y1, a_z1, lam_h1 = _pn_accel_3d(rx1, ry1, rz1, vrx1, vry1, vrz1)
cos_h1, sin_h1 = np.cos(lam_h1), np.sin(lam_h1)
d[6] = vxi1
d[7] = vyi1
d[8] = vzi1
d[9] = -a_y1 * sin_h1
d[10] = a_y1 * cos_h1
d[11] = a_z1
# EKF 1 propagation
d[12] = vxh1
d[13] = vyh1
d[14] = vzh1
d[15] = 0.0
d[16] = 0.0
d[17] = 0.0
# ============== Engagement 2 ==============
xt2, yt2, zt2 = y[18], y[19], y[20]
vxt2, vyt2, vzt2 = y[21], y[22], y[23]
xi2, yi2, zi2 = y[24], y[25], y[26]
vxi2, vyi2, vzi2 = y[27], y[28], y[29]
xh2, yh2, zh2 = y[30], y[31], y[32]
vxh2, vyh2, vzh2 = y[33], y[34], y[35]
# Target 2: crossing maneuver
d[18] = vxt2
d[19] = vyt2
d[20] = vzt2
d[21] = a_t2 * 0.5 * np.sin(omega_t2 * t)
d[22] = a_t2 * np.cos(omega_t2 * t)
d[23] = a_t2 * 0.4 * np.cos(0.5 * omega_t2 * t)
# Interceptor 2: PN
rx2 = xh2 - xi2
ry2 = yh2 - yi2
rz2 = zh2 - zi2
vrx2 = vxh2 - vxi2
vry2 = vyh2 - vyi2
vrz2 = vzh2 - vzi2
a_y2, a_z2, lam_h2 = _pn_accel_3d(rx2, ry2, rz2, vrx2, vry2, vrz2)
cos_h2, sin_h2 = np.cos(lam_h2), np.sin(lam_h2)
d[24] = vxi2
d[25] = vyi2
d[26] = vzi2
d[27] = -a_y2 * sin_h2
d[28] = a_y2 * cos_h2
d[29] = a_z2
# EKF 2 propagation
d[30] = vxh2
d[31] = vyh2
d[32] = vzh2
d[33] = 0.0
d[34] = 0.0
d[35] = 0.0
# ============== Scheduler ==============
T_dw1 = y[36]
T_dw2 = y[37]
P_det1 = y[38]
P_det2 = y[39]
# Required dwell time grows as track quality degrades
R1 = np.sqrt(rx1**2 + ry1**2 + rz1**2 + 0.01)
R2 = np.sqrt(rx2**2 + ry2**2 + rz2**2 + 0.01)
# SNR proxy: dwell requirement proportional to R^4 (radar equation)
T_req1 = T_frame * 0.5 * (R1 / 10000.0) ** 2
T_req2 = T_frame * 0.5 * (R2 / 10000.0) ** 2
# Resource constraint: if both demand too much, scale proportionally
T_total_req = T_req1 + T_req2
if T_total_req > T_frame:
scale = T_frame / T_total_req
T_req1 *= scale
T_req2 *= scale
d[36] = (T_req1 - T_dw1) / tau_sched
d[37] = (T_req2 - T_dw2) / tau_sched
# Detection probability tracks dwell allocation
P_req1 = _clamp(T_dw1 / max(T_req1, 1e-6), 0.0, 1.0)
P_req2 = _clamp(T_dw2 / max(T_req2, 1e-6), 0.0, 1.0)
d[38] = (P_req1 - P_det1) / (tau_sched * 2.0)
d[39] = (P_req2 - P_det2) / (tau_sched * 2.0)
# ============== Measurement updates ==============
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:
rate = w / max(tau_update, 1e-6)
# EKF gains scale with detection probability (coupling mechanism)
K_pos1 = K_pos_base * _clamp(P_det1, 0.1, 1.0)
K_vel1 = K_vel_base * _clamp(P_det1, 0.1, 1.0)
K_pos2 = K_pos_base * _clamp(P_det2, 0.1, 1.0)
K_vel2 = K_vel_base * _clamp(P_det2, 0.1, 1.0)
_apply_update_3d(
d, 12, xi1, yi1, zi1, xt1, yt1, zt1,
xh1, yh1, zh1,
noise_r1[k], noise_az1[k], noise_el1[k],
K_pos1, K_vel1, rate,
)
_apply_update_3d(
d, 30, xi2, yi2, zi2, xt2, yt2, zt2,
xh2, yh2, zh2,
noise_r2[k], noise_az2[k], noise_el2[k],
K_pos2, K_vel2, rate,
)
return d- Parameters
- K_pos_base = 0.45
- K_vel_base = 0.2
- T_frame = 0.04
- T_update = 0.01
- a_t1 = 25
- a_t2 = 20
- dim = 40
- n_updates = 6002
- noise_az1 = [-0.000571074098886, 0.00613951701106, 0.0111986858872, 0.00251111822914, -0.00828100123578, -0.00509642977247, …] [shape=(6002,), min=-0.0237908612417, max=0.0275451331324]
- noise_az2 = [-0.00802493120427, -0.00688842493785, 0.00291895658592, 0.00417290572287, 0.00505298315343, 0.00863211210178, …] [shape=(6002,), min=-0.0244772839505, max=0.0253622631068]
- noise_el1 = [-0.00760456205273, -0.0118415373737, 0.00864477778914, -0.000794919130315, 0.00163065935121, 0.00592640714088, …] [shape=(6002,), min=-0.028086945892, max=0.0266868366956]
- noise_el2 = [0.00116686219261, -0.0132062108204, 0.00113510407344, 0.00253408933933, -0.0027459250115, 0.000468958680236, …] [shape=(6002,), min=-0.0270059443381, max=0.0267108572122]
- noise_r1 = [1.00584176875, -1.05683890633, 5.12338120355, 0.839200937224, -4.28535498529, 2.89276043928, …] [shape=(6002,), min=-31.1953738404, max=26.0575925977]
- noise_r2 = [0.142193525504, -9.16433609358, 15.0045285553, 5.85616472214, 6.95835361039, 8.85529016343, …] [shape=(6002,), min=-35.9529363214, max=31.2179690985]
- omega_t1 = 0.3
- omega_t2 = 0.6
- tau_sched = 0.1
- tau_update = 0.001
- update_times = [0, 0.01, 0.02, 0.03, 0.04, 0.05, …] [shape=(6002,), min=0, max=60.01]
- Initial condition
- y(0) = [10000, 4000, 2000, -200, 0, -30, …] [shape=(40,), min=-3000, max=10000]
- Horizon
- t ∈ [0, 60]
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: none
Recommendation snapshot
Clean best: SolvSRK
Noisy best: SolvSRK
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: Dual Simultaneous Engagement (dim=40) (dual-simultaneous-engagement-dim-40)
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 | SolvSRK | 20% | - | 2,038,173 | 116.27 s | 0.409 |
| - | SciPy BDFSciPy | 0% | - | - | - | - |
| - | SciPy RadauSciPy | 0% | - | - | - | - |
| - | SciPy RK45SciPy | 0% | - | - | - | - |
| - | SciPy LSODASciPy | 0% | - | - | - | - |
| - | SciPy DOP853SciPy | 0% | - | - | - | - |
| - | SciPy RK23SciPy | 0% | - | - | - | - |
| - | CVODE BDFexternal | 0% | - | - | - | - |
| - | CVODE Adamsexternal | 0% | - | - | - | - |
| - | Tsit5external | 0% | - | - | - | - |
At Clean, best balanced arm is SolvSRK.
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_dual_simultaneous_engagement_dim_40_2026,
title = {Resonix Evidence Portal: Dual Simultaneous Engagement (dim=40)},
author = {{Resonix Labs (Canada) Inc.}},
year = {2026},
howpublished = {\url{https://resonixusa.com/evidence/problems/dual-simultaneous-engagement-dim-40}},
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