예제 #1
0
    def __init__(self,
                 compartments,
                 initial_population_size=1,
                 correct_for_dynamical_population_size=False):
        """
        """
        MatrixEpiModel.__init__(self, compartments, initial_population_size,
                                correct_for_dynamical_population_size)

        self.t = sympy.symbols("t")
        if self.t in self.compartments:
            raise ValueError(
                "Don't use `t` as a compartment symbol, as it is reserved for time."
            )

        self.has_functional_rates = False

        self.birth_rates = sympy.zeros(self.N_comp, 1)
        self.linear_rates = sympy.zeros(self.N_comp, self.N_comp)
        self.quadratic_rates = [ sympy.zeros(self.N_comp, self.N_comp)\
                                 for c in range(self.N_comp) ]
        self.birth_events = sympy.zeros(self.N_comp, 1)
        self.linear_events = sympy.zeros(self.N_comp, self.N_comp)
        self.quadratic_events = [ sympy.zeros(self.N_comp, self.N_comp)\
                                 for c in range(self.N_comp) ]
        self.parameter_values = {}
    def test_fusion_and_adding_rates(self):

        A, B, C = list("ABC")

        epi = MatrixEpiModel(list("ABC"))

        # this should not raise a warning that rates do not sum to zero
        # as it will be actively suppressed
        epi.add_fusion_processes([
                (A, B, 1, C),
            ])

        with self.assertWarns(UserWarning):
            # this should raise a warning that rates do not sum to zero
            epi.add_quadratic_rates([
                    (A, B, C, -1),
                    (A, B, A, +1),
                ])
        # now rates should sum to zero
        epi.add_quadratic_rates([
                    (A, B, B, +1),
                    ])

        with self.assertWarns(UserWarning):
            # this should raise a warning that rates do not sum to zero
            epi.add_linear_rates([
                   (A, B, -1) 
                ])
    def test_quadratic_processes(self):

        epi = MatrixEpiModel(list("SEIR"))
        Q = [ np.zeros((4,4)) for C in epi.compartments ]
        Q[0][0,2] = -1
        Q[1][0,2] = +1
        epi.add_transmission_processes([
                ("S", "I",  1.0, "I", "E"),
                ])
        for iM, M in enumerate(epi.quadratic_rates):
            assert(np.all(M.toarray().flatten()==Q[iM].flatten()))
    def test_linear_rates(self):

        epi = MatrixEpiModel(list("SEIR"))
        epi.add_transition_processes([
                ("E", 1.0, "I"),
                ("I", 1.0, "R"),
                ])

        linear_rates = np.zeros((4,4))
        linear_rates[1,1] = -1
        linear_rates[2,1] = +1
        linear_rates[2,2] = -1
        linear_rates[3,2] = +1
        assert(np.all(epi.linear_rates.toarray().flatten()==linear_rates.flatten()))
    def test_initial_condition_warnings(self):

        A, B, C = list("ABC")

        epi = MatrixEpiModel(list("ABC"))

        with self.assertWarns(UserWarning):
            # this should raise a warning that rates do not sum to zero
            epi.set_initial_conditions({A:0.1,B:0.2})

        with self.assertWarns(UserWarning):
            # this should raise a warning that initial conditions were set twice
            epi.set_initial_conditions([(A,0.1),(A,0.2)])
    def test_birth_death(self):

        epi = MatrixEpiModel(list("SIR"))

        R0 = 2
        rho = 1
        mu = 0.2
        eta = R0 * rho

        with self.assertWarns(UserWarning):
            epi.set_processes([
                    ("S", "I", eta, "I", "I"),
                    ("I", rho, "R"),
                    (None, mu, "S"),
                    ("S", mu, None),
                    ("R", mu, None),
                    ("I", mu, None),
                ])
        epi.set_initial_conditions({'S': 0.8, 'I':0.2 })

        t = [0,1000]
        res = epi.integrate(t)
        assert(np.isclose(res['S'][-1],(mu+rho)/eta))
        assert(np.isclose(res['I'][-1],mu/eta*(eta-mu-rho)/(mu+rho)))
    def test_R0(self):
        """
        R0 computation test based on

        "The construction of next-generation matrices for compartmental epidemic models"
        by Diekmann, Heesterbeek, Roberts, J. R. Soc. Interface (2010) 7, 873–885
        doi.org/10.1098/rsif.2009.0386

        (Section 2.2)
        """

        b11 = 1
        b12 = 2
        b21 = 3
        b22 = 6

        #we'll use b11*b22 = b12*b21 because it makes 
        #our lives easier in computing R0 analytically

        mu = 4
        g1 = 5
        g2 = 7
        nu1 = 8
        nu2 = 9
        p = 0.2
        N = 100

        base_comps = list("SEIR")
        cats = [1,2]
        comps = []
        for C in base_comps:
            for c in cats:
                comps.append(C+str(c))

        model = MatrixEpiModel(comps,initial_population_size=N)
        transition_processes = [
                    ("S1", mu, None),
                    ("E1", mu, None),
                    ("I1", mu, None),
                    ("R1", mu, None),
                    ("S2", mu, None),
                    ("E2", mu, None),
                    ("I2", mu, None),
                    ("R2", mu, None),
                    ("E1", nu1, "I1"),
                    ("E2", nu2, "I2"),
                    ("I1", g1, "R1"),
                    ("I2", g2, "R2"),
                ]
        transmission_processes = [
                    ( "S1", "I1", b11, "E1", "I1"),
                    ( "S1", "I2", b12, "E1", "I2"),
                    ( "S2", "I1", b21, "E2", "I1"),
                    ( "S2", "I2", b22, "E2", "I2"),
                ]

        birth_processes =[
                (None, p*mu*N, "S1"),
                (None, (1-p)*mu*N, "S2"),
            ]

        model.set_processes(transition_processes + \
                            transmission_processes + \
                            birth_processes,
                            allow_nonzero_column_sums=True,
                            )
        model.set_initial_conditions({
                'S1': p*N,
                'S2': (1-p)*N,
            })

        R0 = model.get_next_generation_matrix_leading_eigenvalue()

        R0theory = p*b11*nu1/(nu1 + mu)/(g1+mu) + (1-p)*b22*nu2/(nu2+mu)/(g2+mu)

        assert(np.isclose(R0,R0theory))
 def test_compartments(self):
     epi = MatrixEpiModel(list("SEIR"))
     assert(all([ i == epi.get_compartment_id(C) for i, C in enumerate("SEIR") ]))
     assert(epi.get_compartment_id("E") == 1)
     assert(epi.get_compartment(1) == "E")