generate_initial_disease_states() errors when number_initial_E = 0, and can miscount when number_initial_S = 0
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 92/100
Direzione di ricerca
Inizia con generate_initial_disease_states() e riproduci entrambi gli errori usando gli esempi di parametri presenti nell'issue. Aggiungi casi di regressione a test-variables.R per zero persone esposte e zero persone suscettibili, poi esegui i test R pertinenti. Il lavoro è completo quando ogni combinazione valida dei conteggi iniziali produce i conteggi S, E, I e R richiesti, inclusi i pool contenenti una sola persona.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
generate_initial_disease_states() breaks on two kinds of valid initial conditions:
number_initial_E = 0with any initial I or R people errors withinvalid first argument. For example, you can't start an epidemic from infectious people alone.number_initial_S = 0can silently give the wrong counts. When only one person is left for the last draw, that draw can pick someone already assigned to an earlier state.
Both bugs are on main. They have been there since 6b5daf8 (2024-07-23), which added explicit initial I and R counts.
Reproducer
p <- list(human_population = 100, number_initial_S = 95, number_initial_E = 0,
number_initial_I = 5, number_initial_R = 0, seed = 1)
generate_initial_disease_states(p)
#> Error in sample.int(length(x), size, replace, prob) : invalid first argument
The same error comes through get_parameters() and create_variables(), so run_simulation() can't start either.
p <- list(human_population = 10, number_initial_S = 0, number_initial_E = 9,
number_initial_I = 1, number_initial_R = 0, seed = 1)
table(generate_initial_disease_states(p))
#> E I_mild S
#> 8 1 1
Seeds 1, 4 and 5 give E = 8 and S = 1 instead of E = 9 and S = 0. Seeds 2 and 3 happen to be correct.
Which inputs are affected
Tested with human_population = 100, with each count set to 0 or 5:
| E | I | R | Result |
|---|---|---|---|
| 0 | 0 | 0 | ok |
| 0 | > 0 | any | error |
| 0 | 0 | > 0 | error |
| > 0 | any | any | ok, unless S = 0 (below) |
With S = 0, the counts are wrong for some seeds whenever exactly one person is left for the I draw or the R draw. For example, with N = 10: E = 9, I = 1, R = 0, or E = 5, I = 4, R = 1.
Cause
Two R gotchas in how the remaining pool is built and sampled:
x[-integer(0)]returns an empty vector, notx. When E = 0,exposed_indexisinteger(0). Sopopulation_index[-exposed_index]is empty, and the I and R draws sample from nobody.sample(x, size)treats a single numberxas1:x. When one person is left in the pool,sample()draws from everyone up to that person's index, which can include people already made E or I. The draw overwrites them, and the person who should have been drawn stays S.
Proposed fix
Build each remaining pool with setdiff(), and draw with sample.int() so a pool of one person is handled correctly:
draw <- function(pool, size) pool[sample.int(length(pool), size)]
pool <- seq_along(initial_disease_states)
exposed_index <- draw(pool, parameters_list$number_initial_E)
initial_disease_states[exposed_index] <- "E"
pool <- setdiff(pool, exposed_index)
infectious_index <- draw(pool, parameters_list$number_initial_I)
initial_disease_states[infectious_index] <- "I_mild"
pool <- setdiff(pool, infectious_index)
recovered_index <- draw(pool, parameters_list$number_initial_R)
initial_disease_states[recovered_index] <- "R"
I checked this against the current function for every case above, with seeds 1 to 20:
- It gives the right counts in every case.
- It gives identical output in every case where the current function is already correct, so existing seeded runs don't change.
A single shuffle, sample(rep(c("S", "E", "I_mild", "R"), counts)), would be simpler. But it changes the initial state of every seeded run.
test-variables.R should get cases for E = 0 with I > 0, and for S = 0.
- Lingua principale
- R
- Stelle
- 8
- Fork
- 4
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di petal-code/helios
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
petal-code/helios#174 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
petal-code/helios#173 ·
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 84/100
petal-code/helios#166 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
petal-code/helios#157 · 1 commento ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 55/100
petal-code/helios#178 ·
Tutte le issue di petal-code/helios
Issue simili
-
dbRemoveTable() fails on SQLite with 'near "TRUNCATE": syntax error' and leaves the table in placeAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
OHDSI/DatabaseConnector#348 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 71/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100