Implemented first pass at generalizable compartmental model#1
Implemented first pass at generalizable compartmental model#1kabirmoghe wants to merge 1 commit intomainfrom
Conversation
| def __init__( | ||
| self, | ||
| compartments: List[str], | ||
| states: Dict[str, float], |
There was a problem hiding this comment.
Looks like you don't need this param, which is nice! Less params == :)
| compartments: List[str], | ||
| states: Dict[str, float], | ||
| parameters: Dict[str, float], | ||
| transitions: List[Dict], |
There was a problem hiding this comment.
I love how you designed the notion of a transition. It feels like a great way of thinking about a compartmental model.
Actually writing down the transitions is going to be difficult no matter how you implement it. Ideally, you'd like a programmer to be able to understand how to create the right argument to pass to transitions just by reading the documentation. It took me a few examples to understand how the transitions data needed to be structured. I might add some examples to the docs and make the argument description super clear and specific.
You might be able to accept an adj matrix of transition functions instead of a dictionary. But I don't know which is clunkier.
There was a problem hiding this comment.
Definitely a bit unintuitive, so I'll add some detailed documentation for that + examples. I think an adjacency matrix would be tricky given the nature of some of the transitions, right?
There was a problem hiding this comment.
You would be the expert on this rather than me! I mainly gave the adj matrix as an contrasting example to help illustrate how the form of parameters can make the function easier or harder to use. As long as you've thought about it, I trust your judgement.
| def drift(self, x: np.ndarray, ti: float): | ||
| """Deterministic component of the compartmental model""" | ||
| # Defines each state and derivative | ||
| current_states = dict(zip(self.compartments, x)) |
There was a problem hiding this comment.
With the way interfere is designed, you're going to have to assume that the order of the variables in x corresponds to the order of variables in self.compartments.
At the same time, this assumption might let you streamline your transition functions by writing them as:
I_to_R = lambda S, I, R, beta, sigma, gamma: gamma * I * Rthen when you call them it could look like this
for compartment_idx in range(self.dim)
for f in self.transition_adj[component_idx, :]:
dX[compartment_idx] += f(*x, **self.parameters)as long as parameters is a dict that has all the correct param names.
I'm not saying that you have to do this, just that it is something to think about. The main goal is to streamline the code and make it easy for other people to use.
| if self.scalar_noise: | ||
| noise *= rate | ||
|
|
||
| rate += noise | ||
|
|
||
| # Modifying states using rate | ||
| if prev_state is not None: | ||
| derivatives[prev_state] -= rate | ||
| if next_state is not None: | ||
| derivatives[next_state] += rate |
There was a problem hiding this comment.
It's tricky to see if noise implemented this way can be expressed in the form of a standard SDE which is:
dX = mu(x, t)dt + sigma(x, t) dW
see here for details .
I can probably write the noise functions for you. I just need to know if people model the noise on the transition level or if they usually model it at the compartmental level. (You are doing it at the transition level here) I can even use the parameter scalar noise to toggle between additive and multiplicative noise inside the noise function.
There was a problem hiding this comment.
Yeah, that's a good question to ask. I'm honestly not sure, but intuitively, it seemed like keeping it at the transition level was at least a decent way of preserving the system's total population. Does the way it's written now seem like it makes sense?
There was a problem hiding this comment.
That's a good justification for modeling it at the transition level. For the scope of work here it's worth it to me to have the model conform to the standard SDE format even if there are fluctuations in the total population.
No description provided.