Summary
#95 bounded the build-time symbolic derivation for the analytical Jacobian:
a model that does not derive within budget falls back to the finite-difference
Jacobian instead of hanging the build. The sensitivity df/dp path added by
#55 (#65/#66/#67/#68) does the same kind of sympy work and has no budget at
all.
python/bngsim/_codegen.py contains zero references to deadline. Its three
sp.diff call sites are all unguarded:
| line |
function |
what it differentiates |
| 1564 |
_derived_expr_partials_numeric |
a derived-parameter / IC-seed / switch-threshold expression |
| 1679 |
_compute_derived_param_jacobian |
a derived rate constant w.r.t. its primaries |
| 5879 |
_functional_rate_law_partials |
a Functional rate law w.r.t. every parameter it reads |
The Jacobian path, by contrast, has the whole apparatus: _derivation_budget_s(n_species),
the BNGSIM_JAC_DERIV_BUDGET_S override, _DerivationBudgetExceeded, and a
check inside differentiate_rate_law's per-observable loop
(python/bngsim/_jacobian.py:349) so overshoot is bounded to one rate law even
for a pathological single reaction.
#55 itself flagged this in its "What still has to bail" list — "an N-parameter
df/dp multiplies the SymPy work by N. Needs the same budget guard" — and each
of the four stages deferred it because the corpus never came close.
Why it has not bitten
Measured over all 185 non-Elementary corpus models during #66: 2.6 s total,
0.31 s worst model. Nowhere near any plausible budget.
Why it will
Line 5879 is the one that scales badly. It runs one sp.diff per (rate law,
parameter it reads) pair, so cost grows with the product of rate-law size and
parameter count — exactly the axis #95 found super-linear for the Jacobian. The
genome-scale models #95 and #187 identify (BIOMD0000000496, 0000000628,
0000000595, MODEL1001200000) derive for 40 s to >1 min for the Jacobian alone,
where the ODE solve is already sub-second.
A model of that size with a Functional rate law and a large
sensitivity_params list would multiply that, and the failure mode is a build
that appears to hang rather than one that declines and says why. Worse for
rr_parity-style harnesses, which time build+solve together, so a slow
derivation reads as an ODE timeout (the #95 symptom).
Suggested fix
Reuse the #95 machinery rather than adding a second budget — the same reasoning
#68 applied to the switch-condition guard:
- Thread a
deadline through _functional_dfdp_terms ->
_functional_rate_law_partials, checked before each sp.diff in the
per-parameter loop, so overshoot is bounded to one (law, parameter) pair.
- On
_DerivationBudgetExceeded, decline the analytic sensitivity RHS through
the existing _warn_functional_sens_rhs_refused, so it lands with every
other decline reason and CVODES' difference quotient answers instead —
correct, slower, and loud.
- Decide whether the budget is shared with the Jacobian's or separate. Shared
is simpler but means a model that spent its budget on the Jacobian silently
loses the sensitivity RHS too; separate doubles the worst-case build time.
Worth settling explicitly rather than by accident.
_derived_expr_partials_numeric and _compute_derived_param_jacobian are
lower risk (one expression, not N x rate laws) but are on the same path and
should probably take the same deadline for consistency.
Not in scope
Michaelis-Menten's df/dp (#88) is closed form and calls no sympy at all, so it
adds nothing to this and needs no guard.
Summary
#95 bounded the build-time symbolic derivation for the analytical Jacobian:
a model that does not derive within budget falls back to the finite-difference
Jacobian instead of hanging the build. The sensitivity
df/dppath added by#55 (#65/#66/#67/#68) does the same kind of sympy work and has no budget at
all.
python/bngsim/_codegen.pycontains zero references todeadline. Its threesp.diffcall sites are all unguarded:_derived_expr_partials_numeric_compute_derived_param_jacobian_functional_rate_law_partialsThe Jacobian path, by contrast, has the whole apparatus:
_derivation_budget_s(n_species),the
BNGSIM_JAC_DERIV_BUDGET_Soverride,_DerivationBudgetExceeded, and acheck inside
differentiate_rate_law's per-observable loop(
python/bngsim/_jacobian.py:349) so overshoot is bounded to one rate law evenfor a pathological single reaction.
#55 itself flagged this in its "What still has to bail" list — "an N-parameter
df/dpmultiplies the SymPy work by N. Needs the same budget guard" — and eachof the four stages deferred it because the corpus never came close.
Why it has not bitten
Measured over all 185 non-Elementary corpus models during #66: 2.6 s total,
0.31 s worst model. Nowhere near any plausible budget.
Why it will
Line 5879 is the one that scales badly. It runs one
sp.diffper (rate law,parameter it reads) pair, so cost grows with the product of rate-law size and
parameter count — exactly the axis #95 found super-linear for the Jacobian. The
genome-scale models #95 and #187 identify (BIOMD0000000496, 0000000628,
0000000595, MODEL1001200000) derive for 40 s to >1 min for the Jacobian alone,
where the ODE solve is already sub-second.
A model of that size with a Functional rate law and a large
sensitivity_paramslist would multiply that, and the failure mode is a buildthat appears to hang rather than one that declines and says why. Worse for
rr_parity-style harnesses, which time build+solve together, so a slowderivation reads as an ODE timeout (the #95 symptom).
Suggested fix
Reuse the #95 machinery rather than adding a second budget — the same reasoning
#68 applied to the switch-condition guard:
deadlinethrough_functional_dfdp_terms->_functional_rate_law_partials, checked before eachsp.diffin theper-parameter loop, so overshoot is bounded to one (law, parameter) pair.
_DerivationBudgetExceeded, decline the analytic sensitivity RHS throughthe existing
_warn_functional_sens_rhs_refused, so it lands with everyother decline reason and CVODES' difference quotient answers instead —
correct, slower, and loud.
is simpler but means a model that spent its budget on the Jacobian silently
loses the sensitivity RHS too; separate doubles the worst-case build time.
Worth settling explicitly rather than by accident.
_derived_expr_partials_numericand_compute_derived_param_jacobianarelower risk (one expression, not N x rate laws) but are on the same path and
should probably take the same deadline for consistency.
Not in scope
Michaelis-Menten's
df/dp(#88) is closed form and calls no sympy at all, so itadds nothing to this and needs no guard.