def run_social_circles_trial( args: Tuple[Dict[networkgen.Agent, int], Tuple[int, int], Disease, Any] ) -> Optional[Tuple[float, float, float]]: agent_to_quantity, grid_dims, disease, rand = args sim_len = 200 sims_per_trial = 150 target_communities = 25 sc_results = networkgen.make_social_circles_network(agent_to_quantity, grid_dims, rand=rand) if sc_results is None: return None net, _, = sc_results if nx.number_connected_components(net.G) > target_communities: return None to_flicker = partitioning.fluidc_partition(net.G, target_communities) proportion_flickering = len(to_flicker) / net.E social_good_score = rate_social_good(net) network_behavior = StaticFlickerBehavior(net.M, to_flicker, (True, False), "Probs don't change this") avg_sus = np.mean([ np.sum( simulate(net.M, make_starting_sir(net.N, 1), disease, network_behavior, sim_len, None, rand)[-1][0] > 0) for _ in range(sims_per_trial) ]) / net.N return proportion_flickering, avg_sus, social_good_score
def run_inf_prob_vs_perc_sus(name: str, diseases: Sequence[Disease], new_network: Callable[[], Network], flicker_config: RandomFlickerConfig, num_trials: int, rng): """ Save the plot and csv of infection probability vs percent susceptible. """ results: Dict[float, List[float]] = defaultdict(lambda: []) print(f'Running {name}') pbar = tqdm(total=num_trials * len(diseases)) for disease, _ in it.product(diseases, range(num_trials)): net = new_network() flicker = flicker_config.make_behavior(net.M, net.intercommunity_edges) sir0 = make_starting_sir(net.N, 1, rng) perc_sus = np.sum( simulate(net.M, sir0, disease, flicker, 100, None, rng)[-1][0] > 0 ) / net.N results[disease.trans_prob].append(perc_sus) pbar.update() x_coords = tuple(results.keys()) collected_data = np.array([list(values) for values in results.values()]) quartiles = np.quantile(collected_data, (.25, .75), axis=1, interpolation='midpoint') y_coords = np.mean(collected_data, axis=1) plt.figure() plt.title(name) plt.xlim(0, 1) plt.ylim(0, 1) plt.xlabel('Infection Probability') plt.ylabel('Survival Percentage') plt.plot(x_coords, y_coords) plt.fill_between(x_coords, quartiles[0], quartiles[1], alpha=.4) plt.savefig(f'results/{name}.png', format='png', dpi=200)
def run_agent_generated_trial(args: Tuple[Disease, AgentBehavior, int, Any])\ -> Optional[Tuple[float, float, float]]: """ args: (disease to use in the simulation, the behavior agents have when generating the network, the number of agents in the network, an instance of np.random.default_rng) """ disease, agent_behavior, N, rand = args sim_len = 200 sims_per_trial = 150 net = make_agent_generated_network(N, agent_behavior) if net is None: return None to_flicker = partitioning.fluidc_partition(net.G, 50) proportion_flickering = len(to_flicker) / net.E social_good = rate_social_good(net) network_behavior = StaticFlickerBehavior(net.M, to_flicker, (True, False), "Probs don't change this") avg_sus = np.mean([ np.sum( simulate(net.M, make_starting_sir(net.N, 1), disease, network_behavior, sim_len, None, rand)[-1][0] > 0) for _ in range(sims_per_trial) ]) / net.N return proportion_flickering, avg_sus, social_good
def run_connected_community_trial(args: Tuple[ConnectedCommunityConfiguration, Disease, Any])\ -> Optional[Tuple[float, float, float]]: """ args: (ConnectedCommunityConfiguration to use, disease to use, default_rng instance) return: (proportion of edges that flicker, the average number of remaining susceptible agents) or None on failure. """ sim_len = 200 sims_per_trial = 150 configuration, disease, rand = args inner_degrees = configuration.make_inner_degrees() outer_degrees = configuration.make_outer_degrees() net = networkgen.make_connected_community_network(inner_degrees, outer_degrees, rand) # If a network couldn't be successfully generated, return None to signal the failure if net is None: return None to_flicker = {(u, v) for u, v in net.edges if net.communities[u] != net.communities[v]} proportion_flickering = len(to_flicker) / net.E social_good = rate_social_good(net) behavior = StaticFlickerBehavior(net.M, to_flicker, (True, False), "Probs don't change this") avg_sus = np.mean([np.sum(simulate(net.M, make_starting_sir(net.N, 1), disease, behavior, sim_len, None, rand)[-1][0] > 0) for _ in range(sims_per_trial)]) / net.N return proportion_flickering, avg_sus, social_good
def experiment(make_network, seed): """ return: list of (high_reach_survival_rate, high_reach_sim_time, low_reach_survival_rate, low_reach_sim_time) """ rng = np.random.default_rng(seed) hr_net = make_network(high_reach) lr_net = make_network(low_reach) sir0 = make_starting_sir(hr_net.N, 1, rng) hr_sirs = simulate(hr_net.M, sir0, disease, make_behavior(high_reach, make_network, rng), sim_len_cap, rng, None) lr_sirs = simulate(lr_net.M, sir0, disease, make_behavior(low_reach, make_network, rng), sim_len_cap, rng, None) return (calc_survival_rate(hr_sirs), len(hr_sirs), calc_survival_rate(lr_sirs), len(lr_sirs))
def cc_pressure_vs_none_entry_point(): rng = np.random.default_rng(0xbeefee) num_trials = 1000 disease = Disease(4, .4) inner_bounds = 1, 15 outer_bounds = 1, 5 community_size = 20 n_communities = 25 make_ccn = MakeConnectedCommunity(community_size, inner_bounds, n_communities, outer_bounds, rng) pressure_configurations = [ SimplePressureConfig(radius, prob, rng) for radius, prob in it.product((1, 2, 3), (.25, .5, .75)) ] # pressure_experiment(make_ccn, pressure_configurations, disease, num_trials, rng) net = make_ccn() simulate(net.M, make_starting_sir(net.N, 1, rng), disease, pressure_configurations[1].make_behavior(net), 100, nx.spring_layout(net.G))
def __call__(self, encoding: np.ndarray) -> float: net = self._enc_to_G(encoding) M = net.M to_flicker = fluidc_partition(net.G, net.N//20) flicker_behavior = StaticFlickerBehavior(M, to_flicker, (True, False), '') avg_sus = np.mean([np.sum(simulate(M, make_starting_sir(len(M), 1), self._disease, flicker_behavior, self._sim_len, None, self._rand)[-1][0] > 0) for _ in range(self._n_sims)]) / len(M) cost = 2-avg_sus-rate_social_good(net, self._decay_func) return cost
def main(): n_trials = 100 max_steps = 100 rng = np.random.default_rng(0) disease = Disease(4, .2) names = ('elitist-500', 'cavemen-50-10', 'spatial-network', 'cgg-500', 'watts-strogatz-500-4-.1') paths = fio.network_names_to_paths(names) behavior_configs = (RandomFlickerConfig(.5, 'Random .5', rng), StaticFlickerConfig((True, False), 'Static .5')) for net_name, path in zip(names, paths): net = fio.read_network(path) to_flicker = tuple((u, v) for u, v in net.edges if net.communities[u] != net.communities[v]) proportion_flickering = len(to_flicker) / net.E social_good = rate_social_good(net) trial_to_pf = tuple(proportion_flickering for _ in range(n_trials)) trial_to_sg = tuple(social_good for _ in range(n_trials)) print(f'Running simulations for {net_name}.') for config in behavior_configs: behavior = config.make_behavior(net.M, to_flicker) sim_results = [ get_final_stats( simulate(net.M, make_starting_sir(net.N, 1, rng), disease, behavior, max_steps, None, rng=rng)) for _ in tqdm(range(n_trials)) ] results = BasicExperimentResult(f'{net_name} {config.name}', sim_results, trial_to_pf, trial_to_sg) results.save_csv(RESULTS_DIR) results.save_box_plots(RESULTS_DIR) results.save_perc_sus_vs_social_good(RESULTS_DIR)
def run_experiments(args: Tuple[str, int, int, Disease, Sequence[FlickerConfig], str])\ -> Optional[FlickerComparisonResult]: """ Run a batch of experiments and return a tuple containing the network's name, number of flickering edges, and a mapping of behavior name to the final amount of susceptible nodes. Return None on failure. args: (path to the network, number of sims to run for each behavior, simulation length, disease, a sequence of configs for the flickers to use, the name of the baseline flicker to compare the other results to) """ network_path, num_sims, sim_len, disease, flicker_configs, baseline_flicker_name = args net = fio.read_network(network_path) intercommunity_edges = {(u, v) for u, v in net.edges if net.communities[u] != net.communities[v]} behavior_to_results: Dict[str, Sequence[float]] = {} for config in flicker_configs: behavior = config.make_behavior(net.M, intercommunity_edges) # The tuple comprehension is pretty arcane, so here is an explanation. # Each entry is the sum of the number of entries in the final SIR where # the days in S are greater than 0. That is to say, the number of # susceptible agents at the end of the simulation. perc_sus = tuple( np.sum( simulate(net.M, make_starting_sir(net.N, 1), disease, behavior, sim_len, None)[-1][0] > 0) / net.N for _ in range(num_sims)) behavior_to_results[behavior.name] = perc_sus return FlickerComparisonResult(fio.get_network_name(network_path), num_sims, sim_len, len(intercommunity_edges) / net.E, behavior_to_results, baseline_flicker_name)
def pressure_test_entry_point(): rng = np.random.default_rng() net = fio.read_network('networks/cavemen-50-10.txt') simulate(net.M, make_starting_sir(net.N, (0, ), rng), Disease(4, 0.3), SimplePressureBehavior(net, 1), 200, None, rng)