File size: 5,315 Bytes
406ac25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import numpy as np
from scipy.special import gammaln


def lambda_time(lam, t, time):
    # This function computes the value of lambda.
    # INPUT:
    # - lam, t: arrays defining the (piecewise constant) function lambda(t);
    # - time: time instants at which we want to evaluate lambda.
    # OUTPUT:
    # - lambda_time: value of lambda.
    # NOTES: The function is vectorized in the array time. Indeed,
    # it allows to compute kappa for all the time instants in the array time.

    lambda_time = lam[np.searchsorted(t, time, side="right")]
    return lambda_time


def compute_kappa_time(s_t, i_t, lam, t, time, phi, P):
    # This function computes the value of kappa.
    # INPUT:
    # - s_t: number of susceptible individuals;
    # - i_t: number of infected individuals;
    # - lam, t: arrays defining the (piecewise constant) function lambda(t);
    # - time: time instants at which we want to evaluate kappa;
    # - phi: parameter phi of the model;
    # - P: total number of individuals.
    # OUTPUT:
    # - kappa_time: value of kappa.
    # NOTES: The function is vectorized in the arrays time, s_t and i_t.
    # Indeed, it allows to compute kappa for all the time instants in
    # the array time. It is required that time, s_t and i_t
    # have the same dimension.

    p_si_t = 1 - np.exp(-np.multiply(lambda_time(lam, t, time), i_t) / P)
    kappa_time = (1/phi - 1) * np.multiply(s_t, p_si_t)
    return kappa_time


def log_pi_lambda(lam, t, s, i, P, alpha, beta, phi):
    # This function computes the (log-) full-conditional
    # of the parameter vector lambda.
    # INPUT:
    # - lam: array of the values of lambda;
    # - t: array of the breakpoints;
    # - s: array of susceptible individuals during time;
    # - i: array of infected individuals during time;
    # - P: total number of individuals;
    # - alpha, beta: hyperparameters of the prior of lambda;
    # - phi: parameter phi of the model.
    # OUTPUT:
    # - result: (log-) full-conditional of lambda evaluated at lam.

    T = s.shape[0] - 1  # Index of the final time instant.
    time = np.arange(T + 1)  # Array of all time instants.

    # First, we initialize the result to -inf. If all the components of the
    # vector lam are positive (i.e., the vector is admissible) we compute the
    # (log-) full-conditional of lambda evaluated at lam and return the result.
    result = np.NINF
    if all(lam > 0):
        kappa_vec = compute_kappa_time(s[:-1], i[:-1], lam,
                                       t, time[:-1], phi, P)
        result = (np.sum(gammaln(-np.diff(s) + kappa_vec)
                         + kappa_vec * np.log(1 - phi)
                         - gammaln(kappa_vec))
                  + np.sum(np.log(np.power(lam, alpha-1))
                           - np.multiply(beta, lam)))
    return result


def log_pi_t(lam, t, s, i, P, phi):
    # This function computes the (log-) full-conditional
    # of the parameter vector t.
    # INPUT:
    # - lam: array of the values of lambda;
    # - t: array of the breakpoints;
    # - s: array of susceptible individuals during time;
    # - i: array of infected individuals during time;
    # - P: total number of individuals;
    # - phi parameter phi of the model.
    # OUTPUT:
    # - result: (log-) full-conditional of t evaluated at t.

    T = s.shape[0] - 1  # Index of the final time instant.
    time = np.arange(T + 1)  # Array of all time instants.

    # First, we initialize the result to -inf. If we have that
    # 0 < t_1 < t_2 < ... < t_(d-1) < T (i.e., the vector is admissible)
    # we compute the (log-) full-conditional of t evaluated at t
    # and return the result.
    result = np.NINF
    if np.all(np.diff(t) > 0) and t[0] > 0 and t[-1] < T:
        kappa_vec = compute_kappa_time(s[:-1], i[:-1], lam,
                                       t, time[:-1], phi, P)
        result = np.sum(gammaln(-np.diff(s) + kappa_vec)
                        + kappa_vec * np.log(1 - phi)
                        - gammaln(kappa_vec))
    return result


def simulate_data(T, lam, t, s_0, i_0, p_r, phi):
    # This function simulates data according to the process described above.
    # INPUT:
    # - T: index of the final time instant;
    # - lam, t: (true) arrays defining the function lambda(t);
    # - s_0: initial number of susceptible individuals;
    # - i_0: initial number of infected individuals;
    # - p_r: (true) probability of removal from infected population;
    # - phi: parameter phi of the model.
    # OUTPUT:
    # - s: array of susceptible individuals during time;
    # - i: array of infected individuals during time.

    # Compute the total number of individuals.
    P = s_0 + i_0

    # Initialize the arrays s and t.
    s = np.array([s_0])
    i = np.array([i_0])

    time = np.arange(T + 1)
    for t_i in time:
        # Draw a realization of delta_r.
        delta_r = np.random.binomial(i[-1], p_r)
        # Compute the kappa parameter at time t_i.
        kappa = compute_kappa_time(s[-1], i[-1], lam, t, t_i, phi, P)
        # Draw a realization of delta_i.
        delta_i = np.random.negative_binomial(kappa, 1 - phi)

        # Update s and i according to the model.
        s = np.append(s, s[-1] - delta_i)
        i = np.append(i, i[-1] + delta_i - delta_r)
    return s, i