heemod
heemod copied to clipboard
Transition Costs/Effects
I was taking a look at the way transitional cost/effects are currently implemented through tunnel states (relevant: #137) and was wondering if there might be a more parsimonious solution.
The counts of patients entering/exiting can be calculated directly from the Markov calculations without requiring the creation of tunnel states.
Would be interested in hearing thoughts on whether this is worthwhile enough to work on a pull request. Details of what I am doing below...
How this is currently done in compute_counts.eval_matrix:
add_and_mult <- function(x, y) {
(x + inflow) %*% y
}
list_counts <- Reduce(
add_and_mult,
x,
init,
accumulate = TRUE
)
Alternately, one could do:
# Make a diagonal matrix of inital state vector
init_mat = diag(init)
# Do element-wise multiplication to get the numbers
# undergoing each transition
calc_trans <- function(x, y) {
(colSums(x) + diag(inflow)) * y
}
uncond_trans <- Reduce(
calc_trans,
x,
init_mat,
accumulate = TRUE
)
# Sum over columns to get trace
list_counts <- lapply(
uncond_trans,
colSums
)
uncond_trans then represents the counts undergoing each possible transition. These can then be used to calculate the entry/exit counts:
# Zero out diagonals
zero_diag <- function(x) {
n_cols = ncol(x)
diag_one = diag(1,n_cols)
return(x - x*diag_one)
}
zero_diag_trans <- lapply(
uncond_trans,
zero_diag
)
# Sum over rows and add inflow to get entry counts
entry_counts <- lapply(
zero_diag_trans,
function(mat) colSums(mat) + inflow
)
# Add initial state vector to entry at time 0
entry_counts[[1]] = entry_counts[[1]] + init
# Sum over columns to get exit counts
exit_counts <- lapply(
zero_diag_trans,
rowSums
)
Thanks, I'll have a look!
This way of computing transitions indeed keeps track of everything. Implementing transition costs is just a simple matter of coding, except for the following questions:
- What kind of transition costs do we want to feature in
heemod
? Entry/exit costs, or more specific from-x-to-y-costs? (or both? I'd rather have both.) - How do we specify them in the UI? (ideally in a way that is clear, readable, not too tedious)
Some random thoughts:
- The transition costs should be defined by strategy, not by model.
- They should work with model-time and state-time dependency.
- They can impact any state values.
My guess about the best way to handle the syntax would be to declare transitions in much the same way that users already declare states. Example:
define_transition = function(from=NULL, to=NULL, ...) {
# implementation
}
This would allow for all three cases:
- User specifies
from
only -> exit cost/effect - User specifies
to
only -> entry cost/effect - User specifies both
from
andto
-> transition cost/effect
Another important note I should mention is that my code doesn't handle the case where tunnel states are present. This doesn't affect exit costs, but it would be important to zero out transitions into any tunnel (except the first), otherwise those entry costs would be calculated as if they were a state residency cost.