Skip to content

Fix zero sensitivity for conservation laws with parameter-dependent initial values - #3259

Draft
dweindl wants to merge 3 commits into
AMICI-dev:mainfrom
dweindl:fix-dtcldp
Draft

Fix zero sensitivity for conservation laws with parameter-dependent initial values#3259
dweindl wants to merge 3 commits into
AMICI-dev:mainfrom
dweindl:fix-dtcldp

Conversation

@dweindl

@dweindl dweindl commented Sep 8, 2026

Copy link
Copy Markdown
Member

A boundary-condition or constant=true SBML species with no counteracting rate rule gets dx/dt=0 and is eliminated into a conservation law. dtcldp (the sensitivity of a conservation law's total abundance w.r.t. free parameters) was unconditionally hardcoded to zero whenever a conservation law spanned only one species, on the assumption that a single-species total abundance can't depend on a parameter. This breaks as soon as the species' initial value does depend on a parameter (e.g. via an InitialAssignment) -- the chain rule for any other state whose rate law references the eliminated species (via its tcl symbol) then silently drops that dependency.

Whether a conservation law's total abundance depends on a free parameter can't be decided from the model's own symbolic initial conditions alone: preequilibration (steady-state Newton solve) and PEtab condition-table state reinitialization compute/override initial states and sensitivities at runtime, entirely bypassing the model's compiled fx0/fsx0. So a species' initial value can depend on a parameter even where the model's own static formula shows no such dependence -- for single- and multi-species conservation laws alike.

dtcldp is therefore now always emitted as a symbol, never folded to a literal zero. The correct numeric value is always computed at runtime via fdtotal_cldp/fdtotal_cldx_rdata.

Verified on SBML semantic test suite case 00783 (parameter-dependent conservation law, single species): sensitivities now match finite differences, where they were previously hardcoded to zero. Also verified against PEtab test suite cases 0010/0017 (multi-species conservation law under partial preequilibration and reinitialization), which an earlier version of this fix -- one that tried to statically detect the parameter-independent case instead of always emitting a symbol -- broke.

Fixes #3249

🤖 Generated with AI assistance.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.52%. Comparing base (3d695c5) to head (074f978).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3259      +/-   ##
==========================================
- Coverage   78.52%   78.52%   -0.01%     
==========================================
  Files         318      318              
  Lines       22199    22197       -2     
  Branches     1490     1491       +1     
==========================================
- Hits        17432    17430       -2     
  Misses       4759     4759              
  Partials        8        8              
Flag Coverage Δ
cpp 72.30% <100.00%> (+<0.01%) ⬆️
cpp_python 35.23% <100.00%> (-0.02%) ⬇️
petab 48.43% <100.00%> (-0.01%) ⬇️
petab_sciml 16.45% <33.33%> (+<0.01%) ⬆️
petab_sciml_benchmarks 15.00% <33.33%> (+<0.01%) ⬆️
python 70.74% <100.00%> (-0.02%) ⬇️
sbmlsuite-jax 31.74% <33.33%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
python/sdist/amici/_symbolic/de_model.py 91.79% <100.00%> (-0.02%) ⬇️
python/sdist/amici/adapters/fiddy.py 88.18% <ø> (-2.37%) ⬇️

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dweindl dweindl self-assigned this Sep 8, 2026
@dweindl
dweindl force-pushed the fix-dtcldp branch 2 times, most recently from e9b0a2c to a17ac10 Compare September 9, 2026 15:27
dweindl and others added 3 commits September 9, 2026 22:23
Add fiddy-based finite differences sensitivity checks to the SBML semantic
test suite.

Splits the single forward-only sensitivity check into three independent
nodes per case (forward/adjoint/consistency), generalizes the retry
scaffold, fixes cross-test-node model-parameter contamination, and skips known-affected cases (events/piecewise,
zero-state models) with adjoint/forward distinguished where relevant. Disables
fiddy's function-call caching by default (pure overhead here, source of
a flaky CI failure).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nitial values

A boundary-condition or `constant=true` SBML species with no counteracting
rate rule gets dx/dt=0 and is eliminated into a conservation law. `dtcldp`
(the sensitivity of a conservation law's total abundance w.r.t. free
parameters) was unconditionally hardcoded to zero whenever a conservation
law spanned only one species, on the assumption that a single-species
total abundance can't depend on a parameter. This breaks as soon as the
species' initial value does depend on a parameter (e.g. via an
InitialAssignment) -- the chain rule for any other state whose rate law
references the eliminated species (via its `tcl` symbol) then silently
drops that dependency.

Whether a conservation law's total abundance depends on a free parameter
can't be decided from the model's own symbolic initial conditions alone:
preequilibration (steady-state Newton solve) and PEtab condition-table
state reinitialization compute/override initial states and sensitivities
at runtime, entirely bypassing the model's compiled `fx0`/`fsx0`. So a
species' initial value can depend on a parameter even where the model's
own static formula shows no such dependence -- for single- and
multi-species conservation laws alike.

`dtcldp` is therefore now always emitted as a symbol, never folded to a
literal zero. The correct numeric value is always computed at runtime via
`fdtotal_cldp`/`fdtotal_cldx_rdata`.

Verified on SBML semantic test suite case 00783 (parameter-dependent
conservation law, single species): sensitivities now match finite
differences, where they were previously hardcoded to zero. Also verified
against PEtab test suite cases 0010/0017 (multi-species conservation law
under partial preequilibration and reinitialization), which an earlier
version of this fix -- one that tried to statically detect the
parameter-independent case instead of always emitting a symbol -- broke.

AMICI-dev#3249

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Forward sensitivities silently wrong (reported as 0) when a boundary-condition species' initial value depends on a parameter

1 participant