def test_t_span_input(self): """Ensure correct error handling for invalid t_span inputs""" with self.assertRaises(ValueError): # t_span is 2D list(se.solve_gillespie(self.m, self.initial, t_span=[0])) # convert generator to list to force function to be evaluated# with self.assertRaises(ValueError): # t_span must have range list(se.solve_gillespie(self.m, self.initial, t_span=[0, 0])) with self.assertRaises(ValueError): # t_stop > t_start list(se.solve_gillespie(self.m, self.initial, t_span=[-2, 0])) with self.assertRaises(TypeError): # time values must be floats list(se.solve_gillespie(self.m, self.initial, t_span=[0, 'ten']))
def test_neg_propensity(self): """Test error handling of negative elements in propensity matrix""" m_neg = MagicMock() m_neg.return_value = np.array([[0, -1], [0, 0]]) solve = se.solve_gillespie(m_neg, self.initial, self.t_span) with self.assertRaises(ValueError): next(solve)
def test_gillespie_zeros(self, initial): """Ensure that zero propensity gives unchanged state for any initial""" m_zeros = MagicMock() m_zeros.return_value = np.array([[0, 0], [0, 0]]) solution = list(se.solve_gillespie(m_zeros, initial, [0, 10])) final_sol = solution[-1][1:] # take only compartment nums at end self.assertEqual(final_sol.tolist(), initial.tolist(), 'Unexpected output - changed state')
def test_propensity_call(self): m_count = MagicMock() m_count.return_value = np.array([[0, 1], [0, 0]]) solve = se.solve_gillespie(m_count, self.initial, self.t_span) next(solve) # return a yield self.assertEqual(m_count.call_count, 1, 'Propensity Func called unexpected number of times') next(solve) # return a yield self.assertEqual(m_count.call_count, 2, 'Propensity Func called unexpected number of times')
def test_population_conservation(self, initial, propensity_mat): """Ensure population is conserved for any initial and prop matrix""" m_3dim = MagicMock() m_3dim.return_value = propensity_mat initial_pop = np.sum(initial) solve = se.solve_gillespie(m_3dim, initial, [0, 1]) while True: try: output = next(solve) except StopIteration: break self.assertEqual(output.shape, (len(initial) + 1, ), 'Unexpected number of output compartments') self.assertAlmostEqual(np.sum(output[1:]), initial_pop, 'Unexpected output - pop. not conserved')
def test_gillespie_output(self): def prop_func(x: np.ndarray): return np.array([[0, x[1]], [0, 0]]) state = self.initial solve = se.solve_gillespie(prop_func, state, [0, 100]) while True: try: output = next(solve) except StopIteration: break state = output[1:] self.assertTrue(np.all(state >= 0), 'Returned negative values in state array') self.assertEqual(state.tolist(), [0, 10], 'Unexpected output - incomplete infection')
def test_intial_input(self): with self.assertRaises(ValueError): # initial conditions must be +ve list(se.solve_gillespie(self.m, np.array([-10, 0]), self.t_span))
def test_tspan_ordering(self, start, stop): test_span = [start, stop] if stop <= start: with self.assertRaises(ValueError): list(se.solve_gillespie(self.m, self.initial, test_span))