Summary
In ModelMeaslesSchool, the m_update_rash and m_update_isolated functions incorrectly map the outcomes of the SAMPLE_FROM_PROBS macro, causing the hospitalization probability to differ from the expected competing-risks formula.
Expected behavior
The probability of hospitalization (conditional on leaving the rash state) should be:
$$P(\text{hosp}) = \frac{h}{h + r}$$
where $h$ is the hospitalization rate and $r = 1/\text{rash period}$ is the recovery rate.
Actual behavior
Due to the swapped outcome mapping, agents recover with daily probability $1 - r - h$ (the "nothing happens" leftover) instead of $r$. This yields:
$$P(\text{hosp}) = \frac{h}{1 - r}$$
Root cause
The SAMPLE_FROM_PROBS(2, which) macro (defined at the top of measlesschool.hpp) draws from a cumulative roulette and assigns outcomes as:
which |
Probability |
| 0 |
array_double_tmp[0] |
| 1 |
array_double_tmp[1] |
| 2 |
remainder: 1 - [0] - [1] |
In both m_update_rash and m_update_isolated, the arrays are set to:
m->array_double_tmp[0] = 1.0/m->par("Rash period"); // recovery rate r
m->array_double_tmp[1] = m->par("Hospitalization rate"); // hosp rate h
But the outcome handling code had which == 0 → "stay in rash" (or just isolate if detected) and which == 2 → "recover", which is backwards. which == 0 fires with probability r (the recovery rate) but was mapped to "nothing happens", while which == 2 fires with probability 1 - r - h (the true "nothing happens" remainder) but was mapped to "recover".
Fix
Swap the outcome handling so that:
which == 0 (probability r = 1/rash_period) → recover
which == 2 (probability 1 - r - h) → stay in current state (no transition)
This was applied to both m_update_rash and m_update_isolated. Test expectations in 14a-measles.cpp and 14b-measles.cpp were also updated: p_recovered changed from 1 - (1/rash_period + hosp_rate) to 1/rash_period.
Affected files
include/epiworld/models/measlesschool.hpp — two functions: m_update_rash, m_update_isolated
tests/14a-measles.cpp — test expectation for p_recovered
tests/14b-measles.cpp — test expectation for p_recovered
Summary
In
ModelMeaslesSchool, them_update_rashandm_update_isolatedfunctions incorrectly map the outcomes of theSAMPLE_FROM_PROBSmacro, causing the hospitalization probability to differ from the expected competing-risks formula.Expected behavior
The probability of hospitalization (conditional on leaving the rash state) should be:
where$h$ is the hospitalization rate and $r = 1/\text{rash period}$ is the recovery rate.
Actual behavior
Due to the swapped outcome mapping, agents recover with daily probability$1 - r - h$ (the "nothing happens" leftover) instead of $r$ . This yields:
Root cause
The
SAMPLE_FROM_PROBS(2, which)macro (defined at the top ofmeaslesschool.hpp) draws from a cumulative roulette and assigns outcomes as:whicharray_double_tmp[0]array_double_tmp[1]1 - [0] - [1]In both
m_update_rashandm_update_isolated, the arrays are set to:But the outcome handling code had
which == 0→ "stay in rash" (or just isolate if detected) andwhich == 2→ "recover", which is backwards.which == 0fires with probabilityr(the recovery rate) but was mapped to "nothing happens", whilewhich == 2fires with probability1 - r - h(the true "nothing happens" remainder) but was mapped to "recover".Fix
Swap the outcome handling so that:
which == 0(probabilityr = 1/rash_period) → recoverwhich == 2(probability1 - r - h) → stay in current state (no transition)This was applied to both
m_update_rashandm_update_isolated. Test expectations in14a-measles.cppand14b-measles.cppwere also updated:p_recoveredchanged from1 - (1/rash_period + hosp_rate)to1/rash_period.Affected files
include/epiworld/models/measlesschool.hpp— two functions:m_update_rash,m_update_isolatedtests/14a-measles.cpp— test expectation forp_recoveredtests/14b-measles.cpp— test expectation forp_recovered