def behavior_comparison(): networks = ( ('Caveman-50-10', fio.read_network('networks/cavemen-50-10.txt')), ('Elitist-500', fio.read_network('networks/elitist-500.txt')), ('CGG-500', fio.read_network('networks/cgg-500.txt')) ) num_sims = 50 num_behaviors = 3 distributions = [] averages = np.zeros((len(networks), num_behaviors)) loop = tqdm(total=len(networks) * num_behaviors * num_sims) for i, (n_name, net) in enumerate(networks): behaviors = ( ('No Mitigations', behavior.NoMitigation()), ('Generic Pressure R=1', behavior.SimplePressureBehavior(net, rng=RNG, radius=1)), ('Edge Pressure R=1', behavior.SimpleEdgePressureBehavior(net, rng=RNG, radius=1)) # ('All Edges Sequential Flicker 1/4', # StaticFlickerBehavior(net.M, net.edges, (True, False, False, False))), # ('All Edges Random Flicker 0.25', # RandomFlickerBehavior(net.M, net.edges, 0.25)), # ('Collected Pressure Flicker 0.25, R=1', # UnifiedPressureFlickerBehavior(net, 1, RNG)), # ('Generic Pressure Radius 3', # SimplePressureBehavior(net, 3)), # ('Pressure Decay Radius 3', # PressureDecayBehavior(net, 3)), # ('Pressure Flicker Radius 3', # PressureFlickerBehavior(net, 3)) ) for j, (b_name, behavior) in enumerate(behaviors): s_scores = [] for _ in range(num_sims): loop.set_description(f'{n_name}, {b_name}') end_sir = simulate(net.M, sir0=make_starting_sir(net.N, 1, rng=RNG), disease=Disease(4, 0.3), update_connections=behavior, max_steps=200, rng=RNG)[-1] s_scores.append(np.sum(end_sir[0, :] > 0)/net.N) loop.update() # plt.title(f'{n_name}, {b_name}, Avg: {sum(s_scores)/len(s_scores)}') # plt.hist(s_scores) # plt.figure() averages[i, j] = sum(s_scores)/len(s_scores) distributions.append(s_scores) print(wasserstein_distance(distributions[1], distributions[2])) print(wasserstein_distance(distributions[4], distributions[5])) print(wasserstein_distance(distributions[7], distributions[8])) # plt.show() np.set_printoptions(precision=3, suppress=True) print(averages)
def show_edit_distance(): if len(sys.argv) < 3: print(f'Usage: {sys.argv[0]} <network 0> <network 1>') return start_time = time.time() net0 = fio.read_network(sys.argv[1]) net1 = fio.read_network(sys.argv[2]) distance = nx.graph_edit_distance(net0.G, net1.G) name0 = fio.get_network_name(sys.argv[1]) name1 = fio.get_network_name(sys.argv[2]) print( f'Distance between {name0} and {name1}: {distance} ({time.time()-start_time} s)' )
def pressure_decay_test(): G, layout, communities = fio.read_network('networks/elitist-500.txt') if layout is None or communities is None: raise Exception('File is incomplete.') net = Network(G, communities=communities) simulate(net.M, make_starting_sir(net.N, 1, RNG), Disease(4, 0.3), behavior.PressureDecayBehavior(net, 3), 200, layout, RNG)
def generic_pressure_test(): G, layout, communities = fio.read_network('networks/cavemen-10-10.txt') if layout is None or communities is None: raise Exception('File is incomplete.') net = Network(G, communities=communities) simulate(net.M, make_starting_sir(net.N, 1, RNG), Disease(4, 0.3), behavior.SimplePressureBehavior(net, 1), 200, layout, RNG)
def multi_behavior_test(display=True): """ A basic test to visualize the multi-behavior. """ net = fio.read_network('networks/elitist-500.txt') ph1 = behavior.BetweenDistancePressureHandler(net.dm, 0, 1) ph2 = behavior.BetweenDistancePressureHandler(net.dm, 1, 2) ph3 = behavior.BetweenDistancePressureHandler(net.dm, 2, 3) ph4 = behavior.BetweenDistancePressureHandler(net.dm, 10, 40) behaviors = [ behavior.FlickerPressureBehavior(RNG, ph1, .1), behavior.FlickerPressureBehavior(RNG, ph2, .2), behavior.FlickerPressureBehavior(RNG, ph3, .8), behavior.FlickerPressureBehavior(RNG, ph4, 1) ] update_behavior = behavior.MultiPressureBehavior(RNG, behaviors) if display: return simulate(M=net.M, sir0=make_starting_sir(net.N, 1, RNG), disease=Disease(4, .3), update_connections=update_behavior, max_steps=200, rng=RNG, layout=net.layout) else: return simulate(M=net.M, sir0=make_starting_sir(net.N, 1, RNG), disease=Disease(4, .3), update_connections=update_behavior, max_steps=200, rng=RNG, layout=None)
def analyze_network_entry_point(): """Analyze the network given by the command line argument.""" if len(sys.argv) < 2: print(f'Usage: {sys.argv[0]} <network>') return net = fio.read_network(sys.argv[1]) G = nx.Graph(net.G) name = fio.get_network_name(sys.argv[1]) analyze_network(G, name) visualize_network(G, net.layout, name, edge_width_func=all_same, block=False) intercommunity_edges = tuple( (u, v) for u, v in G.edges if net.communities[u] != net.communities[v]) G.remove_edges_from(intercommunity_edges) visualize_network(G, net.layout, 'Partitioned ' + name, edge_width_func=all_same, block=False) meta_G, meta_ns, meta_ew = make_meta_community_network( intercommunity_edges, G) meta_layout = make_meta_community_layout(meta_G, net.layout) visualize_network(meta_G, meta_layout, f'{name} Meta Communities', edge_width_func=lambda G: meta_ew, node_size=meta_ns, block=False) input('Press <enter> to exit.')
def main(): networks = ('cavemen-50-10', 'elitist-500', 'agent-generated-500', 'annealed-agent-generated-500', 'barabasi-albert-500-3', 'cgg-500', 'connected-comm-50-10', 'spatial-network', 'watts-strogatz-500-4-.1') network_paths = fio.network_names_to_paths(networks) for name, path in zip(networks, network_paths): net = fio.read_network(path) print(f'{name:<30} {rate_social_good(net, DecayFunction(.5)):>10.3f}')
def show_social_good(): if len(sys.argv) < 2: print(f'Usage {sys.argv[1]} <network>') return net = fio.read_network(sys.argv[1]) for k in np.linspace(.5, 1.5, 5): sg_score = socialgood.rate_social_good(net, socialgood.DecayFunction(k)) print(f'{k:<6.3f}: {sg_score}')
def save_social_good_csv(networks: Sequence[str], network_paths: Sequence[str]): decay_functions = (DecayFunction(.5), DecayFunction(1), DecayFunction(2)) with open('social-good.csv', 'w') as csvfile: writer = csv.writer(csvfile) writer.writerow([DecayFunction.function_desc] + [str(df.k) for df in decay_functions]) for name, path in tqdm(tuple(zip(networks, network_paths))): scores = [] for decay_func in decay_functions: net = fio.read_network(path) social_good_score = rate_social_good(net, decay_func) scores.append(f'{social_good_score:.3f}') writer.writerow([name] + scores)
def visualize_communicability(): if len(sys.argv) < 2: print(f'Usage {sys.argv[1]} <network>') return net = fio.read_network(sys.argv[1]) name = fio.get_network_name(sys.argv[1]) communicability = nx.communicability_exp(net.G) scores = np.array( [sum(communicability[u].values()) for u in communicability.keys()]) plt.title(f'{name}\nCommunicability') plt.hist(scores) # type: ignore plt.show(block=False) print(f'Network score: {np.sum(scores)}') scores = (scores - np.min(scores)) / (np.max(scores) - np.min(scores)) node_size = 300 * scores visualize_network(net.G, net.layout, name, node_size=node_size)
def visualize_social_good(networks: Sequence[str], network_paths: Sequence[str]): for name, path in zip(networks, network_paths): net = fio.read_network(path) node_size = node_size_from_social_good(net.G, DecayFunction(1)) plt.title(f'{name} Node Size') plt.hist(node_size, bins=None) plt.figure() print( f'{name} min = {np.min(node_size):.2f} max = {np.max(node_size):.2f}' ) visualize_network(net.G, net.layout, name, node_size=node_size, block=False) input('Done.')
def pressure_flicker_test(pressure_distance, display=True): """ A basic test to use for visualizing simulations """ net = fio.read_network('networks/elitist-500.txt') pressure_handler = behavior.DistancePressureHandler(net.dm, pressure_distance) # pressure_handler = behavior.AllPressureHandler() update_behavior = behavior.FlickerPressureBehavior(RNG, pressure_handler, 0.25) if display: return simulate(M=net.M, sir0=make_starting_sir(net.N, 1, RNG), disease=Disease(4, 0.3), update_connections=update_behavior, max_steps=200, rng=RNG, layout=net.layout) else: return simulate(M=net.M, sir0=make_starting_sir(net.N, 1, RNG), disease=Disease(4, 0.3), update_connections=update_behavior, max_steps=200, rng=RNG, layout=None)
def multi_pressure_handler_test(display=True): """ A basic test for the MultiPressureHandler. """ net = fio.read_network('networks/elitist-500.txt') ph1 = behavior.BetweenDistancePressureHandler(net.dm, 2, 3) ph2 = behavior.BetweenDistancePressureHandler(net.dm, 10, 40) ph = behavior.MultiPressureHandler((ph1, ph2)) update_behavior = behavior.FlickerPressureBehavior(RNG, ph, 1) if display: return simulate(M=net.M, sir0=make_starting_sir(net.N, 1, RNG), disease=Disease(4, .3), update_connections=update_behavior, max_steps=200, rng=RNG, layout=net.layout) else: return simulate(M=net.M, sir0=make_starting_sir(net.N, 1, RNG), disease=Disease(4, .3), update_connections=update_behavior, max_steps=200, rng=RNG, layout=None)
def elitist_experiment(): rng = np.random.default_rng() path = 'networks/elitist-500.txt' name = fio.get_network_name(path) net = fio.read_network(path) r, fp = 2, .75 update_connections, uc_name = (sd.SimplePressureBehavior(net, rng, r, fp), f'Pressure(r={r}, fp={fp})') # update_connections, uc_name = sd.no_update, 'Static' disease = sd.Disease(4, .2) sir0 = sd.make_starting_sir(net.N, (0, ), rng) survival_rates = np.array([ simulate_return_survival_rate(net, disease, update_connections, rng, sir0) for _ in range(500) ]) title = f'{disease} {uc_name}\n{name} Survival Rates' plt.title(title) plt.boxplot(survival_rates) plt.savefig(title + '.png', format='png')
def main(): if len(sys.argv) < 3: print(f'Usage {sys.argv[0]} <network> <num communities>') return M, layout = old_read_network_file(sys.argv[1]) if layout is None: print('layout is None. Exiting.') return G = nx.Graph(M) # interedges = label_partition(G, int(sys.argv[2])) interedges = girvan_newman_partition(G, int(sys.argv[2])) communities = intercommunity_edges_to_communities(G, interedges) new_name = get_network_name(sys.argv[1]) + '-new-format' write_network(G, new_name, layout, communities) net = read_network(new_name + '.txt') interedges = tuple( set((u, v) for u, v in net.edges if communities[u] != communities[v])) partitioned = nx.Graph(net.G) partitioned.remove_edges_from(interedges) meta_network, meta_ns, meta_ew = make_meta_community_network( interedges, partitioned) meta_layout = make_meta_community_layout(meta_network, layout) print(f'There are {len(meta_network)} communities.') node_color = [COLORS[i] for i in communities.values()] visualize_network(G, layout, new_name, node_color=node_color, block=False) # type: ignore plt.figure() plt.hist([len(comp) for comp in nx.connected_components(partitioned)], bins=None) plt.figure() visualize_network(meta_network, meta_layout, new_name + ' meta community', node_size=meta_ns, edge_width_func=lambda G: meta_ew)
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 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 agent_based_entry_point(): if len(sys.argv) < 2: print(f'Usage: {sys.argv[0]} <network or number of agents>') return N = int_or_none(sys.argv[1]) if N is None: net = read_network(sys.argv[1]) N = net.N else: net = Network(nx.empty_graph(N)) rand = np.random.default_rng() for i in range(50): start_time = time.time() H = make_agent_generated_network(nx.Graph(net.G), TimeBasedBehavior(N, 4, 6, 15, rand)) if H is None: print( f'Failure on iteration {i} ({time.time()-start_time:.2f} s).') else: print( f'Success on iteration {i} ({time.time()-start_time:.2f} s).')
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)
def __call__(self) -> Network: if self._net is None: path = fio.network_names_to_paths((self._name, ))[0] self._net = fio.read_network(path) return self._net