Skip to content

rm: run a time-indexed table far from t = 0 on RuleMonkey 3.12.0 (#1063) - #1222

Merged
wshlavacek merged 1 commit into
mainfrom
fix/1063-rm-time-table-late-start
Oct 23, 2026
Merged

wshlavacek merged 1 commit into
mainfrom
fix/1063-rm-time-table-late-start

Conversation

@wshlavacek

Copy link
Copy Markdown
Collaborator

Closes #1063.

#1109 and #1188 moved rm runs and sessions of a model that reads time() through its functions onto elapsed time. They left one case, a model with a table function indexed by time, on model time: offsetting a table's clock would index it through a function, which RuleMonkey 3.11.0 could not evaluate (richardposner/RuleMonkey#111). On model time, #1022's require_resolvable_clock refused any run, segment or step whose span the doubles near its times could not divide into RuleMonkey's integration panels, for example a span of 2 at t = 1e13.

RuleMonkey 3.12.0, vendored in #1220, keeps its clock as a per-call origin plus elapsed time. It places events, samples and its panels for a rate that reads the clock on the elapsed part (richardposner/RuleMonkey#110), and rounds only the clock a rate reads to the doubles near it. The table case needs no offset any more, and the refusal now turns away runs RuleMonkey gets right. This PR removes it from run(), step_to() and simulate().

Measured

The fixture is bngsim's step table, which reads 20 for t ≥ 2, seeded with 10⁴ X(p~1) and dephos = 0.001, for a total propensity of 2×10⁵. The table shows X_phos at t0 + 0.05 over 20 seeds, against the closed form on the span the doubles near t0 hold:

t0 main RuleMonkey 3.12.0 alone (rm_driver --t-start) this branch
3 z = −1.1 z = −1.1 z = −1.1
1e9 refused z = −1.1 runs
1e12 refused z = −1.1 runs
1e13 refused z = −1.2 runs

Tests

  • New: test_a_time_indexed_table_keeps_its_waiting_times_far_from_t0 runs that model one-shot and as a RuleMonkeySession from 1e12 and 1e13, 40 seeds each, against the closed form. All four cases fail on main with the refusal.
  • Converted: test_a_clock_too_coarse_to_integrate_over_is_refused pinned the refusal, and becomes test_a_short_span_far_from_t0_runs. The table model now runs that span one-shot, as a session segment and as a step. The test's half for clock-reading functions is unchanged.
  • RuleMonkey tests (the 18 files that drive it): 500 passed, 3 skipped. That is 496 before plus the 4 new cases.
  • Full suite: the pre-push hook's full python/tests run passed.

Corrections to #1220 and #1063's fragments

docs/user-guide/network-free.md, the set_reads_clock header comment and binding docstring (with the regenerated .pyi), and the comments in _rulemonkey_clock.py, _simulator.py and rulemonkey_simulator.cpp say the same.

Not changed

#1059 stays open. method="ssa" keeps its rounding limit on a rate that reads time(), which runs on the continuous loop (#1075's "Not covered"). An SSA event whose trigger reads the clock can also still fire up to half a spacing early.

A model with a table function indexed by time is the one rm still runs
on model time (#1109 and #1188 offset only time() through functions).
On RuleMonkey 3.11.0 that placed events at t + tau in absolute time,
and its panels for a rate that reads the clock at t + k*h, so #1022
added require_resolvable_clock: it refused a run, segment or step
whose span the doubles near its times could not divide into panels of
a thousandth (a span of 2 at t = 1e13).

RuleMonkey 3.12.0, vendored in #1220, keeps its clock as a per-call
origin plus elapsed time and places events, samples and those panels
on the elapsed part (richardposner/RuleMonkey#110). Only the clock a
rate reads is rounded to the doubles near it. So the refusal now turns
away runs RuleMonkey gets right, and this removes it from run(),
step_to() and simulate().

Measured on bngsim's step-table fixture, which reads 20 for t >= 2,
seeded with 10^4 X(p~1) and dephos 0.001 (a total propensity of 2e5),
20 seeds, X_phos at t0 + 0.05 against the closed form on the span the
doubles near t0 hold:

    t0      before (main)   RuleMonkey 3.12.0 alone   this branch
    3       z = -1.1        z = -1.1                  z = -1.1
    1e9     refused         z = -1.1                  runs
    1e12    refused         z = -1.1                  runs
    1e13    refused         z = -1.2                  runs

The new test_a_time_indexed_table_keeps_its_waiting_times_far_from_t0
runs that model one-shot and as a session from 1e12 and 1e13, 40 seeds
each, against the closed form; all four cases fail on main with the
refusal.  test_a_clock_too_coarse_to_integrate_over_is_refused pinned
the refusal and becomes test_a_short_span_far_from_t0_runs: the table
model now runs that span one-shot, as a session segment and as a step.

This also corrects #1220's fragment.  It credited the re-vendor with
"a model that reads the clock keeps its waiting times from a large
t_start", but the model I measured that on read time() through a
function, which #1109 had already moved onto elapsed time; the case
3.12.0 changes is this one.  Its sentence about Arrhenius rules
staying refused until #1058 is dropped too, since #1221 lifted them.
1063.fixed.md, which said a table "still runs on model time" because
3.11.0 recursed on a function counter (richardposner/RuleMonkey#111),
now says what 3.12.0 does, as do network-free.md, the set_reads_clock
comment and docstring, and the comments in _rulemonkey_clock.py and
_simulator.py.

RuleMonkey tests (the 18 files that drive it): 500 passed, 3 skipped.
@wshlavacek
wshlavacek merged commit 94dc017 into main Oct 23, 2026
21 checks passed
@wshlavacek
wshlavacek deleted the fix/1063-rm-time-table-late-start branch October 23, 2026 06:17
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.

rm: run a model that reads the clock on elapsed time with time() offset by t_start, so a late start keeps its waiting times (#1059)

1 participant