Repository navigation
nfsim: integrate a rate a linear time table ramps, and lift the refusal (#1179) - #1448
Merged
Merged
Conversation
…al (#1179) NFsim read a table function indexed by time only at its x values and after each reaction (#892) and held that value in between. A linear table moves in between, so where little fired the run lagged the ramp: from 100 X(p~1) leaving at a rate that ramps from 0 at t = 0 to 10 at t = 1, nf kept all 100 through t = 1, where the exact mean is 1.75. method="nf" refused such a model instead (unreleased). Carry 0020 is amended. Where a linear table indexed by time ramps, stepTo() places the next firing where the propensity integrated from the current time reaches an Exp(1) draw, the time-change theorem, and picks the reaction from the propensities there. Between firings the state is fixed, so the propensity moves with the clock alone; it is integrated over error-controlled 5-point Gauss-Lobatto panels, the scheme bngsim's network SSA and RuleMonkey use, each node a propensity refresh with the clock moved there. No panel spans a breakpoint, and a panel ending on one reads an ulp short of it, so a step table that jumps there is read on the side being integrated. A call that stops inside a ramp leaves the rest of its draw to the next; a breakpoint drops it, as it drops a waiting time. Outside every linear table's ramp stepTo() runs as before. Re-exported and re-vendored on top of #1447's carry 0021; --verify-clean --strict passes with 21 patches. The refusal (refuse_nfsim_linear_time_tables and its scan) is removed, with its unreleased changelog entry. The cold start above now reads 73.3, 29.9 and 1.82 at t = 0.25, 0.5 and 1 against exact 73.4, 29.6 and 1.75 (200 seeds, within 1 SE). On this two-rule model a firing costs about what it does with a step table. Tests check against an ODE solve of one molecule's probability: the four starts of the step-table test on outputs at and between the x values, a file table listed in each order, a saturating rate law that reads the table through another function, a step table that jumps inside the ramp, and a session run in segments that end inside it. With the ramp branch switched off, 11 of these 13 fail; the two that pass are the fixture as written, which fires often enough that the held value was about 3 SE off. test_nfsim.py runs the two linear fixtures again and checks that a file table reads its method. The Windows NFsim cluster goes to 329; its floor moves to 321.
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 #1179. This re-vendors NFsim on top of #1447's carry 0021, which put #1419's direct edit to the vendored shim into the patch series; without it the refresh would have reverted that edit.
What was wrong
NFsim read a table function indexed by time only at its x values and after each reaction (#892), and held that value in between. A linear table keeps moving between its x values, so wherever little fired the run lagged the ramp, with no error. From the issue's cold start (100
X(p~1)leaving at a rate that ramps from 0 at t = 0 to 10 at t = 1),nfkept all 100 through t = 1, where the exact mean is 1.75. Main refused such a model onmethod="nf"instead; that refusal is unreleased.The fix: carry 0020, amended
Where a linear table indexed by time ramps,
System::stepTonow integrates the hazard, as the issue proposed and as bngsim's SSA (#719) and RuleMonkey 3.11 do:next_clocked_event_time, which shares bngsim's SSA scheme, with the same tolerances and the same refusal of a singular rate. Each node is a propensity refresh with the clock moved there. No panel is longer than 1/1000 of the ramp.stepTocall that stops inside a ramp leaves the rest of its draw to the next call. A breakpoint drops it, as it already drops a waiting time; that is exact because the waiting time is memoryless.stepToruns exactly as before. Same-seed trajectories of every model without a ramping linear table are unchanged.The carry is landed on
bngsim/vendor, patches 0020 and 0021 are re-exported, and the tree is re-vendored.vendor_nfsim.py --verify-clean --strictpasses with 21 patches.The refusal (
refuse_nfsim_linear_time_tablesand its scan) is removed, along with its unreleased changelog entry. The #892 entry, the user guide and the carry's docs now describe the integration.Evidence
The issue's cold start, 200 seeds, against exact means:
New tests in
test_nfsim_time_table_breakpoints.pycompare against an ODE solve of one molecule's probability. That gives the exact mean, because every molecule is independent. They cover:NfsimSessionrun in segments that end inside the rampWith the ramp branch switched off, 11 of these 13 fail. The two that pass are the fixture as written, which fires often enough that the old held value was only about 3 SE off.
test_nfsim.pyruns the two linear fixtures again, and checks that a file table reads its method: the linear one interpolates at t = 0.5 and the step one holds.Cost
Each firing inside a ramp costs a few refreshes of every propensity instead of one. On the fixture with 10,000 molecules, a firing took 10.9 µs with the linear table against 10.2 µs with the step table, and the same within noise over a long tail after the ramp. That model has two rules; a model with many rules pays proportionally more per firing, but only while a linear table ramps.
Testing
The NFsim cluster, the network-free checks, the vendoring and the CI-bound tests pass locally (529). The pre-push suite passed. The Windows NFsim cluster grows to 329, so its floor moves to 321.