Summary
On the sbml_backend = bngsim fast path (the cached-clone + set_param route added in #415), a
parameter whose value is fixed by an initialAssignment is never recomputed. bngsim evaluates
the assignment once when the engine template is loaded, and set_param does not propagate to it, so
the derived parameter keeps its load-time value for the whole fit even when the parameters it is
derived from are fitted or set by a condition:.
_compute_initial_dependency_names only ever seeded its dependency set from initialAssignments on
species; an assignment on a parameter was collected into expr_refs but never marked as needing
a recompute.
Impact
The simulated model silently disagrees with what the same job produces through the reload path (and
with what any other PEtab tool produces). It is a scalar-path bug: it corrupts the objective for
every optimizer, not just the gradient ones.
Bertozzi_PNAS2020 (Benchmark-Models-PEtab, in the Grein et al. 2026 subset) is the worked example:
<initialAssignment symbol="beta_N"> <!-- beta_N = R0_ * gamma_ / N_ -->
beta_N is the only place R0_ reaches the dynamics, and the conditions set
R0_ = R0_CA / R0_ = R0_NY and N_ = 39560000. Observed before the fix:
base I_ : [5.00e+02 1.46e+07 5.35e+06 1.97e+06]
R0_ 3 -> 3.3 max trajectory delta = 0 # R0_ is completely inert
engine beta_N (fast path) = 0.01 # the load-time value (R0_=0.1, gamma_=0.1, N_=1)
engine beta_N (reload) = 8.34e-09 # the correct R0_*gamma_/N_
Two of the eight free parameters (R0_CA, R0_NY) therefore had an identically flat objective, and
the reported nominal NLL was 1.79e11 against a reference J* = 158.86. With the fix the fast path
is byte-identical to the reload path and the trajectory tracks the data.
Fix
Treat a parameter with an initialAssignment as the derived constant SBML says it is: seed the
initial-dependency set from parameter assignments as well as species ones, recompute both in
_recompute_initial_assignments (via libSBML's expandInitialAssignments, as the species initials
already are), and apply the recomputed parameter values to the engine clone alongside the
recomputed species initials. A parameter an assignmentRule or rateRule governs is excluded --
bngsim recomputes those dynamically, so an initial override would fight the rule.
Scope
bngsim SBML/Antimony backend only. The reload path (_needs_structural_reload) was already correct
and is the oracle the regression test compares against.
Summary
On the
sbml_backend = bngsimfast path (the cached-clone +set_paramroute added in #415), aparameter whose value is fixed by an
initialAssignmentis never recomputed. bngsim evaluatesthe assignment once when the engine template is loaded, and
set_paramdoes not propagate to it, sothe derived parameter keeps its load-time value for the whole fit even when the parameters it is
derived from are fitted or set by a
condition:._compute_initial_dependency_namesonly ever seeded its dependency set frominitialAssignments onspecies; an assignment on a parameter was collected into
expr_refsbut never marked as needinga recompute.
Impact
The simulated model silently disagrees with what the same job produces through the reload path (and
with what any other PEtab tool produces). It is a scalar-path bug: it corrupts the objective for
every optimizer, not just the gradient ones.
Bertozzi_PNAS2020(Benchmark-Models-PEtab, in the Grein et al. 2026 subset) is the worked example:beta_Nis the only placeR0_reaches the dynamics, and the conditions setR0_ = R0_CA/R0_ = R0_NYandN_ = 39560000. Observed before the fix:Two of the eight free parameters (
R0_CA,R0_NY) therefore had an identically flat objective, andthe reported nominal NLL was
1.79e11against a referenceJ* = 158.86. With the fix the fast pathis byte-identical to the reload path and the trajectory tracks the data.
Fix
Treat a parameter with an
initialAssignmentas the derived constant SBML says it is: seed theinitial-dependency set from parameter assignments as well as species ones, recompute both in
_recompute_initial_assignments(via libSBML'sexpandInitialAssignments, as the species initialsalready are), and apply the recomputed parameter values to the engine clone alongside the
recomputed species initials. A parameter an
assignmentRuleorrateRulegoverns is excluded --bngsim recomputes those dynamically, so an initial override would fight the rule.
Scope
bngsim SBML/Antimony backend only. The reload path (
_needs_structural_reload) was already correctand is the oracle the regression test compares against.