Repository navigation
Conversation
…nl#1332) abs, min, max, clamp and if() over parameters alone, at values that put them exactly on their switch, have no derivative in a parameter that moves it. The compiled dfdp took sign(0) = 0 and the average at a tie: 10*abs(q) + s at q = 0 gave dX*/dq = 0 for one-sided slopes of +-47.62, and 10*min(q, 1) + s at q = 1 gave 23.81 for 47.62 or 0, with no error. Such a column is refused (SensitivityUnsupportedError, naming the parameter, reaction and bend), at the values of each run, steady state, compute_all_sensitivities call and batch row.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1332.
What was wrong
A rate law that bends in a parameter (
abs,min,max,clamp,if()), at a value that puts it exactly on the bend, has no derivative in that parameter. The model is0 -> Xatr(),X -> 0at k1 = 0.21, so X* = r/k1. On main c0877fa, at the steady state and in a run to t = 100 alike:r()10*abs(q) + s10*min(q, 1) + sBoth come from the compiled ∂f/∂p (
sens_dfdp_source"codegen"). It differentiates each branch and takessign(0) = 0and half at a tie (_kink_bindingsin_jacobian.py). Neither number is a derivative, and no error was raised. dX*/ds was right throughout.The fix
New
python/bngsim/_parameter_kinks.py.parameters_on_a_kink(core, params)works as follows:_exprtk_to_sympy(..., bends=True). Parses are cached by text, so a batch's rows cost a lookup.Abs,Max/Min,clampand the relational conditions ofPiecewise.A bend is reported when:
abs(u): u == 0 exactly, and ±u differ in their slope in p.min/max: the extreme is attained by two or more arguments whose slopes in p differ. A tie of one slope has a derivative and is left alone.clamp(lo, x, hi): x is on an edge, with the two sides' slopes differing.if(): a condition's two sides are equal and their difference moves with p. Such a switch is a jump or a corner. This is conservative for anif()whose branches happen to agree in value and slope at the boundary.Exact zero is deliberate. It is precisely where the compiled derivative returns neither side's slope. A bend an ulp away gives the one-sided derivative of the function the engine evaluates.
Simulator._raise_if_param_on_a_kinkraisesSensitivityUnsupportedError, naming each parameter, reaction and bend:It is asked at the values each solve uses, since a
set_paramcan put a parameter on a kink after theSimulatoris built:run(), beside the Forward sensitivity returns a warned-but-wrong gradient at a state-dependent moving crossing (the uncompensated-crossing residue after #150/#355) #414 refusal;steady_state(sensitivity_params=...), beside the other per-parameter refusals;compute_all_sensitivities, for the parameters it targets;run_batchrow, on the row's clone.Tests (
test_sensitivity_parameter_on_a_kink.py, 15)absat 0,minandmaxties at 1,if(q > 0, …)at 0 (4)set_paramonto the kink after the Simulator is builtrun_batchrow on the kink, the model itself off itcompute_all_sensitivitieson the kinks, which the bend does not move, at q = 0min(q, q*(s - 0.3))at q = 1, exactly 1.0 = 1.0; a bend over the state,abs(Xo - q), left to the envelopeMutations
run()does not askset_paramtestcompute_all_sensitivitiesdoes not askK2 first survived on a control that sympy simplified away (
min(q, q)isq), and then on one whose tie missed by an ulp (q*s/1.3). The control in the PR is an exact tie.Measured
Full suite (macOS arm64, main c0877fa + this branch): 16,430 passed, 0 failed, 137 skipped. No existing sensitivity test is refused, and the suite's wall time is unchanged (8 min). The suite ran before
test_compute_all_sensitivities_on_the_kink_is_refusedwas added; that file passes 15 of 15.pre-commit run --all-files(new files staged) andsphinx -Wwithdocs/requirements-ci.txtare clean.Not in this PR
abs(X - q)where X* = q), which the issue also mentions. That is a crossing question and belongs to the envelope.floor,ceilandsignover parameters at a step. Their value jumps there; they were not reported in Forward sensitivity at a parameter that sits on a kink of a rate law returns one side's slope or neither (dX*/dq = 0 for ±47.6), with no error #1332.