Last active
March 27, 2020 13:13
-
-
Save lucasgautheron/f424f7be262681b632ffd7aa7dbef10f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SystemState { | |
constructor() { | |
this.S = 1; | |
this.E = []; | |
this.A = []; | |
this.I = []; | |
this.R = []; | |
this.M = 0; | |
this.time = 0; | |
for (let i = 0; i < 2; ++i) { | |
this.E[i] = 0; | |
this.A[i] = 0; | |
this.I[i] = 0; | |
this.R[i] = 0; | |
} | |
this.I[0] = 0.0002; | |
} | |
evolve(system, prev_state, dt) { | |
let lambda = (system.beta[0]*(prev_state.A[0]+prev_state.I[0]+prev_state.A[1]) | |
+ system.beta[1] * prev_state.I[1]) * (1-system.c); | |
this.S = prev_state.S - (lambda * prev_state.S) * dt; | |
for (let i = 0; i < 2; ++i) { | |
this.A[i] = prev_state.A[i] + (system.epsilon * prev_state.E[i] - system.sigma * prev_state.A[i]) * dt; | |
this.R[i] = prev_state.R[i] + (system.gamma[i] * prev_state.I[i]) * dt; | |
this.I[i] = prev_state.I[i] + (system.sigma * prev_state.A[i] - system.gamma[i] * prev_state.I[i]) * dt | |
} | |
this.I[1] -= (system.alpha * prev_state.I[1]) * dt; | |
this.E[0] = prev_state.E[0] + ( | |
(system.p * lambda * prev_state.S) | |
- system.epsilon * prev_state.E[0] | |
+ system.p * system.nu | |
) * dt | |
this.E[1] = prev_state.E[1] + ( | |
((1-system.p) * lambda * prev_state.S) | |
- system.epsilon * prev_state.E[1] | |
+ (1-system.p) * system.nu | |
) * dt | |
this.M = prev_state.M + system.alpha * prev_state.I[1] * dt; | |
this.time = prev_state.time + dt; | |
} | |
} | |
class SocialDistancingRule { | |
constructor(begin, end, efficiency) { | |
this.begin = begin; | |
this.end = end; | |
this.efficiency = efficiency; | |
} | |
includes(time) { | |
return time > this.begin && time < this.end; | |
} | |
} | |
class System { | |
constructor(seasonalForcing = 0, | |
socialDistancingRules = [], | |
epsilon = 1/4.2, sigma = 1, gamma1 = 1/17, gamma2 = 1/20, | |
R0 = 2.5, p = 0.9, theta = 0.15, | |
nu = 1e-6, b = 0.2, | |
c = 0) { | |
this.epsilon = epsilon; // taux de fin de latence [jour^-1] | |
this.sigma = sigma; // taux d'apparition des symptomes [jour^-1] | |
this.gamma = [gamma1, gamma2]; // taux de guérison des infections légères et sévères [jour^-1] | |
this.R0 = R0; // taux de reproduction de base [1] | |
this.p = p; // proportion des infections ne nécessitant pas d'hospitalisation | |
this.teta = theta; // taux de létalité des infections hospitalisées | |
this.alpha = gamma2 * theta / (1-theta); // taux de mortalité des infections sévères | |
this.nu = nu; // taux de migration | |
this.b = b; // diminution de transmission par hospitalisation | |
this.c = c; // fraction du R0 diminuée par des politiques de santé publique | |
this.states = []; | |
this.seasonalForcing = seasonalForcing; | |
this.socialDistancingRules = socialDistancingRules; | |
console.log(socialDistancingRules); | |
this.states.push(new SystemState()); | |
} | |
recomputePropagationCoefficients() { | |
let current_time = this.states[this.states.length - 1].time; | |
// apply seasonal forcing | |
let R0 = this.R0; | |
if (this.seasonalForcing > 0.001) { | |
R0 = R0 * (1-this.seasonalForcing) + R0 * this.seasonalForcing*Math.cos(2 * Math.PI * (current_time+30)/365); | |
} | |
// apply social distancing rules | |
this.c = 0; | |
for (const rule in this.socialDistancingRules) { | |
if (this.socialDistancingRules[rule].includes(current_time)) { | |
this.c = Math.max(this.c, this.socialDistancingRules[rule].efficiency); | |
break; | |
} | |
} | |
this.beta = []; | |
for (let i = 0; i < 2; ++i) { | |
this.beta[i] = R0 * this.gamma[0] * this.sigma * | |
(this.alpha + this.gamma[1]) / ( | |
(this.gamma[0] + this.p*this.sigma) * (this.gamma[1] + this.alpha) + this.b*this.gamma[0]*this.sigma*(1-this.p) | |
) | |
} | |
} | |
evolve(dt) { | |
this.recomputePropagationCoefficients(); | |
let last_state = this.states[this.states.length - 1]; | |
let next_state = new SystemState(); | |
next_state.evolve(this, last_state, dt); | |
this.states.push(next_state); | |
} | |
run(days, iterations) { | |
let dt = days/iterations; | |
console.log(dt); | |
for (let i = 0; i < iterations; ++i) { | |
this.evolve(dt); | |
} | |
} | |
} | |
system = new System(seasonalForcing = 0.7, socialDistancingRules = [new SocialDistancingRule(50, 80, 0.9)]); | |
system.run(4*365, 4*2000); | |
stats = []; | |
for (let i = 0; i < system.states.length; ++i) { | |
let state = system.states[i]; | |
stats.push([state.time, state.S, state.E[0], state.E[1], state.A[0], state.A[1], state.I[0], state.I[1], state.R[0], state.R[1], , state.M].join(" ")); | |
} | |
const fs = require('fs'); | |
fs.writeFileSync("res.csv", stats.join("\n")); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment