def setUp(self): self.test_outflow_data = pd.DataFrame({ 'compartment_duration': [1, 1, 2, 2.5, 10], 'total_population': [4, 2, 2, 4, 3], 'outflow_to': ['jail', 'prison', 'jail', 'prison', 'prison'], 'compartment': ['test'] * 5 }) self.historical_data = pd.DataFrame({ 2015: { 'jail': 2, 'prison': 2 }, 2016: { 'jail': 1, 'prison': 0 }, 2017: { 'jail': 1, 'prison': 1 } }) self.compartment_policies = [] self.test_transition_table = IncarceratedTransitions( self.test_outflow_data) self.test_transition_table.initialize_transition_table() self.test_transition_table.initialize(self.compartment_policies)
def initialize(self): """Initialize the transition tables, and then the compartments, for the SubSimulation""" # TODO(#4512): allow sparse data if not self.microsim and not self.total_population_data.empty: if self.user_inputs['start_time_step'] not in self.total_population_data.time_step.values: raise ValueError(f"Start time must be included in population data input\n" f"Expected: {self.user_inputs['start_time_step']}, " f"Actual: {self.total_population_data.time_step.values}") # Initialize a default transition class for each compartment to represent the no-policy scenario transitions_per_compartment = {} for compartment in self.simulation_architecture: transition_type = self.simulation_architecture[compartment] compartment_duration_data = self.transitions_data[self.transitions_data['compartment'] == compartment] if compartment_duration_data.empty: if transition_type is not None: raise ValueError(f"Transition data missing for compartment {compartment}. Data is required for all " "disaggregtion axes. Even the 'release' compartment needs transition data even if " "it's just outflow to 'release'") else: if transition_type == 'incarcerated': transition_class = IncarceratedTransitions(compartment_duration_data) elif transition_type == 'released': transition_class = ReleasedTransitions(compartment_duration_data) else: raise ValueError(f'unrecognized transition table type {transition_type}') transition_class.initialize_transition_table() transitions_per_compartment[compartment] = transition_class # Create a transition object for each compartment and year with policies applied and store shell policies shell_policies = dict() for compartment in self.simulation_architecture: # Select any policies that are applicable for this compartment compartment_policies = SparkPolicy.get_compartment_policies(self.policy_list, compartment) # add to the dict compartment -> transition class with policies applied if compartment in transitions_per_compartment: transitions_per_compartment[compartment].initialize(compartment_policies) # add shell policies to dict that gets passed to initialization else: shell_policies[compartment] = compartment_policies # Preprocess the historical data into separate pieces per compartment historical_outflows = self._load_data() # Initialize the compartment classes self._initialize_compartments(historical_outflows, transitions_per_compartment, shell_policies)
class TestShellCompartment(unittest.TestCase): """Test the ShellCompartment class runs correctly""" def setUp(self): self.test_outflow_data = pd.DataFrame({ 'compartment_duration': [1, 1, 2, 2.5, 10], 'total_population': [4, 2, 2, 4, 3], 'outflow_to': ['jail', 'prison', 'jail', 'prison', 'prison'], 'compartment': ['test'] * 5 }) self.historical_data = pd.DataFrame({ 2015: { 'jail': 2, 'prison': 2 }, 2016: { 'jail': 1, 'prison': 0 }, 2017: { 'jail': 1, 'prison': 1 } }) self.compartment_policies = [] self.test_transition_table = IncarceratedTransitions( self.test_outflow_data) self.test_transition_table.initialize_transition_table() self.test_transition_table.initialize(self.compartment_policies) def test_all_edges_fed_to(self): """ShellCompartments require edges to the compartments defined in the outflows_data""" starting_ts = 2015 policy_ts = 2018 test_shell_compartment = ShellCompartment(self.test_outflow_data, starting_ts=starting_ts, policy_ts=policy_ts, tag='test_shell', constant_admissions=True, policy_list=[]) test_full_compartment = FullCompartment(self.historical_data, self.test_transition_table, starting_ts=starting_ts, policy_ts=policy_ts, tag='test_compartment') with self.assertRaises(ValueError): test_shell_compartment.initialize_edges( [test_shell_compartment, test_full_compartment])
class TestFullCompartment(unittest.TestCase): """Test the FullCompartment runs correctly""" def setUp(self): self.test_supervision_data = pd.DataFrame({ 'compartment_duration': [1, 1, 2, 2.5, 10], 'total_population': [4, 2, 2, 4, 3], 'outflow_to': ['jail', 'prison', 'jail', 'prison', 'prison'], 'compartment': ['test'] * 5 }) self.test_incarceration_data = pd.DataFrame({ 'compartment_duration': [1, 1, 2, 2.5, 10], 'total_population': [4, 2, 2, 4, 3], 'outflow_to': ['supervision', 'release', 'supervision', 'release', 'release'], 'compartment': ['test'] * 5 }) self.compartment_policies = [] self.incarceration_transition_table = IncarceratedTransitions(self.test_incarceration_data) self.incarceration_transition_table.initialize_transition_table() self.incarceration_transition_table.initialize(self.compartment_policies) self.release_transition_table = ReleasedTransitions(self.test_supervision_data) self.release_transition_table.initialize_transition_table() self.release_transition_table.initialize(self.compartment_policies) self.historical_data = pd.DataFrame({ 2015: {'jail': 2, 'prison': 2}, 2016: {'jail': 1, 'prison': 0}, 2017: {'jail': 1, 'prison': 1} }) def test_step_forward_fails_without_initialized_edges(self): """Tests that step_forward() needs the initialize_edges() to have been run""" rel_compartment = FullCompartment(self.historical_data, self.release_transition_table, 2015, 2018, 'release') with self.assertRaises(ValueError): rel_compartment.step_forward() def test_all_edges_fed_to(self): """Tests that all edges in self.edges are included in self.transition_tables""" rel_compartment = FullCompartment(self.historical_data, self.release_transition_table, 2015, 2018, 'release') test_compartment = FullCompartment(self.historical_data, self.incarceration_transition_table, 2015, 2018, 'test_compartment') compartment_list = [rel_compartment, test_compartment] for compartment in compartment_list: compartment.initialize_edges(compartment_list) for compartment in compartment_list: compartment.step_forward()
def setUp(self): self.test_incarceration_data = pd.DataFrame({ 'compartment_duration': [1, 1, 2, 2.5, 10], 'total_population': [4, 2, 2, 4, 3], 'inflow_to': ['supervision', 'release', 'supervision', 'release', 'release'] }) self.compartment_policies = pd.DataFrame(columns=[ 'compartment', 'sub_population', 'retroactive_policies', 'non_retroactive_policies']) self.incarceration_transition_table = IncarceratedTransitions(['release']) self.incarceration_transition_table.initialize_transition_table(self.test_incarceration_data) self.incarceration_transition_table.initialize(self.compartment_policies) self.historical_data = pd.DataFrame({ 2015: {'jail': 2, 'prison': 2}, 2016: {'jail': 1, 'prison': 0}, 2017: {'jail': 1, 'prison': 1} })
def test_transition_table_rejects_impossible_large_probabilities(self): compartment_transitions = IncarceratedTransitions(self.test_data) compartment_transitions.initialize_transition_table() compartment_transitions.initialize(self.compartment_policies)