def test_hard(self): # the SLIARD model is considered to be hard because a state can # go to multiple state. This is not as hard as the SEIHFR model # below. state_list = ['S', 'L', 'I', 'A', 'R', 'D'] param_list = [ 'beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon', 'N' ] ode_list = [ Transition('S', '- beta * S/N * ( I + delta * A)', 'ODE'), Transition('L', 'beta * S/N * (I + delta * A) - kappa * L', 'ODE'), Transition('I', 'p * kappa * L - alpha * I', 'ODE'), Transition('A', '(1-p) * kappa * L - epsilon * A', 'ODE'), Transition('R', 'f * alpha * I + epsilon * A', 'ODE'), Transition('D', '(1-f) * alpha * I', 'ODE') ] ode = SimulateOde(state_list, param_list, ode=ode_list) ode2 = ode.get_unrolled_obj() diffEqZero = map( lambda x: x == 0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def setUp(self): self.n_sim = 1000 # initial time self.t0 = 0 # the initial state, normalized to zero one self.x0 = [1, 1.27e-6, 0] # set the time sequence that we would like to observe self.t = np.linspace(0, 150, 100) # Standard. Find the solution. ode = common_models.SIR() ode.parameters = [0.5, 1.0 / 3.0] ode.initial_values = (self.x0, self.t0) self.solution = ode.integrate(self.t[1::], full_output=False) # now we need to define our ode explicitly state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # our stochastic version self.odeS = SimulateOde(state_list, param_list, transition=transition_list)
def setUp(self): n_size = 50 self.n_sim = 3 # x0 = [1,1.27e-6,0] # original self.x0 = [2362206.0, 3.0, 0.0] self.t = np.linspace(0, 250, n_size) # use a shorter version if we just want to test # whether setting the seed is applicable self.t_seed = np.linspace(0, 10, 10) self.index = np.random.randint(n_size) state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma', 'N'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # initialize the model self.odeS = SimulateOde(state_list, param_list, transition=transition_list) self.odeS.parameters = [0.5, 1.0 / 3.0, self.x0[0]] self.odeS.initial_values = (self.x0, self.t[0])
def test_adding_parameters(self): ''' Test adding parameters to a model ''' expected_result = [ ODEVariable('beta', 'beta', None, True), ODEVariable('gamma', 'gamma', None, True), ODEVariable('mu', 'mu', None, True), ODEVariable('B', 'B', None, True) ] # Model parts stateList = ['S', 'I', 'R'] paramList = ['beta', 'gamma'] # build the basic model t1 = Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T) t2 = Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) modelTrans = SimulateOde(stateList, paramList, transition=[t1, t2]) # add to the parameters modelTrans.param_list = paramList + ['mu', 'B'] self.assertListEqual( modelTrans.param_list, expected_result, 'Adding parameters does not give expected ' 'parameter list')
def test_stochastic(self): ode = SimulateOde(self.states, self.params, birth_death=self.birth_deaths, transition=self.transitions) ode.parameters = self.param_eval ode.initial_values = (self.x0, self.t[0]) _simX, _simT = ode.simulate_jump(self.t, 5, parallel=False, full_output=True)
def test_simple(self): ode1 = Transition('S', '-beta*S*I', 'ode') ode2 = Transition('I', 'beta*S*I - gamma * I', 'ode') ode3 = Transition('R', 'gamma*I', 'ode') state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma'] ode = SimulateOde(state_list, param_list, ode=[ode1, ode2, ode3]) ode2 = ode.get_unrolled_obj() diffEqZero = map(lambda x: x==0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def test_simple(self): ode1 = Transition('S', '-beta*S*I', 'ode') ode2 = Transition('I', 'beta*S*I - gamma * I', 'ode') ode3 = Transition('R', 'gamma*I', 'ode') state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma'] ode = SimulateOde(state_list, param_list, ode=[ode1, ode2, ode3]) ode2 = ode.get_unrolled_obj() diffEqZero = map( lambda x: x == 0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def setUp(self): n_size = 50 self.n_sim = 3 # x0 = [1,1.27e-6,0] # original self.x0 = [2362206.0, 3.0, 0.0] self.t = np.linspace(0, 250, n_size) # use a shorter version if we just want to test # whether setting the seed is applicable self.t_seed = np.linspace(0, 10, 10) self.index = np.random.randint(n_size) state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma', 'N'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # initialize the model self.odeS = SimulateOde(state_list, param_list, transition=transition_list) self.odeS.parameters = [0.5, 1.0/3.0, self.x0[0]] self.odeS.initial_values = (self.x0, self.t[0])
def test_derived_param(self): # the derived parameters are treated separately when compared to the # normal parameters and the odes ode = common_models.Legrand_Ebola_SEIHFR() ode_list = [ Transition('S', '-(beta_I*S*I + beta_H_Time*S*H + beta_F_Time*S*F)'), Transition( 'E', '(beta_I*S*I + beta_H_Time*S*H + beta_F_Time*S*F) - alpha*E'), Transition( 'I', '-gamma_I*(1 - theta_1)*(1 - delta_1)*I - gamma_D*(1 - theta_1)*delta_1*I - gamma_H*theta_1*I + alpha*E' ), Transition( 'H', 'gamma_H*theta_1*I - gamma_DH*delta_2*H - gamma_IH*(1 - delta_2)*H' ), Transition( 'F', '- gamma_F*F + gamma_DH*delta_2*H + gamma_D*(1 - theta_1)*delta_1*I' ), Transition( 'R', 'gamma_I*(1 - theta_1)*(1 - delta_1)*I + gamma_F*F + gamma_IH*(1 - delta_2)*H' ), Transition('tau', '1') ] ode1 = SimulateOde(ode.state_list, ode.param_list, ode._derivedParamEqn, ode=ode_list) ode2 = ode1.get_unrolled_obj() diffEqZero = map( lambda x: x == 0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def test_derived_param(self): # the derived parameters are treated separately when compared to the # normal parameters and the odes ode = common_models.Legrand_Ebola_SEIHFR() ode_list = [ Transition('S', '-(beta_I*S*I + beta_H_Time*S*H + beta_F_Time*S*F)'), Transition('E', '(beta_I*S*I + beta_H_Time*S*H + beta_F_Time*S*F) - alpha*E'), Transition('I', '-gamma_I*(1 - theta_1)*(1 - delta_1)*I - gamma_D*(1 - theta_1)*delta_1*I - gamma_H*theta_1*I + alpha*E'), Transition('H', 'gamma_H*theta_1*I - gamma_DH*delta_2*H - gamma_IH*(1 - delta_2)*H'), Transition('F', '- gamma_F*F + gamma_DH*delta_2*H + gamma_D*(1 - theta_1)*delta_1*I'), Transition('R', 'gamma_I*(1 - theta_1)*(1 - delta_1)*I + gamma_F*F + gamma_IH*(1 - delta_2)*H'), Transition('tau', '1') ] ode1 = SimulateOde(ode.state_list, ode.param_list, ode._derivedParamEqn, ode=ode_list) ode2 = ode1.get_unrolled_obj() diffEqZero = map(lambda x: x==0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def test_hard(self): # the SLIARD model is considered to be hard because a state can # go to multiple state. This is not as hard as the SEIHFR model # below. state_list = ['S', 'L', 'I', 'A', 'R', 'D'] param_list = ['beta', 'p', 'kappa', 'alpha', 'f', 'delta', 'epsilon', 'N'] ode_list = [ Transition('S', '- beta * S/N * ( I + delta * A)', 'ODE'), Transition('L', 'beta * S/N * (I + delta * A) - kappa * L', 'ODE'), Transition('I', 'p * kappa * L - alpha * I', 'ODE'), Transition('A', '(1-p) * kappa * L - epsilon * A', 'ODE'), Transition('R', 'f * alpha * I + epsilon * A', 'ODE'), Transition('D', '(1-f) * alpha * I', 'ODE') ] ode = SimulateOde(state_list, param_list, ode=ode_list) ode2 = ode.get_unrolled_obj() diffEqZero = map(lambda x: x==0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def test_bd(self): state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma', 'B', 'mu'] ode_list = [ Transition(origin='S', equation='-beta * S * I + B - mu * S', transition_type=TransitionType.ODE), Transition(origin='I', equation='beta * S * I - gamma * I - mu * I', transition_type=TransitionType.ODE), Transition(origin='R', destination='R', equation='gamma * I', transition_type=TransitionType.ODE) ] ode = SimulateOde(state_list, param_list, ode=ode_list) ode2 = ode.get_unrolled_obj() diffEqZero = map(lambda x: x==0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
def test_bd(self): state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma', 'B', 'mu'] ode_list = [ Transition(origin='S', equation='-beta * S * I + B - mu * S', transition_type=TransitionType.ODE), Transition(origin='I', equation='beta * S * I - gamma * I - mu * I', transition_type=TransitionType.ODE), Transition(origin='R', destination='R', equation='gamma * I', transition_type=TransitionType.ODE) ] ode = SimulateOde(state_list, param_list, ode=ode_list) ode2 = ode.get_unrolled_obj() diffEqZero = map( lambda x: x == 0, sympy.simplify(ode.get_ode_eqn() - ode2.get_ode_eqn())) self.assertTrue(numpy.all(numpy.array(list(diffEqZero))))
params = ['beta', 'gamma', 'N'] transitions = [Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T)] # initial conditions N = 7781984.0 in_inf = round(0.0000001*N) init_state = [N - in_inf, in_inf, 0.0] # # # time max_t = 9 # 50 t = np.linspace (0 , max_t , 101) # # # deterministic parameter values param_evals = [('beta', 3.6), ('gamma', 0.2), ('N', N)] # construct model model_j = SimulateOde(states, params, transition=transitions) model_j.parameters = param_evals model_j.initial_values = (init_state, t[0]) # run 10 simulations start = time.time() simX, simT = model_j.simulate_jump(t[1::], iteration=10, full_output=True) end = time.time() logging.info('Simulation took {} seconds'.format(end - start))
class TestSimulateParam(TestCase): def setUp(self): self.n_sim = 1000 # initial time self.t0 = 0 # the initial state, normalized to zero one self.x0 = [1, 1.27e-6, 0] # set the time sequence that we would like to observe self.t = np.linspace(0, 150, 100) # Standard. Find the solution. ode = common_models.SIR() ode.parameters = [0.5, 1.0 / 3.0] ode.initial_values = (self.x0, self.t0) self.solution = ode.integrate(self.t[1::], full_output=False) # now we need to define our ode explicitly state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # our stochastic version self.odeS = SimulateOde(state_list, param_list, transition=transition_list) def tearDown(self): self.solution = None self.odeS = None def test_simulate_param_1(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution. In this case, a scipy.distn object. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = scipy.stats.gamma(100.0, 0.0, 1.0 / 200.0) d['gamma'] = scipy.stats.gamma(100.0, 0.0, 1.0 / 300.0) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions sim = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False) solution_diff = sim - self.solution # test :) self.assertTrue(np.any(abs(solution_diff) <= 0.2)) def test_simulate_param_2(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution. In this case, a function handle which has the same name as those found in R. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = (rgamma, {'shape': 100.0, 'rate': 200.0}) d['gamma'] = (rgamma, (100.0, 300.0)) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions sim = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False) solution_diff = sim - self.solution # test :) self.assertTrue(np.all(abs(solution_diff) <= 0.2)) def test_simulate_param_same_seed(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution and simulating using the same seed should produce the same result. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = scipy.stats.gamma(100.0, 0.0, 1.0 / 200.0) d['gamma'] = scipy.stats.gamma(100.0, 0.0, 1.0 / 300.0) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions seed = np.random.randint(1000) np.random.seed(seed) solution1, Yall1 = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False, full_output=True) np.random.seed(seed) solution2, Yall2 = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False, full_output=True) self.assertTrue(np.allclose(solution1, solution2)) for i, yi in enumerate(Yall1): self.assertTrue(np.allclose(Yall2[i], yi)) def test_simulate_param_different_seed(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution and simulating using different seeds should produce different results. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = scipy.stats.gamma(100.0, 0.0, 1.0 / 200.0) d['gamma'] = scipy.stats.gamma(100.0, 0.0, 1.0 / 300.0) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions np.random.seed(1) solution1, Yall1 = self.odeS.simulate_param(self.t[1::], 1000, parallel=False, full_output=True) np.random.seed(2) solution2, Yall2 = self.odeS.simulate_param(self.t[1::], 1000, parallel=False, full_output=True) self.assertFalse(np.allclose(solution1, solution2)) for i, yi in enumerate(Yall1): self.assertFalse(np.allclose(Yall2, yi))
class TestSimulateParam(TestCase): def setUp(self): self.n_sim = 1000 # initial time self.t0 = 0 # the initial state, normalized to zero one self.x0 = [1, 1.27e-6, 0] # set the time sequence that we would like to observe self.t = np.linspace(0, 150, 100) # Standard. Find the solution. ode = common_models.SIR() ode.parameters = [0.5, 1.0 / 3.0] ode.initial_values = (self.x0, self.t0) self.solution = ode.integrate(self.t[1::], full_output=False) # now we need to define our ode explicitly state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # our stochastic version self.odeS = SimulateOde(state_list, param_list, transition=transition_list) def tearDown(self): self.solution = None self.odeS = None def test_simulate_param_1(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution. In this case, a scipy.distn object. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = scipy.stats.gamma(100.0, 0.0, 1.0/200.0) d['gamma'] = scipy.stats.gamma(100.0, 0.0, 1.0/300.0) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions sim = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False) solution_diff = sim - self.solution # test :) self.assertTrue(np.any(abs(solution_diff) <= 0.2)) def test_simulate_param_2(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution. In this case, a function handle which has the same name as those found in R. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = (rgamma, {'shape': 100.0, 'rate': 200.0}) d['gamma'] = (rgamma, (100.0, 300.0)) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions sim = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False) solution_diff = sim - self.solution # test :) self.assertTrue(np.all(abs(solution_diff) <= 0.2)) def test_simulate_param_same_seed(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution and simulating using the same seed should produce the same result. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = scipy.stats.gamma(100.0, 0.0, 1.0/200.0) d['gamma'] = scipy.stats.gamma(100.0, 0.0, 1.0/300.0) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions seed = np.random.randint(1000) np.random.seed(seed) solution1, Yall1 = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False, full_output=True) np.random.seed(seed) solution2, Yall2 = self.odeS.simulate_param(self.t[1::], self.n_sim, parallel=False, full_output=True) self.assertTrue(np.allclose(solution1, solution2)) for i, yi in enumerate(Yall1): self.assertTrue(np.allclose(Yall2[i], yi)) def test_simulate_param_different_seed(self): """ Stochastic ode under the interpretation that the parameters follow some sort of distribution and simulating using different seeds should produce different results. """ # define our parameters in terms of two gamma distributions # where the expected values are the same as before [0.5,1.0/3.0] d = dict() d['beta'] = scipy.stats.gamma(100.0, 0.0, 1.0/200.0) d['gamma'] = scipy.stats.gamma(100.0, 0.0, 1.0/300.0) self.odeS.parameters = d self.odeS.initial_values = (self.x0, self.t0) # now we generate the solutions np.random.seed(1) solution1, Yall1 = self.odeS.simulate_param(self.t[1::], 1000, parallel=False, full_output=True) np.random.seed(2) solution2, Yall2 = self.odeS.simulate_param(self.t[1::], 1000, parallel=False, full_output=True) self.assertFalse(np.allclose(solution1, solution2)) for i, yi in enumerate(Yall1): self.assertFalse(np.allclose(Yall2, yi))
class TestSimulateJump(TestCase): def setUp(self): n_size = 50 self.n_sim = 3 # x0 = [1,1.27e-6,0] # original self.x0 = [2362206.0, 3.0, 0.0] self.t = np.linspace(0, 250, n_size) # use a shorter version if we just want to test # whether setting the seed is applicable self.t_seed = np.linspace(0, 10, 10) self.index = np.random.randint(n_size) state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma', 'N'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # initialize the model self.odeS = SimulateOde(state_list, param_list, transition=transition_list) self.odeS.parameters = [0.5, 1.0 / 3.0, self.x0[0]] self.odeS.initial_values = (self.x0, self.t[0]) def tearDown(self): self.odeS = None def test_simulate_jump_serial(self): """ Stochastic ode under the interpretation that we have a continuous time Markov chain as the underlying process """ solution = self.odeS.integrate(self.t[1::]) # random evaluation to see if the functions break down self.odeS.transition_mean(self.x0, self.t[0]) self.odeS.transition_var(self.x0, self.t[0]) self.odeS.transition_mean(solution[self.index, :], self.t[self.index]) self.odeS.transition_var(solution[self.index, :], self.t[self.index]) _simX, _simT = self.odeS.simulate_jump(250, self.n_sim, parallel=False, full_output=True) def test_simulate_jump_same_seed(self): """ Testing that using the same seed produces the same simulation under a CTMC interpretation only under a serial simulation. When simulating with a parallel backend, the result will be different as the seed does not propagate through. """ seed = np.random.randint(1000) # First note that the default is a parallel simulation using # dask as the backend. This does not use the seed. # But if we run it in serial then the seed will be used # and the output will be identical np.random.seed(seed) simX1, simT1 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) np.random.seed(seed) simX2, simT2 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) for i, xi in enumerate(simX1): self.assertTrue(np.allclose(simX2[i], xi)) def test_simulate_jump_different_seed(self): """ Testing that using a different seed produces different simulations under a CTMC interpretation regardless of the backend. """ np.random.seed(1) simX1, simT1 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) np.random.seed(2) simX2, simT2 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) for i, xi in enumerate(simX1): self.assertFalse(np.allclose(simX2[i], xi))
class TestSimulateJump(TestCase): def setUp(self): n_size = 50 self.n_sim = 3 # x0 = [1,1.27e-6,0] # original self.x0 = [2362206.0, 3.0, 0.0] self.t = np.linspace(0, 250, n_size) # use a shorter version if we just want to test # whether setting the seed is applicable self.t_seed = np.linspace(0, 10, 10) self.index = np.random.randint(n_size) state_list = ['S', 'I', 'R'] param_list = ['beta', 'gamma', 'N'] transition_list = [ Transition(origin='S', destination='I', equation='beta*S*I/N', transition_type=TransitionType.T), Transition(origin='I', destination='R', equation='gamma*I', transition_type=TransitionType.T) ] # initialize the model self.odeS = SimulateOde(state_list, param_list, transition=transition_list) self.odeS.parameters = [0.5, 1.0/3.0, self.x0[0]] self.odeS.initial_values = (self.x0, self.t[0]) def tearDown(self): self.odeS = None def test_simulate_jump_serial(self): """ Stochastic ode under the interpretation that we have a continuous time Markov chain as the underlying process """ solution = self.odeS.integrate(self.t[1::]) # random evaluation to see if the functions break down self.odeS.transition_mean(self.x0, self.t[0]) self.odeS.transition_var(self.x0, self.t[0]) self.odeS.transition_mean(solution[self.index,:], self.t[self.index]) self.odeS.transition_var(solution[self.index,:], self.t[self.index]) _simX, _simT = self.odeS.simulate_jump(250, self.n_sim, parallel=False, full_output=True) def test_simulate_jump_same_seed(self): """ Testing that using the same seed produces the same simulation under a CTMC interpretation only under a serial simulation. When simulating with a parallel backend, the result will be different as the seed does not propagate through. """ seed = np.random.randint(1000) # First note that the default is a parallel simulation using # dask as the backend. This does not use the seed. # But if we run it in serial then the seed will be used # and the output will be identical np.random.seed(seed) simX1, simT1 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) np.random.seed(seed) simX2, simT2 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) for i, xi in enumerate(simX1): self.assertTrue(np.allclose(simX2[i], xi)) def test_simulate_jump_different_seed(self): """ Testing that using a different seed produces different simulations under a CTMC interpretation regardless of the backend. """ np.random.seed(1) simX1, simT1 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) np.random.seed(2) simX2, simT2 = self.odeS.simulate_jump(self.t_seed[1::], self.n_sim, parallel=False, full_output=True) for i, xi in enumerate(simX1): self.assertFalse(np.allclose(simX2[i], xi))