Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(non) probabilistic E > I transition (SEIR) #157

Closed
ggrrll opened this issue May 11, 2020 · 11 comments
Closed

(non) probabilistic E > I transition (SEIR) #157

ggrrll opened this issue May 11, 2020 · 11 comments

Comments

@ggrrll
Copy link
Contributor

ggrrll commented May 11, 2020

hi,

if I understood correctly, here

self.progress[u] += self.params['model']['alpha']

you have a 'sharp' transition (step function, w.r.t time from exposure)

I think a probabilistic version would be better (more realistic), like the one I am attempting here:

ggrrll@6fcec70#diff-55a281f20b0ed52ec6ac2dc08e33ce64R91

that is basically the one mentioned in the paper you referenced

@ggrrll
Copy link
Contributor Author

ggrrll commented May 12, 2020

of course, if you want to keep it similar to the one of the paper, also this

https://github.com/ggrrll/ndlib/blob/6fcec70b9948c62ae0935d061ab2451f31e113e2/ndlib/models/epidemics/SEIRModel.py#L91

should be changed as ~ 1 - exp( - 𝛼 * t)

@GiulioRossetti
Copy link
Owner

Hi,
I completely agree.
The implementation was made by a group of students (as part of a small project) that opted for a step function to simplify their implementation.

If you like to address the discrepancy feel free to make a pull request, I'll be happy to merge it in the master branch!

Giulio

@ggrrll
Copy link
Contributor Author

ggrrll commented May 18, 2020

sorry, the implementation in this commit/line

https://github.com/ggrrll/ndlib/blob/6fcec70b9948c62ae0935d061ab2451f31e113e2/ndlib/models/epidemics/SEIRModel.py#L91

is wrong, as we should of course consider the time, since exposure

@ggrrll
Copy link
Contributor Author

ggrrll commented May 20, 2020

closed due to #164

@mihaibanciu
Copy link

mihaibanciu commented Jul 9, 2020

@GiulioRossetti @ggrrll Sorry to revisit this, but according to the paper referenced at the top of the thread, both E->I and I->R transition probabilities follow exponential distributions. Here's what it says in section 2:

(iii) an exposed individual's probability of becoming infectious in a specified time interval is independent of time after initial contact, so that the probability of remaining in the exposed class at time t after initial contact is e^(-at), where 1/a is the mean latent period; (iv) after an individual becomes infective, the probability of that individual recovering after time t is e^(-gt), where 1/g is the mean infectious period.

Accordingly, I modified the code to reflect the same logic in transitioning from I to R. Didn't want to open a new issue, so I'm posting the suggestion below:

@ -62,6 +62,9 @@ class SEIRModel(DiffusionModel):
            else:
                return {"iteration": 0, "status": {},
                        "node_count": node_count.copy(), "status_delta": status_delta.copy()}
+            for u in self.graph.nodes:
+                if self.status[u] == 1:
+                    self.progress[u] = 0 # set timestamp t_0 = 0 for all infected nodes in fraction_infected

        for u in self.graph.nodes:

@ -87,14 +90,15 @@ class SEIRModel(DiffusionModel):

            elif u_status == 2:

-                # apply prob. of infection, after (t - t_i) 
-                if eventp < 1 - np.exp(- (self.actual_iteration - self.progress[u]) * self.params['model']['alpha']): 
+                # apply prob. of infection, after (t - t_i)
+                if eventp < 1 - np.exp(- (self.actual_iteration - self.progress[u]) * self.params['model']['alpha']):
                    actual_status[u] = 1  # Infected
-                    del self.progress[u]
+                    self.progress[u] =  self.actual_iteration # save time of infection t_i


            elif u_status == 1:
-                if eventp < self.params['model']['gamma']:
+                if eventp < 1 - np.exp(- (self.actual_iteration - self.progress[u]) * self.params['model']['gamma']):
                    actual_status[u] = 3  # Removed
+                    del self.progress[u]

        delta, node_count, status_delta = self.status_delta(actual_status)
        self.status = actual_status

Apologize if this is the wrong way to go about. I'm a noob at using Github and didn't want to break anything by accident!

@ggrrll
Copy link
Contributor Author

ggrrll commented Jul 20, 2020

@mihaibanciu sorry for the late reply

Actually, this is something I have implemented few moths ago in two v.
https://github.com/ggrrll/ndlib/branches

and we actually quickly chatted with @GiulioRossetti about it, some time ago...

Indeed I was wondering whether we should have an 'exponential' implementation (like in branch: cont_time:SEIRModel ) or rather have all transitions in rate-like implementation (like in branch: SEIRModel:disc_time )

@mihaibanciu
Copy link

I think it should be done. The Exponential looks so different than the Uniform distribution and the models are so sensitive to initial parameters so that the final counts per each state could look very different if this is not addressed.

BTW, in your branch you mention an error on L96 in the seir model. Is that a KeyError? I'm seeing the same. I wonder if one needs to initialize self_progress with t_i = 0 for all nodes that are in fraction_infected at iteration 0. See my first three suggested additions, above.

@GiulioRossetti
Copy link
Owner

GiulioRossetti commented Jul 20, 2020

Sorry for the late reply.

Indeed, it make sense to have both implementations in NDlib since we got several requests (both here and via email) asking for them.

I think that, at this point, the optimal solution will be to add continuous versions for both SEIR and SEIS models.

If you agree I'll give a look to your implementations to understand the nature of the error and move forward with the inclusion.

@GiulioRossetti
Copy link
Owner

@mihaibanciu @ggrrll check out the implementations in the dedicated branch.

If they are fine, I'll push them into master and include the in the next release (that I would like to release within this week).

@ggrrll: The error you faced was due to a missing initialization of infection seeds progress variable, as correctly pointed out by @mihaibanciu. To make things more readable I splitted the progress tracking in two disjoint dict.

@mihaibanciu
Copy link

@GiulioRossetti As far as I can tell the cont branch looks good, I just looked at the *_ct.py files. I noticed one typo in a file name:
DynamicCompostiteModel.py --> DynamicCompositeModel.py (there's an extra 't' in Composite that should disappear).

@GiulioRossetti
Copy link
Owner

Ok that's something that can be easily fixed :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants