def cost(self, x): u = self.forward(x) diff = (self.obs - u) negative_log_likelihood = 0.5 * np.dot( np.dot(diff, self.Gamma_noise_inv), diff) controls = self.unflatten(x) penalty_controls = 0. * np.sum( np.mean(ewm( 1., np.power( np.abs(np.diff(controls[0], axis=0)) - np.diff(controls[0], axis=0), 1.)), axis=0)) penalty_controls += np.sum( np.mean(ewm(1., np.power(np.abs(np.diff(controls[0], axis=0)), 1.)), axis=0)) # # # penalization on HFR, beta, delta, kappa, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q from mean # result = 0. # for j in range(0, len(parameters)): # result = result + 0.5/500 * np.sum(np.power(np.divide(np.abs(controls[j+1] - parameters[j]), parameters[j]/2), 1)) # # penalty_controls += result print("cost, penalty = ", negative_log_likelihood, 10. * penalty_controls) return negative_log_likelihood + 10. * penalty_controls
def penalization(controls, coeffs, kappas): result = 0. # # penalization on alpha, q, tau from decreasing # increasing = [0.01, 1., 1.] # for i in range(1): # result = result + increasing[i]*np.sum(np.mean(ewm(coeffs[i][1:], np.power(np.abs(np.diff(controls[i], axis=0))-np.diff(controls[i], axis=0), 1.)), axis=0)) result = np.sum(np.mean(ewm(coeffs[0][1:], np.power(np.abs(np.diff(controls[0], axis=0))-np.diff(controls[0], axis=0), 1.)), axis=0)) # result = result + 1.*np.sum(np.mean(ewm(coeffs[3][1:], np.power(np.abs(np.diff(controls[3], axis=0))+np.diff(controls[3], axis=0), 1.)), axis=0)) # # # penalization on HFR, beta, delta, kappa, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q from mean # for j in range(2, len(parameters)): # result = result + 0.5/500 * np.sum(np.power(np.divide(controls[j+3] - parameters[j], parameters[j]/2), 2)) return result
# # data from China, https://science.sciencemag.org/content/sci/suppl/2020/03/13/science.abb3221.DC1/abb3221_Li_SM_rev.pdf # theta = 0.5 # # data from EU https://www.imperial.ac.uk/media/imperial-college/medicine/mrc-gida/2020-04-23-COVID19-Report-16.pdf # theta = 0.1 # a big range investigated from 0 - 1 # ratio of pre-isolation infectious period, only in action if quarantine is used # data from EU, https://www.imperial.ac.uk/media/imperial-college/medicine/mrc-gida/2020-04-23-COVID19-Report-16.pdf delta = 0.5 # #### initial seeding and simulation time step # proportion of each age and risk group population_proportion = 1. # # susceptible population in each age and risk group S = np.array([ewm(N_total, population_proportion)]) # exposed at the beginning E = np.array([100.]) # S, E, Q, A, I, H, R, D, Tc, Tu # Tc/Tu is the total reported/unreported positive cases zeros = np.zeros(1) # Tc = np.ones(1) * data_confirmed[0] y0 = np.array([S, E, zeros, zeros, zeros, zeros, zeros, zeros, zeros, zeros]).flatten("C") # # set data from solution to fitted death data # data = np.load("data/find_initial.npz") # solution_opt = data["solution_opt"] # today = data["today"] # y0 = solution_opt[today, :] # #### control variable for social distancing, isolution, and quarantine, in [0, 1], 0 means no control, 1 full control
def seir(self, y, t, parameters, controls, stochastic=False): # define the right hand side of the ode systems given state y, time t, parameters, and controls if self.number_group > 1: y = y.reshape((10, self.number_group)) S, E, Q, A, I, H, R, D, Tc, Tu = y q, tau, HFR, kappa, beta, delta, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q = parameters # _, _, _, delta, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q = parameters alpha, = controls alpha = (np.tanh(alpha) + 1) / 2 alpha = self.interpolation(t, self.t_control, alpha) # alpha, q, tau, HFR, kappa = [self.interpolation(t, self.t_control, controls[i]) for i in range(self.number_time_dependent_controls)] # tau_p = self.interpolation(t - np.max(1./sigma), self.t_control, controls[2]) # tau_p = self.interpolation(t, self.t_control, controls[2]) # tau_p = tau # IHR = np.divide(kappa, np.max(kappa) + tau_p) IHR = kappa QHR = ewm(tau, IHR) # gamma_A = gamma_I pi = self.proportion2factor(IHR, eta_I, gamma_I) nu = self.proportion2factor(HFR, mu, gamma_H) rho = self.proportion2factor(QHR, eta_Q, gamma_Q) contact = self.contact_rate(t) # theta_I = 2 - tau # theta_A = 1 - tau theta_I = 1. - 0 * tau theta_A = 1. - 0 * tau delta = 1. + 0 * delta C_E = ewm( 1 - alpha, ewm( 1 - q, ewm(delta, np.dot(contact, ewm(theta_I, np.divide(I, self.N_total))))) + np.dot(contact, ewm(theta_A, np.divide(A, self.N_total)))) C_Q = ewm( 1 - alpha, ewm( q, ewm(delta, np.dot(contact, ewm(theta_I, np.divide(I, self.N_total)))))) if stochastic: zeros = np.zeros(np.size(S)) S = np.max([zeros, S], axis=0) E = np.max([zeros, E], axis=0) Q = np.max([zeros, Q], axis=0) A = np.max([zeros, A], axis=0) I = np.max([zeros, I], axis=0) H = np.max([zeros, H], axis=0) P1 = ewm(beta, ewm(C_E, S)) P2 = ewm(beta, ewm(C_Q, S)) P3 = ewm(tau, ewm(sigma, E)) P4 = ewm(1 - tau, ewm(sigma, E)) P5 = ewm(rho, ewm(eta_Q, Q)) P6 = ewm(1 - rho, ewm(gamma_Q, Q)) P7 = ewm(gamma_A, A) P8 = ewm(pi, ewm(eta_I, I)) P9 = ewm(1 - pi, ewm(gamma_I, I)) P10 = ewm(nu, ewm(mu, H)) P11 = ewm(1 - nu, ewm(gamma_H, H)) if stochastic: P1 = np.random.poisson(P1) P2 = np.random.poisson(P2) P3 = np.random.poisson(P3) P4 = np.random.poisson(P4) P5 = np.random.poisson(P5) P6 = np.random.poisson(P6) P7 = np.random.poisson(P7) P8 = np.random.poisson(P8) P9 = np.random.poisson(P9) P10 = np.random.poisson(P10) P11 = np.random.poisson(P11) dS = -P1 - P2 dE = P1 - P3 - P4 dQ = P2 - P5 - P6 dA = P4 - P7 dI = P3 - P8 - P9 dH = P8 + P5 - P10 - P11 dR = P7 + P9 + P11 + P6 dD = P10 dTc = P3 + P2 # + quarantined, P2 dTu = P4 dydt = np.array([dS, dE, dQ, dA, dI, dH, dR, dD, dTc, dTu]).flatten("C") return dydt
def proportion2factor(self, proportion, r1, r2): # define a function to transform proportion to factor, e.g., from prop_EI to tau with r1=sigma_I, r2 = sigma_A factor = np.divide(ewm(r2, proportion), r1 + ewm(r2 - r1, proportion)) return factor
def reproduction(self, t, parameters, controls, solution): # effective reproduction number at time t # https://royalsocietypublishing.org/doi/pdf/10.1098/rsif.2009.0386 # The construction of next-generation matrices for compartmental epidemic models t_set = t number_time = len(t) if number_time == 1: t_set = [t] Rt = np.zeros(number_time) for n_t in range(number_time): t = t_set[n_t] q, tau, HFR, kappa, beta, delta, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q = parameters # alpha, q, tau, HFR, kappa, beta, delta, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q = controls # alpha, q, tau, HFR, kappa, beta, _, _, _, _, _, _, _, _, _ = controls alpha = self.interpolation(t, self.t_control, controls) # tau_p = self.interpolation(t - np.max(1./sigma), self.t_control, controls[2]) # tau_p = self.interpolation(t, self.t_control, controls[2]) # IHR = np.divide(kappa, np.max(kappa) + tau_p) IHR = kappa QHR = ewm(tau, IHR) pi = self.proportion2factor(IHR, eta_I, gamma_I) # transform the parameter in the vector format ones = np.ones(self.number_group) alpha, q, tau, pi, beta, delta, kappa, sigma, eta_I, eta_Q, mu, gamma_I, gamma_A, gamma_H, gamma_Q = \ ewm(alpha,ones), ewm(q,ones), ewm(tau,ones), ewm(pi,ones), ewm(beta,ones), ewm(delta,ones), ewm(kappa,ones), \ ewm(sigma,ones), ewm(eta_I,ones), ewm(eta_Q,ones), ewm(mu,ones), ewm(gamma_I,ones), ewm(gamma_A,ones), ewm(gamma_H,ones), ewm(gamma_Q,ones) # theta_I = 2 - tau # theta_A = 1 - tau theta_I = 1. - 0 * tau theta_A = 1. - 0 * tau delta = 1. + 0 * delta S = solution[n_t, :self.number_group] zeros = np.zeros((self.number_group, self.number_group)) ItoS = np.diag(beta) * np.diag(1.-alpha) * np.diag(1.-q) * np.diag(delta) * np.dot(self.contact_rate(t), np.diag(theta_I)) * np.diag(np.divide(S, self.N_total)) AtoS = np.diag(beta) * np.diag(1.-alpha) * np.dot(self.contact_rate(t), np.diag(theta_A)) * np.diag(np.divide(S, self.N_total)) T = np.block([ [zeros, AtoS, ItoS], [zeros, zeros, zeros], [zeros, zeros, zeros] ]) Sigma = np.block([ [-np.diag(sigma), zeros, zeros], [np.diag(1.-tau)*np.diag(sigma), -np.diag(gamma_A), zeros], [np.diag(tau)*np.diag(sigma), zeros, -np.diag(pi)*np.diag(eta_I)-np.diag(1.-pi)*np.diag(gamma_I)] ]) w, _ = np.linalg.eig(-np.dot(T, np.linalg.inv(Sigma))) Rt[n_t] = np.max(w) return Rt
# # data from China, https://science.sciencemag.org/content/sci/suppl/2020/03/13/science.abb3221.DC1/abb3221_Li_SM_rev.pdf # theta = 0.5 # # data from EU https://www.imperial.ac.uk/media/imperial-college/medicine/mrc-gida/2020-04-23-COVID19-Report-16.pdf # theta = 0.1 # a big range investigated from 0 - 1 # ratio of pre-isolation infectious period, only in action if quarantine is used # data from EU, https://www.imperial.ac.uk/media/imperial-college/medicine/mrc-gida/2020-04-23-COVID19-Report-16.pdf delta = 0.5 # #### initial seeding and simulation time step # proportion of each age and risk group population_proportion = 1. # # susceptible population in each age and risk group S = np.array([ewm(N_total, population_proportion)]) # exposed at the beginning E = np.array([100.]) # S, E, Q, A, I, H, R, D, Tc, Tu # Tc/Tu is the total reported/unreported positive cases zeros = np.zeros(1) # Tc = np.ones(1) * data_confirmed[0] y0 = np.array( [S, E, zeros, zeros, zeros, zeros, zeros, zeros, zeros, zeros]).flatten("C") # # set data from solution to fitted death data # data = np.load("data/find_initial.npz") # solution_opt = data["solution_opt"] # today = data["today"] # y0 = solution_opt[today, :]