diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 790a344..fabcb79 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,13 +53,13 @@ jobs: - name: Test NetworkZ run: | - pytest --doctest-modules --durations=10 + pytest - name: Test Dispatching # Limit this to only a single combination from the matrix if: ${{ (matrix.os == 'ubuntu') && (matrix.python-version == '3.11') }} run: | - NetworkZ_GRAPH_CONVERT=nx-loopback pytest --doctest-modules --durations=10 + NetworkZ_GRAPH_CONVERT=nx-loopback pytest extra: runs-on: ${{ matrix.os }} @@ -123,7 +123,7 @@ jobs: - name: Test NetworkZ run: | - pytest --doctest-modules --durations=10 + pytest prerelease: runs-on: ${{ matrix.os }}-latest @@ -147,4 +147,4 @@ jobs: - name: Test NetworkZ run: | - pytest --doctest-modules --durations=10 + pytest diff --git a/.gitignore b/.gitignore index 93431b5..f944dfc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ scripts +*.txt # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/README.md b/README.md index 5313b1e..f60430d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,10 @@ NetworkZ is a library of graph algorithms in Python. It is an extension of the [NetworkX](https://github.com/networkx/networkx). It contains (by import) everything that is in NetworkX, plus some additional algorithms that were submitted into NetworkX but not merged yet. Currently, NetworkZ contains the following additional algorithms: * [Rank-maximal matching](networkz/algorithms/bipartite/rank_maximal_matching.py): by Oriya Alperin, Liel Vaknin and Amiel Lejzor. +* [Maximum-weight fractional matching](networkz/algorithms/max_weight_fractional_matching.py): by Oriya Alperin, Liel Vaknin and Amiel Lejzor. * [Social-aware coalition formation](networkz/algorithms/approximation/coalition_formation.py) - by Victor Kushnir. +* [Minimum cut on a graph with node capacity](networkz/algorithms/max_flow_with_node_capacity.py): by Yuval Bubnovsky, Almog David and Shaked Levi. +* [Several approximate solutions to the Firefighter problem](networkz/algorithms/approximation/firefighter_problem): by Yuval Bubnovsky, Almog David and Shaked Levi. ## Installation diff --git a/experiments/firefighter_problem/comparisons.py b/experiments/firefighter_problem/comparisons.py new file mode 100644 index 0000000..75d6876 --- /dev/null +++ b/experiments/firefighter_problem/comparisons.py @@ -0,0 +1,407 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import experiments_csv +from experiments_csv import * +import logging +from time import perf_counter +import pandas as pd +import random + +from networkz.algorithms.approximation.firefighter_problem.Utils import * +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import * +from networkz.algorithms.approximation.firefighter_problem.Random_Graph_Generator import generate_random_layered_network +from networkz.algorithms.approximation.firefighter_problem.Random_Graph_Generator import generate_random_DiGraph + +logger = logging.getLogger(__name__) + +def setup_global_logger(level: int = logging.DEBUG): + """ + Setup the global logger with a specific format and logging level. + + Parameters: + ---------- + level : int + Logging level, e.g., logging.DEBUG, logging.INFO. + """ + log_format = "|| %(asctime)s || %(levelname)s || %(message)s" + date_format = '%H:%M:%S' + formatter = logging.Formatter(log_format, datefmt=date_format) + handler = logging.StreamHandler() + handler.setFormatter(formatter) + + root_logger = logging.getLogger() + root_logger.setLevel(level) + root_logger.addHandler(handler) + +def runner_no_spreading(algorithm, graph, source, targets): + """ + Run the specified algorithm without spreading. + + Parameters: + ---------- + algorithm : function + The algorithm to be executed. + graph : nx.Graph + The graph on which the algorithm is to be run. + source : int + The source node. + targets : list + The target nodes to be saved. + + Returns: + ------- + dict: + A dictionary containing the budget used by the algorithm. + """ + if algorithm == heuristic_minbudget: + result = algorithm(Graph=graph, source=source, targets=targets, spreading=False) + return {"Budget": result} + else: + result = algorithm(Graph=graph, source=source, targets=targets) + return {"Budget": result} + +def runner_spreading(algorithm, graph, budget, source, targets): + """ + Run the specified algorithm with spreading. + + Parameters: + ---------- + algorithm : function + The algorithm to be executed. + graph : nx.Graph + The graph on which the algorithm is to be run. + source : int + The source node. + targets : list + The target nodes to be saved. + + Returns: + ------- + dict: + A dictionary containing the budget used or nodes saved by the algorithm. + """ + if algorithm == heuristic_minbudget: + return {"Budget": (algorithm(Graph=graph, source=source, targets=targets, spreading=True))} + + if algorithm == heuristic_maxsave: + return {"Nodes_Saved": (str(len(algorithm(Graph=graph, budget=budget, source=source, targets=targets, spreading=True)[1])))} + + if algorithm == spreading_maxsave: + return {"Nodes_Saved": (str(len(algorithm(Graph=graph, budget=budget, source=source, targets=targets)[1])))} + + else: + return {"Budget": (algorithm(Graph=graph, source=source, targets=targets))} + +def Compare_NonSpread(): + """ + Compare the performance of different algorithms without spreading. + + This function runs multiple experiments on randomly generated layered networks + and plots the results comparing the budget used by different algorithms. + """ + ex1 = experiments_csv.Experiment("./experiments/", "non_spreading.csv", backup_folder=None) + ex1.clear_previous_results() # to clear previous experiments + + input_ranges = { + "algorithm": [non_spreading_dirlaynet_minbudget, non_spreading_minbudget, heuristic_minbudget], + } + + def multiple_runs(runs=30): + for _ in range(runs): + graph = generate_random_layered_network() + source = 0 + nodes = list(graph.nodes) + nodes.remove(0) + num_targets = random.randint(1, int(len(nodes) / 4) + 1) + targets = random.sample(nodes, num_targets) + for algorithm in input_ranges["algorithm"]: + start_time = perf_counter() + result = runner_no_spreading(algorithm, graph, source, targets) + runtime = perf_counter() - start_time + ex1.add({**{"algorithm": algorithm.__name__, "runtime": runtime, "graph_nodes": len(graph.nodes)}, **result}) + return {"status": "completed"} + + # Set a time limit for the entire batch run + ex1.run_with_time_limit(multiple_runs, input_ranges={}, time_limit=0.9) + + # Preprocess the DataFrame to extract numeric budget values + results_csv_file = "./experiments/non_spreading_minbudget.csv" + results = pd.read_csv(results_csv_file) + + # Extract the numeric budget from the 'Budget' column + def extract_budget_numeric(budget): + if isinstance(budget, tuple): + return budget[0] + elif isinstance(budget, str): + try: + return eval(budget)[0] + except: + return None + return None + + results['Budget_numeric'] = results['Budget'].apply(extract_budget_numeric) + + # Drop rows where the 'Budget_numeric' is not available + results = results.dropna(subset=['Budget_numeric']) + + # Save the preprocessed DataFrame to a temporary CSV file + preprocessed_csv_file = "./experiments/non_spreading_minbudget_preprocessed.csv" + results.to_csv(preprocessed_csv_file, index=False) + + print("\n DataFrame-NonSpread: \n", results) + + # Plot the results using the preprocessed CSV file + single_plot_results( + results_csv_file=preprocessed_csv_file, + filter={}, + x_field="graph_nodes", + y_field="Budget_numeric", + z_field="algorithm", + mean=True, + save_to_file="./experiments/non_spreading.png" + ) + + print("\n DataFrame-NonSpread: \n", ex1.dataFrame) + +def Compare_SpreadingMaxSave(): + """ + Compare the performance of different algorithms with spreading for maximizing saved nodes. + + This function runs multiple experiments on randomly generated directed graphs + and plots the results comparing the number of nodes saved by different algorithms. + """ + ex2 = experiments_csv.Experiment("./experiments/", "spreading_maxsave.csv", backup_folder=None) + ex2.clear_previous_results() # to clear previous experiments + + input_ranges = { + "algorithm": [spreading_maxsave, heuristic_maxsave] + } + + node_counts = [100, 200, 400] + edge_probabilities = [0.1, 0.5, 0.8] + budget_range = [1,2,3,5,7,10] + + def multiple_runs(runs=10): + for num_nodes in node_counts: + for edge_prob in edge_probabilities: + graph = generate_random_DiGraph(num_nodes=num_nodes, edge_probability=edge_prob, seed=None) + for _ in range(runs): + source = 0 + nodes = list(graph.nodes) + nodes.remove(0) + num_targets = random.randint(1, int(len(nodes) / 2) + 1) + targets = random.sample(nodes, num_targets) + for budget in budget_range: + for algorithm in input_ranges["algorithm"]: + start_time = perf_counter() + result = runner_spreading(algorithm, graph, budget, source, targets) + runtime = perf_counter() - start_time + + ex2.add({**{"algorithm": algorithm.__name__, "runtime": runtime, "Budget": budget, "graph_nodes": num_nodes, "edge_probability": edge_prob}, **result}) + return {"status": "completed"} + + # Set a time limit for the entire batch run + ex2.run_with_time_limit(multiple_runs, input_ranges={}, time_limit=0.9) + + ## DATA ISSUE WE HAD SO THIS IS A FIX ## + # Load the results + results_csv_file = "./experiments/spreading_maxsave.csv" + results = pd.read_csv(results_csv_file) + + # Ensure 'algorithm' column is of type string + results['algorithm'] = results['algorithm'].astype(str) + + # Ensure 'Budget' column is numeric and drop rows with NaNs + results['Budget'] = pd.to_numeric(results['Budget'], errors='coerce') + results = results.dropna(subset=['Budget']) + + # Ensure 'Budget' is an integer + results['Budget'] = results['Budget'].astype(int) + + # Ensure 'Nodes_Saved' column is numeric and drop rows with NaNs + results['Nodes_Saved'] = pd.to_numeric(results['Nodes_Saved'], errors='coerce') + results = results.dropna(subset=['Nodes_Saved']) + + # Ensure 'Nodes_Saved' is an integer + results['Nodes_Saved'] = results['Nodes_Saved'].astype(int) + + # Save the cleaned DataFrame to a new CSV file (optional, for debugging) + cleaned_csv_file = "./experiments/spreading_maxsave_preprocessed.csv" + results.to_csv(cleaned_csv_file, index=False) + + # Plot the results using the cleaned DataFrame + multi_plot_results( + results_csv_file=cleaned_csv_file, + filter={}, + subplot_rows=2, + subplot_cols=3, + x_field="graph_nodes", + y_field="Nodes_Saved", + z_field="algorithm", + subplot_field="Budget", + sharex=True, + sharey=True, + mean=True, + save_to_file="./experiments/spreading_maxsave_budget.png" + ) + + multi_plot_results( + results_csv_file=cleaned_csv_file, + filter={"graph_nodes":100}, + subplot_rows=3, + subplot_cols=1, + x_field="Budget", + y_field="Nodes_Saved", + z_field="algorithm", + subplot_field="edge_probability", + sharex=True, + sharey=True, + mean=True, + save_to_file="./experiments/spreading_maxsave_100_edge_prob.png" + ) + + multi_plot_results( + results_csv_file=cleaned_csv_file, + filter={"graph_nodes":200}, + subplot_rows=3, + subplot_cols=1, + x_field="Budget", + y_field="Nodes_Saved", + z_field="algorithm", + subplot_field="edge_probability", + sharex=True, + sharey=True, + mean=True, + save_to_file="./experiments/spreading_maxsave_200_edge_prob.png" + ) + + multi_plot_results( + results_csv_file=cleaned_csv_file, + filter={"graph_nodes":400}, + subplot_rows=3, + subplot_cols=1, + x_field="Budget", + y_field="Nodes_Saved", + z_field="algorithm", + subplot_field="edge_probability", + sharex=True, + sharey=True, + mean=True, + save_to_file="./experiments/spreading_maxsave_400_edge_prob.png" + ) + + print("\n DataFrame-NonSpread: \n", ex2.dataFrame) + +def Compare_SpreadingMinBudget(): + """ + Compare the performance of different algorithms with spreading for minimizing the budget. + + This function runs multiple experiments on randomly generated directed graphs + and plots the results comparing the budget used by different algorithms. + """ + ex3 = experiments_csv.Experiment("./experiments/", "spreading_minbudget.csv", backup_folder=None) + ex3.clear_previous_results() # to clear previous experiments + + input_ranges = { + "algorithm": [spreading_minbudget, heuristic_minbudget] + } + + node_counts = [100, 200, 400] + edge_probabilities = [0.1, 0.5, 0.8] + + def multiple_runs(runs=10): + for num_nodes in node_counts: + for edge_prob in edge_probabilities: + graph = generate_random_DiGraph(num_nodes=num_nodes, edge_probability=edge_prob, seed=None) + for _ in range(runs): + source = 0 + nodes = list(graph.nodes) + nodes.remove(0) + num_targets = random.randint(1, int(len(nodes) / 2) + 1) + targets = random.sample(nodes, num_targets) + for algorithm in input_ranges["algorithm"]: + start_time = perf_counter() + result = runner_spreading(algorithm, graph, None, source, targets) + runtime = perf_counter() - start_time + ex3.add({**{"algorithm": algorithm.__name__, "runtime": runtime, "graph_nodes": num_nodes, "edge_probability": edge_prob}, **result}) + return {"status": "completed"} + + # Set a time limit for the entire batch run + ex3.run_with_time_limit(multiple_runs, input_ranges={}, time_limit=0.9) + + # Preprocess the DataFrame to extract numeric budget values + results_csv_file = "./experiments/spreading_minbudget.csv" + results = pd.read_csv(results_csv_file) + + # Extract the numeric budget from the 'Budget' column + def extract_budget_numeric(budget): + if isinstance(budget, tuple): + return budget[0] + elif isinstance(budget, str): + try: + return eval(budget)[0] + except: + return None + return None + + results['Budget_numeric'] = results['Budget'].apply(extract_budget_numeric) + + # Drop rows where the 'Budget_numeric' is not available + results = results.dropna(subset=['Budget_numeric']) + + # Save the preprocessed DataFrame to a temporary CSV file + preprocessed_csv_file = "./experiments/spreading_minbudget_preprocessed.csv" + results.to_csv(preprocessed_csv_file, index=False) + + print("\n DataFrame-NonSpread: \n", results) + + # Plot the results using the preprocessed CSV file + single_plot_results( + results_csv_file=preprocessed_csv_file, + filter={}, + x_field="graph_nodes", + y_field="Budget_numeric", + z_field="algorithm", + mean=True, + save_to_file="./experiments/spreading_minbudget.png" + ) + + single_plot_results( + results_csv_file=preprocessed_csv_file, + filter={"edge_probability":0.1}, + x_field="graph_nodes", + y_field="Budget_numeric", + z_field="algorithm", + mean=True, + save_to_file="./experiments/spreading_minbudget_edge.png" + ) + + print("\n DataFrame-NonSpread: \n", ex3.dataFrame) + +if __name__ == "__main__": + """To run this - please run one at a time; mark the others and then run""" + + setup_global_logger(level=logging.DEBUG) + + #Compare_NonSpread() + Compare_SpreadingMinBudget() + #Compare_SpreadingMaxSave() \ No newline at end of file diff --git a/experiments/firefighter_problem/non_spreading.csv b/experiments/firefighter_problem/non_spreading.csv new file mode 100644 index 0000000..7c9b5f7 --- /dev/null +++ b/experiments/firefighter_problem/non_spreading.csv @@ -0,0 +1,92 @@ +algorithm,runtime,graph_nodes,Budget +non_spreading_dirlaynet_minbudget,0.3383908999385312,140,"(4, {0: [2, 12, 97, 130], 2: [87, 110], 3: [97, 110], 4: [110], 5: [110]})" +non_spreading_minbudget,0.015752499923110008,140,"(11, [])" +heuristic_minbudget,0.798951999982819,140,"(4, [(2, 1), (12, 1), (10, 1), (6, 1), (34, 2), (30, 2), (33, 2), (37, 2), (48, 3), (47, 3), (42, 3), (40, 3), (60, 4), (53, 4), (59, 4), (67, 4), (87, 5), (69, 5), (75, 5), (77, 5), (97, 6), (99, 6), (95, 6), (98, 6), (102, 7), (110, 7), (107, 7), (105, 7)])" +non_spreading_dirlaynet_minbudget,0.17233670002315193,110,"(9, {0: [7, 25, 17, 39, 31, 55, 66, 84, 91], 1: [39, 31, 55, 66, 91], 2: [55, 91], 4: [91], 5: [91]})" +non_spreading_minbudget,0.01266180002130568,110,"(18, [])" +heuristic_minbudget,0.7278256000718102,110,"(4, [(7, 1), (25, 1), (17, 1), (19, 1), (29, 2), (39, 2), (33, 2), (31, 2), (55, 3), (45, 3), (52, 3), (51, 3), (66, 4), (65, 4), (62, 4), (67, 4), (84, 5), (80, 5), (77, 5), (78, 5)])" +non_spreading_dirlaynet_minbudget,0.36679140001069754,152,"(7, {0: [7, 14, 21, 78, 103, 109, 147], 1: [36], 4: [147]})" +non_spreading_minbudget,0.020042599993757904,152,"(9, [])" +heuristic_minbudget,1.0867155999876559,152,"(3, [(21, 1), (7, 1), (14, 1), (36, 2), (43, 2), (45, 2), (78, 3), (62, 3), (71, 3), (82, 4), (83, 4), (88, 4), (103, 5), (101, 5), (97, 5), (109, 6), (126, 6), (131, 6)])" +non_spreading_dirlaynet_minbudget,0.5028269999893382,208,"(24, {0: [7, 14, 17, 23, 24, 9, 16, 1, 5, 22, 6, 15, 4, 13, 8, 18, 11, 21, 20, 10, 3, 12, 19, 2]})" +non_spreading_minbudget,0.027307800017297268,208,"(24, [])" +heuristic_minbudget,1.8271003999980167,208,"(9, [(23, 1), (22, 1), (20, 1), (18, 1), (17, 1), (3, 1), (9, 1), (8, 1), (4, 1), (53, 2), (32, 2), (37, 2), (27, 2), (48, 2), (31, 2), (40, 2), (46, 2), (39, 2), (77, 3), (69, 3), (64, 3), (67, 3), (66, 3), (56, 3), (79, 3), (72, 3), (61, 3), (85, 4), (86, 4), (82, 4), (91, 4), (84, 4), (87, 4), (88, 4), (90, 4), (93, 4), (106, 5), (109, 5), (99, 5), (95, 5), (98, 5), (96, 5), (108, 5), (103, 5), (97, 5), (126, 6), (114, 6), (117, 6), (113, 6), (111, 6), (130, 6), (119, 6), (118, 6), (121, 6), (136, 7), (135, 7), (146, 7), (150, 7), (158, 7), (139, 7), (154, 7), (144, 7), (145, 7), (167, 8), (169, 8), (163, 8), (166, 8), (165, 8), (162, 8), (168, 8), (164, 8)])" +non_spreading_dirlaynet_minbudget,0.4180444999365136,180,"(11, {0: [5, 20, 13, 19, 2, 22, 58, 72, 118, 145, 168], 1: [22, 58, 72, 145, 168], 2: [58, 72, 118]})" +non_spreading_minbudget,0.026318399934098125,180,"(19, [])" +heuristic_minbudget,1.598106799996458,180,"(6, [(13, 1), (19, 1), (20, 1), (5, 1), (2, 1), (17, 1), (21, 2), (22, 2), (33, 2), (35, 2), (38, 2), (40, 2), (72, 3), (58, 3), (69, 3), (73, 3), (50, 3), (74, 3), (92, 4), (94, 4), (93, 4), (96, 4), (89, 4), (81, 4), (102, 5), (118, 5), (100, 5), (101, 5), (108, 5), (119, 5), (126, 6), (128, 6), (124, 6), (125, 6), (129, 6), (123, 6), (136, 7), (134, 7)])" +non_spreading_dirlaynet_minbudget,0.2731701999437064,139,"(9, {0: [24, 25, 10, 5, 39, 38, 31, 40, 36], 1: [39, 38, 31, 40, 36, 45]})" +non_spreading_minbudget,0.019093799986876547,139,"(15, [])" +heuristic_minbudget,1.0293473000638187,139,"(6, [(25, 1), (24, 1), (10, 1), (5, 1), (8, 1), (20, 1), (34, 2), (36, 2), (38, 2), (39, 2), (33, 2), (30, 2), (46, 3), (42, 3), (44, 3), (45, 3), (55, 3), (43, 3), (63, 4), (72, 4), (69, 4), (62, 4), (65, 4), (64, 4), (83, 5), (92, 5), (91, 5), (77, 5), (90, 5), (82, 5), (97, 6), (99, 6), (101, 6), (98, 6), (100, 6), (104, 6), (107, 7), (109, 7), (110, 7)])" +non_spreading_dirlaynet_minbudget,0.3905019999947399,184,"(12, {0: [25, 11, 20, 17, 37, 47, 79, 76, 97, 91, 96, 106], 1: [37, 47, 79, 76, 97, 91, 96, 106], 2: [79, 76, 97, 91, 96], 3: [97, 91, 96]})" +non_spreading_minbudget,0.037450100062415004,184,"(24, [])" +heuristic_minbudget,1.7678336999379098,184,"(6, [(17, 1), (25, 1), (11, 1), (20, 1), (2, 1), (13, 1), (43, 2), (47, 2), (37, 2), (50, 2), (33, 2), (57, 2), (82, 3), (77, 3), (79, 3), (76, 3), (59, 3), (70, 3), (88, 4), (92, 4), (97, 4), (87, 4), (94, 4), (86, 4), (111, 5), (113, 5), (109, 5), (114, 5), (125, 5), (122, 5), (140, 6), (138, 6), (135, 6), (141, 6), (129, 6), (127, 6), (151, 7), (152, 7), (144, 7), (150, 7), (162, 7), (142, 7)])" +non_spreading_dirlaynet_minbudget,0.26434650004375726,116,"(9, {0: [4, 2, 8, 1, 5, 6, 3, 9, 32]})" +non_spreading_minbudget,0.015567100024782121,116,"(9, [])" +heuristic_minbudget,0.3790762999560684,116,"(6, [(2, 1), (1, 1), (9, 1), (4, 1), (5, 1), (8, 1), (14, 2), (39, 2), (13, 2), (24, 2), (31, 2), (19, 2), (44, 3), (61, 3), (55, 3), (42, 3), (60, 3), (48, 3), (69, 4), (76, 4), (72, 4), (62, 4), (73, 4), (64, 4)])" +non_spreading_dirlaynet_minbudget,0.27031509997323155,146,"(3, {0: [23, 29, 97], 1: [105], 2: [55, 97], 3: [97], 4: [97]})" +non_spreading_minbudget,0.01591560000088066,146,"(9, [])" +heuristic_minbudget,0.8679373000049964,146,"(2, [(23, 1), (1, 1), (29, 2), (31, 2), (55, 3), (58, 3), (60, 4), (63, 4), (88, 5), (93, 5), (98, 6), (101, 6), (106, 7), (109, 7), (116, 8), (120, 8)])" +non_spreading_dirlaynet_minbudget,0.18942820001393557,99,"(7, {0: [7, 13, 11, 17, 49, 68, 98], 1: [49, 68, 98], 2: [49, 68, 98]})" +non_spreading_minbudget,0.012153099989518523,99,"(13, [])" +heuristic_minbudget,0.6063708999427035,99,"(4, [(7, 1), (13, 1), (17, 1), (11, 1), (24, 2), (41, 2), (39, 2), (21, 2), (48, 3), (50, 3), (49, 3), (55, 3), (68, 4), (85, 4), (71, 4), (64, 4)])" +non_spreading_dirlaynet_minbudget,0.12446479999925941,82,"(7, {0: [24, 1, 20, 3, 19, 53, 58], 1: [58], 2: [58], 3: [58]})" +non_spreading_minbudget,0.007472099969163537,82,"(10, [])" +heuristic_minbudget,0.5537956999614835,82,"(5, [(1, 1), (24, 1), (3, 1), (19, 1), (20, 1), (34, 2), (28, 2), (32, 2), (30, 2), (33, 2), (37, 3), (38, 3)])" +non_spreading_dirlaynet_minbudget,0.17413019994273782,107,"(12, {0: [7, 4, 2, 8, 10, 11, 9, 1, 6, 3, 12, 5]})" +non_spreading_minbudget,0.010613199905492365,107,"(12, [])" +heuristic_minbudget,0.7465448000002652,107,"(8, [(6, 1), (12, 1), (1, 1), (11, 1), (3, 1), (7, 1), (10, 1), (5, 1), (23, 2), (16, 2), (28, 2), (15, 2), (18, 2), (26, 2), (22, 2), (24, 2), (41, 3), (36, 3), (38, 3), (49, 3), (46, 3), (32, 3), (47, 3), (44, 3), (63, 4), (54, 4), (58, 4), (64, 4), (62, 4), (53, 4), (61, 4), (60, 4), (69, 5), (75, 5), (67, 5), (79, 5), (80, 5), (78, 5), (74, 5), (82, 5), (84, 6), (85, 6), (86, 6), (87, 6)])" +non_spreading_dirlaynet_minbudget,0.25344030000269413,134,"(20, {0: [7, 14, 17, 9, 16, 1, 5, 6, 15, 4, 8, 18, 11, 20, 10, 3, 12, 19, 2, 40]})" +non_spreading_minbudget,0.08458460005931556,134,"(20, [])" +heuristic_minbudget,0.6117942000273615,134,"(5, [(20, 1), (8, 1), (4, 1), (17, 1), (6, 1), (49, 2), (30, 2), (40, 2), (42, 2), (44, 2), (61, 3), (55, 3), (53, 3), (57, 3), (56, 3), (65, 4), (71, 4), (64, 4), (66, 4), (63, 4), (77, 5), (85, 5), (90, 5), (78, 5), (91, 5), (97, 6), (101, 6), (103, 6), (107, 6), (93, 6), (117, 7), (116, 7), (109, 7), (110, 7), (111, 7)])" +non_spreading_dirlaynet_minbudget,0.17076830007135868,90,"(8, {0: [6, 1, 5, 30, 18, 43, 45, 64], 1: [30, 18, 43, 45, 64], 2: [43, 45, 64], 3: [64]})" +non_spreading_minbudget,0.011342300102114677,90,"(14, [])" +heuristic_minbudget,0.5426640999503434,90,"(4, [(6, 1), (1, 1), (5, 1), (4, 1), (30, 2), (18, 2), (29, 2), (37, 2), (52, 3), (45, 3), (43, 3), (48, 3), (73, 4), (64, 4), (66, 4), (80, 4)])" +non_spreading_dirlaynet_minbudget,0.19489240006078035,112,"(9, {0: [7, 4, 2, 8, 1, 5, 6, 3, 9]})" +non_spreading_minbudget,0.01148700003977865,112,"(9, [])" +heuristic_minbudget,0.4493562000570819,112,"(4, [(9, 1), (5, 1), (3, 1), (6, 1), (24, 2), (19, 2), (10, 2), (13, 2), (28, 3), (37, 3), (41, 3), (26, 3), (58, 4), (66, 4), (47, 4), (60, 4), (74, 5), (79, 5), (76, 5), (83, 5), (89, 6), (88, 6), (85, 6), (87, 6), (91, 7), (92, 7), (95, 7), (98, 7)])" +non_spreading_dirlaynet_minbudget,0.3376789001049474,148,"(11, {0: [7, 4, 8, 6, 11, 9, 1, 5, 10, 3, 2]})" +non_spreading_minbudget,0.02147559996228665,148,"(11, [])" +heuristic_minbudget,0.899608499952592,148,"(4, [(2, 1), (5, 1), (6, 1), (7, 1), (26, 2), (21, 2), (32, 2), (20, 2), (49, 3), (41, 3), (52, 3), (42, 3), (66, 4), (65, 4), (74, 4), (72, 4), (102, 5), (107, 5), (109, 5), (92, 5), (115, 6), (129, 6), (132, 6), (117, 6)])" +non_spreading_dirlaynet_minbudget,0.16925049992278218,108,"(9, {0: [7, 4, 2, 8, 1, 5, 6, 3, 9]})" +non_spreading_minbudget,0.010174600058235228,108,"(9, [])" +heuristic_minbudget,0.37108299997635186,108,"(6, [(6, 1), (1, 1), (4, 1), (9, 1), (8, 1), (7, 1), (12, 2), (16, 2), (13, 2), (22, 2), (15, 2), (20, 2), (30, 3), (31, 3), (24, 3), (33, 3), (32, 3), (27, 3), (40, 4), (43, 4), (42, 4), (39, 4), (38, 4), (37, 4), (46, 5), (44, 5), (48, 5), (61, 5), (68, 5), (58, 5), (74, 6), (75, 6), (71, 6), (69, 6), (73, 6), (76, 6)])" +non_spreading_dirlaynet_minbudget,0.17099270003382117,91,"(15, {0: [7, 4, 2, 13, 14, 8, 10, 11, 9, 6, 3, 12, 15, 5, 23]})" +non_spreading_minbudget,0.010515599977225065,91,"(15, [])" +heuristic_minbudget,0.5208220999920741,91,"(6, [(4, 1), (13, 1), (6, 1), (10, 1), (14, 1), (2, 1), (22, 2), (31, 2), (27, 2), (23, 2), (29, 2), (28, 2), (34, 3), (48, 3), (39, 3), (44, 3), (51, 3), (33, 3), (55, 4), (71, 4), (64, 4), (61, 4), (67, 4), (59, 4)])" +non_spreading_dirlaynet_minbudget,0.15158629999496043,85,"(7, {0: [8, 20, 6, 27, 35, 46, 69], 1: [69]})" +non_spreading_minbudget,0.008138900040648878,85,"(8, [])" +heuristic_minbudget,0.3552039999049157,85,"(3, [(8, 1), (20, 1), (6, 1), (27, 2), (26, 2), (29, 2), (38, 3), (42, 3), (32, 3), (46, 4), (45, 4), (49, 4)])" +non_spreading_dirlaynet_minbudget,0.22132230002898723,127,"(8, {0: [7, 4, 8, 1, 5, 6, 3, 2]})" +non_spreading_minbudget,0.016545600024983287,127,"(8, [])" +heuristic_minbudget,0.5257905001053587,127,"(6, [(6, 1), (1, 1), (5, 1), (2, 1), (4, 1), (7, 1), (28, 2), (11, 2), (27, 2), (14, 2), (29, 2), (12, 2), (41, 3), (43, 3), (46, 3), (48, 3), (42, 3), (40, 3), (67, 4), (71, 4), (56, 4), (49, 4), (62, 4), (69, 4), (73, 5), (75, 5), (91, 5), (83, 5), (81, 5), (80, 5), (98, 6), (101, 6), (94, 6), (99, 6), (92, 6), (95, 6)])" +non_spreading_dirlaynet_minbudget,0.2360579000087455,129,"(7, {0: [7, 4, 1, 5, 6, 3, 2]})" +non_spreading_minbudget,0.015887600020505488,129,"(7, [])" +heuristic_minbudget,0.2970746000064537,129,"(3, [(5, 1), (2, 1), (7, 1), (16, 2), (8, 2), (13, 2), (27, 3), (24, 3), (22, 3), (28, 4), (29, 4), (32, 4), (43, 5), (45, 5), (38, 5), (52, 6), (53, 6), (56, 6), (64, 7), (62, 7), (69, 7), (83, 8), (93, 8), (98, 8)])" +non_spreading_dirlaynet_minbudget,0.3081332999281585,149,"(22, {0: [7, 14, 17, 9, 16, 1, 5, 22, 6, 15, 4, 13, 8, 18, 11, 21, 20, 10, 3, 12, 19, 2]})" +non_spreading_minbudget,0.020257299998775125,149,"(22, [])" +heuristic_minbudget,0.8213011999614537,149,"(9, [(18, 1), (16, 1), (19, 1), (11, 1), (14, 1), (17, 1), (13, 1), (10, 1), (5, 1), (47, 2), (35, 2), (28, 2), (43, 2), (34, 2), (46, 2), (45, 2), (32, 2), (39, 2), (56, 3), (71, 3), (54, 3), (57, 3), (67, 3), (53, 3), (55, 3), (68, 3), (72, 3), (80, 4), (76, 4), (74, 4), (79, 4), (78, 4), (77, 4), (75, 4)])" +non_spreading_dirlaynet_minbudget,0.21045160002540797,110,"(5, {0: [14, 43, 24, 45, 102], 1: [43, 24, 102]})" +non_spreading_minbudget,0.012047900003381073,110,"(8, [])" +heuristic_minbudget,0.7300266999518499,110,"(4, [(14, 1), (19, 1), (15, 1), (12, 1), (44, 2), (27, 2), (24, 2), (43, 2), (45, 3), (52, 3), (56, 3), (49, 3), (71, 4), (73, 4), (61, 4), (70, 4), (80, 5), (77, 5), (81, 5), (86, 5)])" +non_spreading_dirlaynet_minbudget,0.27784580003935844,138,"(6, {0: [7, 15, 9, 39, 49, 51], 1: [39, 49, 51], 2: [49, 51]})" +non_spreading_minbudget,0.020029000006616116,138,"(11, [])" +heuristic_minbudget,0.8300812999950722,138,"(5, [(9, 1), (15, 1), (7, 1), (18, 1), (1, 1), (39, 2), (48, 2), (28, 2), (31, 2), (36, 2), (53, 3), (51, 3), (52, 3), (49, 3), (50, 3), (70, 4), (64, 4)])" +non_spreading_dirlaynet_minbudget,0.31440829997882247,163,"(6, {0: [23, 20, 39, 43, 51, 50], 1: [39, 43, 51, 50], 2: [51, 50]})" +non_spreading_minbudget,0.01737050001975149,163,"(10, [])" +heuristic_minbudget,0.8383238000096753,163,"(4, [(23, 1), (20, 1), (7, 1), (22, 1), (39, 2), (26, 2), (43, 2), (27, 2), (51, 3), (52, 3), (50, 3), (53, 3), (67, 4), (78, 4), (77, 4), (69, 4), (87, 5), (93, 5), (80, 5), (97, 5), (122, 6), (115, 6), (116, 6), (121, 6), (125, 7), (123, 7), (126, 7), (127, 7)])" +non_spreading_dirlaynet_minbudget,0.23480509989894927,93,"(10, {0: [7, 4, 8, 6, 11, 5, 10, 3, 2, 32]})" +non_spreading_minbudget,0.009444999974220991,93,"(11, [])" +heuristic_minbudget,0.25563530006911606,93,"(4, [(10, 1), (5, 1), (11, 1), (8, 1), (17, 2), (12, 2), (13, 2), (18, 2), (26, 3), (24, 3), (41, 3), (23, 3), (60, 4), (44, 4), (61, 4), (49, 4)])" +non_spreading_dirlaynet_minbudget,0.47728039999492466,219,"(4, {0: [13, 19, 67, 173]})" +non_spreading_minbudget,0.02702299994416535,219,"(5, [])" +heuristic_minbudget,0.8602139001013711,219,"(2, [(19, 1), (13, 1), (43, 2), (46, 2), (58, 3), (56, 3), (62, 4), (67, 4), (97, 5), (74, 5), (101, 6), (108, 6), (126, 7), (140, 7)])" +non_spreading_dirlaynet_minbudget,0.11988609994295985,73,"(1, {3: [67]})" +non_spreading_minbudget,0.006057800026610494,73,"(2, [])" +heuristic_minbudget,0.11525369994342327,73,"(1, [(3, 1), (9, 2), (34, 3), (46, 4)])" +non_spreading_dirlaynet_minbudget,0.3718286999501288,178,"(5, {0: [4, 23, 59, 58, 70], 1: [59, 58], 2: [59, 58]})" +non_spreading_minbudget,0.022550499998033047,178,"(9, [])" +heuristic_minbudget,0.8823112000245601,178,"(3, [(4, 1), (23, 1), (8, 1), (52, 2), (53, 2), (29, 2), (59, 3), (54, 3), (60, 3), (61, 4), (68, 4), (70, 4), (76, 5), (77, 5), (78, 5), (102, 6), (99, 6), (97, 6), (118, 7), (127, 7), (113, 7), (142, 8), (150, 8), (155, 8)])" +non_spreading_dirlaynet_minbudget,0.22105910000391304,119,"(2, {0: [42, 64], 1: [109], 2: [103], 3: [103]})" +non_spreading_minbudget,0.013426600024104118,119,"(6, [])" +heuristic_minbudget,0.5361911000218242,119,"(2, [(10, 1), (23, 1), (26, 2), (28, 2), (42, 3), (36, 3), (78, 4), (64, 4), (103, 5), (100, 5)])" +,31.387649700045586,, diff --git a/experiments/firefighter_problem/non_spreading_minbudget.png b/experiments/firefighter_problem/non_spreading_minbudget.png new file mode 100644 index 0000000..8b74f04 Binary files /dev/null and b/experiments/firefighter_problem/non_spreading_minbudget.png differ diff --git a/experiments/firefighter_problem/non_spreading_preprocessed.csv b/experiments/firefighter_problem/non_spreading_preprocessed.csv new file mode 100644 index 0000000..2f04a8c --- /dev/null +++ b/experiments/firefighter_problem/non_spreading_preprocessed.csv @@ -0,0 +1,91 @@ +algorithm,runtime,graph_nodes,Budget,Budget_numeric +non_spreading_dirlaynet_minbudget,0.3383908999385312,140.0,"(4, {0: [2, 12, 97, 130], 2: [87, 110], 3: [97, 110], 4: [110], 5: [110]})",4.0 +non_spreading_minbudget,0.01575249992311,140.0,"(11, [])",11.0 +heuristic_minbudget,0.798951999982819,140.0,"(4, [(2, 1), (12, 1), (10, 1), (6, 1), (34, 2), (30, 2), (33, 2), (37, 2), (48, 3), (47, 3), (42, 3), (40, 3), (60, 4), (53, 4), (59, 4), (67, 4), (87, 5), (69, 5), (75, 5), (77, 5), (97, 6), (99, 6), (95, 6), (98, 6), (102, 7), (110, 7), (107, 7), (105, 7)])",4.0 +non_spreading_dirlaynet_minbudget,0.1723367000231519,110.0,"(9, {0: [7, 25, 17, 39, 31, 55, 66, 84, 91], 1: [39, 31, 55, 66, 91], 2: [55, 91], 4: [91], 5: [91]})",9.0 +non_spreading_minbudget,0.0126618000213056,110.0,"(18, [])",18.0 +heuristic_minbudget,0.7278256000718102,110.0,"(4, [(7, 1), (25, 1), (17, 1), (19, 1), (29, 2), (39, 2), (33, 2), (31, 2), (55, 3), (45, 3), (52, 3), (51, 3), (66, 4), (65, 4), (62, 4), (67, 4), (84, 5), (80, 5), (77, 5), (78, 5)])",4.0 +non_spreading_dirlaynet_minbudget,0.3667914000106975,152.0,"(7, {0: [7, 14, 21, 78, 103, 109, 147], 1: [36], 4: [147]})",7.0 +non_spreading_minbudget,0.0200425999937579,152.0,"(9, [])",9.0 +heuristic_minbudget,1.086715599987656,152.0,"(3, [(21, 1), (7, 1), (14, 1), (36, 2), (43, 2), (45, 2), (78, 3), (62, 3), (71, 3), (82, 4), (83, 4), (88, 4), (103, 5), (101, 5), (97, 5), (109, 6), (126, 6), (131, 6)])",3.0 +non_spreading_dirlaynet_minbudget,0.5028269999893382,208.0,"(24, {0: [7, 14, 17, 23, 24, 9, 16, 1, 5, 22, 6, 15, 4, 13, 8, 18, 11, 21, 20, 10, 3, 12, 19, 2]})",24.0 +non_spreading_minbudget,0.0273078000172972,208.0,"(24, [])",24.0 +heuristic_minbudget,1.8271003999980169,208.0,"(9, [(23, 1), (22, 1), (20, 1), (18, 1), (17, 1), (3, 1), (9, 1), (8, 1), (4, 1), (53, 2), (32, 2), (37, 2), (27, 2), (48, 2), (31, 2), (40, 2), (46, 2), (39, 2), (77, 3), (69, 3), (64, 3), (67, 3), (66, 3), (56, 3), (79, 3), (72, 3), (61, 3), (85, 4), (86, 4), (82, 4), (91, 4), (84, 4), (87, 4), (88, 4), (90, 4), (93, 4), (106, 5), (109, 5), (99, 5), (95, 5), (98, 5), (96, 5), (108, 5), (103, 5), (97, 5), (126, 6), (114, 6), (117, 6), (113, 6), (111, 6), (130, 6), (119, 6), (118, 6), (121, 6), (136, 7), (135, 7), (146, 7), (150, 7), (158, 7), (139, 7), (154, 7), (144, 7), (145, 7), (167, 8), (169, 8), (163, 8), (166, 8), (165, 8), (162, 8), (168, 8), (164, 8)])",9.0 +non_spreading_dirlaynet_minbudget,0.4180444999365136,180.0,"(11, {0: [5, 20, 13, 19, 2, 22, 58, 72, 118, 145, 168], 1: [22, 58, 72, 145, 168], 2: [58, 72, 118]})",11.0 +non_spreading_minbudget,0.0263183999340981,180.0,"(19, [])",19.0 +heuristic_minbudget,1.598106799996458,180.0,"(6, [(13, 1), (19, 1), (20, 1), (5, 1), (2, 1), (17, 1), (21, 2), (22, 2), (33, 2), (35, 2), (38, 2), (40, 2), (72, 3), (58, 3), (69, 3), (73, 3), (50, 3), (74, 3), (92, 4), (94, 4), (93, 4), (96, 4), (89, 4), (81, 4), (102, 5), (118, 5), (100, 5), (101, 5), (108, 5), (119, 5), (126, 6), (128, 6), (124, 6), (125, 6), (129, 6), (123, 6), (136, 7), (134, 7)])",6.0 +non_spreading_dirlaynet_minbudget,0.2731701999437064,139.0,"(9, {0: [24, 25, 10, 5, 39, 38, 31, 40, 36], 1: [39, 38, 31, 40, 36, 45]})",9.0 +non_spreading_minbudget,0.0190937999868765,139.0,"(15, [])",15.0 +heuristic_minbudget,1.0293473000638187,139.0,"(6, [(25, 1), (24, 1), (10, 1), (5, 1), (8, 1), (20, 1), (34, 2), (36, 2), (38, 2), (39, 2), (33, 2), (30, 2), (46, 3), (42, 3), (44, 3), (45, 3), (55, 3), (43, 3), (63, 4), (72, 4), (69, 4), (62, 4), (65, 4), (64, 4), (83, 5), (92, 5), (91, 5), (77, 5), (90, 5), (82, 5), (97, 6), (99, 6), (101, 6), (98, 6), (100, 6), (104, 6), (107, 7), (109, 7), (110, 7)])",6.0 +non_spreading_dirlaynet_minbudget,0.3905019999947399,184.0,"(12, {0: [25, 11, 20, 17, 37, 47, 79, 76, 97, 91, 96, 106], 1: [37, 47, 79, 76, 97, 91, 96, 106], 2: [79, 76, 97, 91, 96], 3: [97, 91, 96]})",12.0 +non_spreading_minbudget,0.037450100062415,184.0,"(24, [])",24.0 +heuristic_minbudget,1.7678336999379098,184.0,"(6, [(17, 1), (25, 1), (11, 1), (20, 1), (2, 1), (13, 1), (43, 2), (47, 2), (37, 2), (50, 2), (33, 2), (57, 2), (82, 3), (77, 3), (79, 3), (76, 3), (59, 3), (70, 3), (88, 4), (92, 4), (97, 4), (87, 4), (94, 4), (86, 4), (111, 5), (113, 5), (109, 5), (114, 5), (125, 5), (122, 5), (140, 6), (138, 6), (135, 6), (141, 6), (129, 6), (127, 6), (151, 7), (152, 7), (144, 7), (150, 7), (162, 7), (142, 7)])",6.0 +non_spreading_dirlaynet_minbudget,0.2643465000437572,116.0,"(9, {0: [4, 2, 8, 1, 5, 6, 3, 9, 32]})",9.0 +non_spreading_minbudget,0.0155671000247821,116.0,"(9, [])",9.0 +heuristic_minbudget,0.3790762999560684,116.0,"(6, [(2, 1), (1, 1), (9, 1), (4, 1), (5, 1), (8, 1), (14, 2), (39, 2), (13, 2), (24, 2), (31, 2), (19, 2), (44, 3), (61, 3), (55, 3), (42, 3), (60, 3), (48, 3), (69, 4), (76, 4), (72, 4), (62, 4), (73, 4), (64, 4)])",6.0 +non_spreading_dirlaynet_minbudget,0.2703150999732315,146.0,"(3, {0: [23, 29, 97], 1: [105], 2: [55, 97], 3: [97], 4: [97]})",3.0 +non_spreading_minbudget,0.0159156000008806,146.0,"(9, [])",9.0 +heuristic_minbudget,0.8679373000049964,146.0,"(2, [(23, 1), (1, 1), (29, 2), (31, 2), (55, 3), (58, 3), (60, 4), (63, 4), (88, 5), (93, 5), (98, 6), (101, 6), (106, 7), (109, 7), (116, 8), (120, 8)])",2.0 +non_spreading_dirlaynet_minbudget,0.1894282000139355,99.0,"(7, {0: [7, 13, 11, 17, 49, 68, 98], 1: [49, 68, 98], 2: [49, 68, 98]})",7.0 +non_spreading_minbudget,0.0121530999895185,99.0,"(13, [])",13.0 +heuristic_minbudget,0.6063708999427035,99.0,"(4, [(7, 1), (13, 1), (17, 1), (11, 1), (24, 2), (41, 2), (39, 2), (21, 2), (48, 3), (50, 3), (49, 3), (55, 3), (68, 4), (85, 4), (71, 4), (64, 4)])",4.0 +non_spreading_dirlaynet_minbudget,0.1244647999992594,82.0,"(7, {0: [24, 1, 20, 3, 19, 53, 58], 1: [58], 2: [58], 3: [58]})",7.0 +non_spreading_minbudget,0.0074720999691635,82.0,"(10, [])",10.0 +heuristic_minbudget,0.5537956999614835,82.0,"(5, [(1, 1), (24, 1), (3, 1), (19, 1), (20, 1), (34, 2), (28, 2), (32, 2), (30, 2), (33, 2), (37, 3), (38, 3)])",5.0 +non_spreading_dirlaynet_minbudget,0.1741301999427378,107.0,"(12, {0: [7, 4, 2, 8, 10, 11, 9, 1, 6, 3, 12, 5]})",12.0 +non_spreading_minbudget,0.0106131999054923,107.0,"(12, [])",12.0 +heuristic_minbudget,0.7465448000002652,107.0,"(8, [(6, 1), (12, 1), (1, 1), (11, 1), (3, 1), (7, 1), (10, 1), (5, 1), (23, 2), (16, 2), (28, 2), (15, 2), (18, 2), (26, 2), (22, 2), (24, 2), (41, 3), (36, 3), (38, 3), (49, 3), (46, 3), (32, 3), (47, 3), (44, 3), (63, 4), (54, 4), (58, 4), (64, 4), (62, 4), (53, 4), (61, 4), (60, 4), (69, 5), (75, 5), (67, 5), (79, 5), (80, 5), (78, 5), (74, 5), (82, 5), (84, 6), (85, 6), (86, 6), (87, 6)])",8.0 +non_spreading_dirlaynet_minbudget,0.2534403000026941,134.0,"(20, {0: [7, 14, 17, 9, 16, 1, 5, 6, 15, 4, 8, 18, 11, 20, 10, 3, 12, 19, 2, 40]})",20.0 +non_spreading_minbudget,0.0845846000593155,134.0,"(20, [])",20.0 +heuristic_minbudget,0.6117942000273615,134.0,"(5, [(20, 1), (8, 1), (4, 1), (17, 1), (6, 1), (49, 2), (30, 2), (40, 2), (42, 2), (44, 2), (61, 3), (55, 3), (53, 3), (57, 3), (56, 3), (65, 4), (71, 4), (64, 4), (66, 4), (63, 4), (77, 5), (85, 5), (90, 5), (78, 5), (91, 5), (97, 6), (101, 6), (103, 6), (107, 6), (93, 6), (117, 7), (116, 7), (109, 7), (110, 7), (111, 7)])",5.0 +non_spreading_dirlaynet_minbudget,0.1707683000713586,90.0,"(8, {0: [6, 1, 5, 30, 18, 43, 45, 64], 1: [30, 18, 43, 45, 64], 2: [43, 45, 64], 3: [64]})",8.0 +non_spreading_minbudget,0.0113423001021146,90.0,"(14, [])",14.0 +heuristic_minbudget,0.5426640999503434,90.0,"(4, [(6, 1), (1, 1), (5, 1), (4, 1), (30, 2), (18, 2), (29, 2), (37, 2), (52, 3), (45, 3), (43, 3), (48, 3), (73, 4), (64, 4), (66, 4), (80, 4)])",4.0 +non_spreading_dirlaynet_minbudget,0.1948924000607803,112.0,"(9, {0: [7, 4, 2, 8, 1, 5, 6, 3, 9]})",9.0 +non_spreading_minbudget,0.0114870000397786,112.0,"(9, [])",9.0 +heuristic_minbudget,0.4493562000570819,112.0,"(4, [(9, 1), (5, 1), (3, 1), (6, 1), (24, 2), (19, 2), (10, 2), (13, 2), (28, 3), (37, 3), (41, 3), (26, 3), (58, 4), (66, 4), (47, 4), (60, 4), (74, 5), (79, 5), (76, 5), (83, 5), (89, 6), (88, 6), (85, 6), (87, 6), (91, 7), (92, 7), (95, 7), (98, 7)])",4.0 +non_spreading_dirlaynet_minbudget,0.3376789001049474,148.0,"(11, {0: [7, 4, 8, 6, 11, 9, 1, 5, 10, 3, 2]})",11.0 +non_spreading_minbudget,0.0214755999622866,148.0,"(11, [])",11.0 +heuristic_minbudget,0.899608499952592,148.0,"(4, [(2, 1), (5, 1), (6, 1), (7, 1), (26, 2), (21, 2), (32, 2), (20, 2), (49, 3), (41, 3), (52, 3), (42, 3), (66, 4), (65, 4), (74, 4), (72, 4), (102, 5), (107, 5), (109, 5), (92, 5), (115, 6), (129, 6), (132, 6), (117, 6)])",4.0 +non_spreading_dirlaynet_minbudget,0.1692504999227821,108.0,"(9, {0: [7, 4, 2, 8, 1, 5, 6, 3, 9]})",9.0 +non_spreading_minbudget,0.0101746000582352,108.0,"(9, [])",9.0 +heuristic_minbudget,0.3710829999763518,108.0,"(6, [(6, 1), (1, 1), (4, 1), (9, 1), (8, 1), (7, 1), (12, 2), (16, 2), (13, 2), (22, 2), (15, 2), (20, 2), (30, 3), (31, 3), (24, 3), (33, 3), (32, 3), (27, 3), (40, 4), (43, 4), (42, 4), (39, 4), (38, 4), (37, 4), (46, 5), (44, 5), (48, 5), (61, 5), (68, 5), (58, 5), (74, 6), (75, 6), (71, 6), (69, 6), (73, 6), (76, 6)])",6.0 +non_spreading_dirlaynet_minbudget,0.1709927000338211,91.0,"(15, {0: [7, 4, 2, 13, 14, 8, 10, 11, 9, 6, 3, 12, 15, 5, 23]})",15.0 +non_spreading_minbudget,0.010515599977225,91.0,"(15, [])",15.0 +heuristic_minbudget,0.5208220999920741,91.0,"(6, [(4, 1), (13, 1), (6, 1), (10, 1), (14, 1), (2, 1), (22, 2), (31, 2), (27, 2), (23, 2), (29, 2), (28, 2), (34, 3), (48, 3), (39, 3), (44, 3), (51, 3), (33, 3), (55, 4), (71, 4), (64, 4), (61, 4), (67, 4), (59, 4)])",6.0 +non_spreading_dirlaynet_minbudget,0.1515862999949604,85.0,"(7, {0: [8, 20, 6, 27, 35, 46, 69], 1: [69]})",7.0 +non_spreading_minbudget,0.0081389000406488,85.0,"(8, [])",8.0 +heuristic_minbudget,0.3552039999049157,85.0,"(3, [(8, 1), (20, 1), (6, 1), (27, 2), (26, 2), (29, 2), (38, 3), (42, 3), (32, 3), (46, 4), (45, 4), (49, 4)])",3.0 +non_spreading_dirlaynet_minbudget,0.2213223000289872,127.0,"(8, {0: [7, 4, 8, 1, 5, 6, 3, 2]})",8.0 +non_spreading_minbudget,0.0165456000249832,127.0,"(8, [])",8.0 +heuristic_minbudget,0.5257905001053587,127.0,"(6, [(6, 1), (1, 1), (5, 1), (2, 1), (4, 1), (7, 1), (28, 2), (11, 2), (27, 2), (14, 2), (29, 2), (12, 2), (41, 3), (43, 3), (46, 3), (48, 3), (42, 3), (40, 3), (67, 4), (71, 4), (56, 4), (49, 4), (62, 4), (69, 4), (73, 5), (75, 5), (91, 5), (83, 5), (81, 5), (80, 5), (98, 6), (101, 6), (94, 6), (99, 6), (92, 6), (95, 6)])",6.0 +non_spreading_dirlaynet_minbudget,0.2360579000087455,129.0,"(7, {0: [7, 4, 1, 5, 6, 3, 2]})",7.0 +non_spreading_minbudget,0.0158876000205054,129.0,"(7, [])",7.0 +heuristic_minbudget,0.2970746000064537,129.0,"(3, [(5, 1), (2, 1), (7, 1), (16, 2), (8, 2), (13, 2), (27, 3), (24, 3), (22, 3), (28, 4), (29, 4), (32, 4), (43, 5), (45, 5), (38, 5), (52, 6), (53, 6), (56, 6), (64, 7), (62, 7), (69, 7), (83, 8), (93, 8), (98, 8)])",3.0 +non_spreading_dirlaynet_minbudget,0.3081332999281585,149.0,"(22, {0: [7, 14, 17, 9, 16, 1, 5, 22, 6, 15, 4, 13, 8, 18, 11, 21, 20, 10, 3, 12, 19, 2]})",22.0 +non_spreading_minbudget,0.0202572999987751,149.0,"(22, [])",22.0 +heuristic_minbudget,0.8213011999614537,149.0,"(9, [(18, 1), (16, 1), (19, 1), (11, 1), (14, 1), (17, 1), (13, 1), (10, 1), (5, 1), (47, 2), (35, 2), (28, 2), (43, 2), (34, 2), (46, 2), (45, 2), (32, 2), (39, 2), (56, 3), (71, 3), (54, 3), (57, 3), (67, 3), (53, 3), (55, 3), (68, 3), (72, 3), (80, 4), (76, 4), (74, 4), (79, 4), (78, 4), (77, 4), (75, 4)])",9.0 +non_spreading_dirlaynet_minbudget,0.2104516000254079,110.0,"(5, {0: [14, 43, 24, 45, 102], 1: [43, 24, 102]})",5.0 +non_spreading_minbudget,0.012047900003381,110.0,"(8, [])",8.0 +heuristic_minbudget,0.7300266999518499,110.0,"(4, [(14, 1), (19, 1), (15, 1), (12, 1), (44, 2), (27, 2), (24, 2), (43, 2), (45, 3), (52, 3), (56, 3), (49, 3), (71, 4), (73, 4), (61, 4), (70, 4), (80, 5), (77, 5), (81, 5), (86, 5)])",4.0 +non_spreading_dirlaynet_minbudget,0.2778458000393584,138.0,"(6, {0: [7, 15, 9, 39, 49, 51], 1: [39, 49, 51], 2: [49, 51]})",6.0 +non_spreading_minbudget,0.0200290000066161,138.0,"(11, [])",11.0 +heuristic_minbudget,0.8300812999950722,138.0,"(5, [(9, 1), (15, 1), (7, 1), (18, 1), (1, 1), (39, 2), (48, 2), (28, 2), (31, 2), (36, 2), (53, 3), (51, 3), (52, 3), (49, 3), (50, 3), (70, 4), (64, 4)])",5.0 +non_spreading_dirlaynet_minbudget,0.3144082999788224,163.0,"(6, {0: [23, 20, 39, 43, 51, 50], 1: [39, 43, 51, 50], 2: [51, 50]})",6.0 +non_spreading_minbudget,0.0173705000197514,163.0,"(10, [])",10.0 +heuristic_minbudget,0.8383238000096753,163.0,"(4, [(23, 1), (20, 1), (7, 1), (22, 1), (39, 2), (26, 2), (43, 2), (27, 2), (51, 3), (52, 3), (50, 3), (53, 3), (67, 4), (78, 4), (77, 4), (69, 4), (87, 5), (93, 5), (80, 5), (97, 5), (122, 6), (115, 6), (116, 6), (121, 6), (125, 7), (123, 7), (126, 7), (127, 7)])",4.0 +non_spreading_dirlaynet_minbudget,0.2348050998989492,93.0,"(10, {0: [7, 4, 8, 6, 11, 5, 10, 3, 2, 32]})",10.0 +non_spreading_minbudget,0.0094449999742209,93.0,"(11, [])",11.0 +heuristic_minbudget,0.255635300069116,93.0,"(4, [(10, 1), (5, 1), (11, 1), (8, 1), (17, 2), (12, 2), (13, 2), (18, 2), (26, 3), (24, 3), (41, 3), (23, 3), (60, 4), (44, 4), (61, 4), (49, 4)])",4.0 +non_spreading_dirlaynet_minbudget,0.4772803999949246,219.0,"(4, {0: [13, 19, 67, 173]})",4.0 +non_spreading_minbudget,0.0270229999441653,219.0,"(5, [])",5.0 +heuristic_minbudget,0.8602139001013711,219.0,"(2, [(19, 1), (13, 1), (43, 2), (46, 2), (58, 3), (56, 3), (62, 4), (67, 4), (97, 5), (74, 5), (101, 6), (108, 6), (126, 7), (140, 7)])",2.0 +non_spreading_dirlaynet_minbudget,0.1198860999429598,73.0,"(1, {3: [67]})",1.0 +non_spreading_minbudget,0.0060578000266104,73.0,"(2, [])",2.0 +heuristic_minbudget,0.1152536999434232,73.0,"(1, [(3, 1), (9, 2), (34, 3), (46, 4)])",1.0 +non_spreading_dirlaynet_minbudget,0.3718286999501288,178.0,"(5, {0: [4, 23, 59, 58, 70], 1: [59, 58], 2: [59, 58]})",5.0 +non_spreading_minbudget,0.022550499998033,178.0,"(9, [])",9.0 +heuristic_minbudget,0.8823112000245601,178.0,"(3, [(4, 1), (23, 1), (8, 1), (52, 2), (53, 2), (29, 2), (59, 3), (54, 3), (60, 3), (61, 4), (68, 4), (70, 4), (76, 5), (77, 5), (78, 5), (102, 6), (99, 6), (97, 6), (118, 7), (127, 7), (113, 7), (142, 8), (150, 8), (155, 8)])",3.0 +non_spreading_dirlaynet_minbudget,0.221059100003913,119.0,"(2, {0: [42, 64], 1: [109], 2: [103], 3: [103]})",2.0 +non_spreading_minbudget,0.0134266000241041,119.0,"(6, [])",6.0 +heuristic_minbudget,0.5361911000218242,119.0,"(2, [(10, 1), (23, 1), (26, 2), (28, 2), (42, 3), (36, 3), (78, 4), (64, 4), (103, 5), (100, 5)])",2.0 diff --git a/experiments/firefighter_problem/spreading_maxsave.csv b/experiments/firefighter_problem/spreading_maxsave.csv new file mode 100644 index 0000000..402ba53 --- /dev/null +++ b/experiments/firefighter_problem/spreading_maxsave.csv @@ -0,0 +1,1082 @@ +algorithm,runtime,Budget,graph_nodes,edge_probability,Nodes_Saved +spreading_maxsave,0.08716789999743924,1,100,0.1,17 +heuristic_maxsave,0.032615200034342706,1,100,0.1,17 +spreading_maxsave,0.08247730002040043,2,100,0.1,24 +heuristic_maxsave,0.03249310003593564,2,100,0.1,25 +spreading_maxsave,0.26054399996064603,3,100,0.1,31 +heuristic_maxsave,0.03926589997718111,3,100,0.1,31 +spreading_maxsave,0.13694779999786988,5,100,0.1,42 +heuristic_maxsave,0.11109409999335185,5,100,0.1,40 +spreading_maxsave,0.16288850002456456,7,100,0.1,44 +heuristic_maxsave,0.05416710005374625,7,100,0.1,46 +spreading_maxsave,0.20015620003687218,10,100,0.1,47 +heuristic_maxsave,0.04395620001014322,10,100,0.1,48 +spreading_maxsave,0.05649819999234751,1,100,0.1,5 +heuristic_maxsave,0.029464400024153292,1,100,0.1,5 +spreading_maxsave,0.07986429997254163,2,100,0.1,5 +heuristic_maxsave,0.03359050001017749,2,100,0.1,5 +spreading_maxsave,0.098236599995289,3,100,0.1,5 +heuristic_maxsave,0.08675860002404079,3,100,0.1,5 +spreading_maxsave,0.13702339999144897,5,100,0.1,5 +heuristic_maxsave,0.0499644999508746,5,100,0.1,5 +spreading_maxsave,0.15495280001778156,7,100,0.1,5 +heuristic_maxsave,0.04423040000256151,7,100,0.1,5 +spreading_maxsave,0.1916928999708034,10,100,0.1,5 +heuristic_maxsave,0.04138439998496324,10,100,0.1,5 +spreading_maxsave,0.06430410000029951,1,100,0.1,9 +heuristic_maxsave,0.025437000032979995,1,100,0.1,6 +spreading_maxsave,0.13984530000016093,2,100,0.1,12 +heuristic_maxsave,0.03264219994889572,2,100,0.1,9 +spreading_maxsave,0.10051050002221018,3,100,0.1,12 +heuristic_maxsave,0.038937399978749454,3,100,0.1,12 +spreading_maxsave,0.13558080000802875,5,100,0.1,13 +heuristic_maxsave,0.05305609997594729,5,100,0.1,16 +spreading_maxsave,0.24316899996483698,7,100,0.1,15 +heuristic_maxsave,0.06414859998039901,7,100,0.1,17 +spreading_maxsave,0.23131400003330782,10,100,0.1,17 +heuristic_maxsave,0.06319100002292544,10,100,0.1,17 +spreading_maxsave,0.05988299997989088,1,100,0.1,6 +heuristic_maxsave,0.02577399997971952,1,100,0.1,6 +spreading_maxsave,0.07544829999096692,2,100,0.1,9 +heuristic_maxsave,0.03426980000222102,2,100,0.1,9 +spreading_maxsave,0.09296229999745265,3,100,0.1,9 +heuristic_maxsave,0.12324909999733791,3,100,0.1,9 +spreading_maxsave,0.14677549997577444,5,100,0.1,9 +heuristic_maxsave,0.0495435000048019,5,100,0.1,9 +spreading_maxsave,0.1772472999873571,7,100,0.1,9 +heuristic_maxsave,0.055875000020023435,7,100,0.1,9 +spreading_maxsave,0.2268023999640718,10,100,0.1,9 +heuristic_maxsave,0.05596740002511069,10,100,0.1,9 +spreading_maxsave,0.06244779995176941,1,100,0.1,15 +heuristic_maxsave,0.025558800029102713,1,100,0.1,15 +spreading_maxsave,0.14300390001153573,2,100,0.1,22 +heuristic_maxsave,0.04185989999677986,2,100,0.1,20 +spreading_maxsave,0.14189980004448444,3,100,0.1,28 +heuristic_maxsave,0.07025290001183748,3,100,0.1,25 +spreading_maxsave,0.19750859995838255,5,100,0.1,33 +heuristic_maxsave,0.048199000011663884,5,100,0.1,32 +spreading_maxsave,0.23970649996772408,7,100,0.1,35 +heuristic_maxsave,0.07180949999019504,7,100,0.1,38 +spreading_maxsave,0.3098434999701567,10,100,0.1,38 +heuristic_maxsave,0.04116299998713657,10,100,0.1,39 +spreading_maxsave,0.06702149996999651,1,100,0.1,8 +heuristic_maxsave,0.024725899973418564,1,100,0.1,7 +spreading_maxsave,0.07488119998015463,2,100,0.1,12 +heuristic_maxsave,0.03541030001360923,2,100,0.1,9 +spreading_maxsave,0.10977509996155277,3,100,0.1,12 +heuristic_maxsave,0.03487839997978881,3,100,0.1,13 +spreading_maxsave,0.14335279999068007,5,100,0.1,13 +heuristic_maxsave,0.04845410003326833,5,100,0.1,13 +spreading_maxsave,0.22635160002391785,7,100,0.1,13 +heuristic_maxsave,0.04644229996483773,7,100,0.1,13 +spreading_maxsave,0.19589239999186248,10,100,0.1,13 +heuristic_maxsave,0.04726169997593388,10,100,0.1,13 +spreading_maxsave,0.05790449999039993,1,100,0.1,18 +heuristic_maxsave,0.023330500000156462,1,100,0.1,16 +spreading_maxsave,0.09364779997849837,2,100,0.1,26 +heuristic_maxsave,0.03607450000708923,2,100,0.1,24 +spreading_maxsave,0.11407450004480779,3,100,0.1,33 +heuristic_maxsave,0.038080800033640116,3,100,0.1,30 +spreading_maxsave,0.2105161999934353,5,100,0.1,42 +heuristic_maxsave,0.11549989995546639,5,100,0.1,40 +spreading_maxsave,0.23027239996008575,7,100,0.1,45 +heuristic_maxsave,0.051699900010135025,7,100,0.1,46 +spreading_maxsave,0.30371230002492666,10,100,0.1,47 +heuristic_maxsave,0.06799489998957142,10,100,0.1,50 +spreading_maxsave,0.06436839996604249,1,100,0.1,4 +heuristic_maxsave,0.027392900025006384,1,100,0.1,4 +spreading_maxsave,0.07906960003310814,2,100,0.1,6 +heuristic_maxsave,0.03214169997954741,2,100,0.1,6 +spreading_maxsave,0.10434780002105981,3,100,0.1,6 +heuristic_maxsave,0.10287839994998649,3,100,0.1,6 +spreading_maxsave,0.18564270000206307,5,100,0.1,6 +heuristic_maxsave,0.046756000025197864,5,100,0.1,6 +spreading_maxsave,0.19580169999971986,7,100,0.1,6 +heuristic_maxsave,0.05795609997585416,7,100,0.1,6 +spreading_maxsave,0.24842509999871254,10,100,0.1,6 +heuristic_maxsave,0.053634700016118586,10,100,0.1,6 +spreading_maxsave,0.0823748999973759,1,100,0.1,11 +heuristic_maxsave,0.03845659998478368,1,100,0.1,10 +spreading_maxsave,0.09743260004324839,2,100,0.1,17 +heuristic_maxsave,0.039166799979284406,2,100,0.1,15 +spreading_maxsave,0.1427152000251226,3,100,0.1,22 +heuristic_maxsave,0.04553379997378215,3,100,0.1,19 +spreading_maxsave,0.1616103000123985,5,100,0.1,28 +heuristic_maxsave,0.1175424000248313,5,100,0.1,28 +spreading_maxsave,0.158801699988544,7,100,0.1,28 +heuristic_maxsave,0.047847700014244765,7,100,0.1,31 +spreading_maxsave,0.20470469997962937,10,100,0.1,31 +heuristic_maxsave,0.03717609995510429,10,100,0.1,31 +spreading_maxsave,0.0614874999737367,1,100,0.1,13 +heuristic_maxsave,0.025471200002357364,1,100,0.1,12 +spreading_maxsave,0.09362950001377612,2,100,0.1,17 +heuristic_maxsave,0.031568000034894794,2,100,0.1,16 +spreading_maxsave,0.15379599999869242,3,100,0.1,21 +heuristic_maxsave,0.038320899999234825,3,100,0.1,19 +spreading_maxsave,0.14088149997405708,5,100,0.1,22 +heuristic_maxsave,0.04945940000470728,5,100,0.1,24 +spreading_maxsave,0.1497899999958463,7,100,0.1,24 +heuristic_maxsave,0.0549229999887757,7,100,0.1,28 +spreading_maxsave,0.18971940001938492,10,100,0.1,27 +heuristic_maxsave,0.11680079996585846,10,100,0.1,29 +spreading_maxsave,0.09479150001425296,1,100,0.5,17 +heuristic_maxsave,0.03854199999477714,1,100,0.5,17 +spreading_maxsave,0.06843059998936951,2,100,0.5,22 +heuristic_maxsave,0.056115000043064356,2,100,0.5,23 +spreading_maxsave,0.08718600001884624,3,100,0.5,23 +heuristic_maxsave,0.046098000020720065,3,100,0.5,24 +spreading_maxsave,0.12304549996042624,5,100,0.5,25 +heuristic_maxsave,0.06793620000826195,5,100,0.5,26 +spreading_maxsave,0.13412550004431978,7,100,0.5,27 +heuristic_maxsave,0.14189939998323098,7,100,0.5,28 +spreading_maxsave,0.16360910004004836,10,100,0.5,30 +heuristic_maxsave,0.13868380000349134,10,100,0.5,31 +spreading_maxsave,0.04747380001936108,1,100,0.5,4 +heuristic_maxsave,0.024995500047225505,1,100,0.5,5 +spreading_maxsave,0.060543700004927814,2,100,0.5,5 +heuristic_maxsave,0.03978089999873191,2,100,0.5,6 +spreading_maxsave,0.09406159998616204,3,100,0.5,6 +heuristic_maxsave,0.045352499990258366,3,100,0.5,7 +spreading_maxsave,0.1553810999612324,5,100,0.5,8 +heuristic_maxsave,0.08766020002076402,5,100,0.5,8 +spreading_maxsave,0.12187080003786832,7,100,0.5,8 +heuristic_maxsave,0.0768394999904558,7,100,0.5,8 +spreading_maxsave,0.16662909998558462,10,100,0.5,8 +heuristic_maxsave,0.10883009998360649,10,100,0.5,8 +spreading_maxsave,0.059583399968687445,1,100,0.5,14 +heuristic_maxsave,0.03534970001783222,1,100,0.5,12 +spreading_maxsave,0.0718957000062801,2,100,0.5,18 +heuristic_maxsave,0.09262369998032227,2,100,0.5,18 +spreading_maxsave,0.12327189999632537,3,100,0.5,19 +heuristic_maxsave,0.05665320000844076,3,100,0.5,19 +spreading_maxsave,0.11424119997536764,5,100,0.5,21 +heuristic_maxsave,0.07066810003016144,5,100,0.5,21 +spreading_maxsave,0.13711609999882057,7,100,0.5,23 +heuristic_maxsave,0.0789570999913849,7,100,0.5,23 +spreading_maxsave,0.16975489998003468,10,100,0.5,26 +heuristic_maxsave,0.22815019998233765,10,100,0.5,26 +spreading_maxsave,0.04996400000527501,1,100,0.5,1 +heuristic_maxsave,0.030396000016480684,1,100,0.5,1 +spreading_maxsave,0.0949655000003986,2,100,0.5,2 +heuristic_maxsave,0.05807430000277236,2,100,0.5,2 +spreading_maxsave,0.07740580005338416,3,100,0.5,2 +heuristic_maxsave,0.04553000000305474,3,100,0.5,2 +spreading_maxsave,0.09961149998707697,5,100,0.5,2 +heuristic_maxsave,0.061857599997892976,5,100,0.5,2 +spreading_maxsave,0.20101849996717647,7,100,0.5,2 +heuristic_maxsave,0.13328330003423616,7,100,0.5,2 +spreading_maxsave,0.14695280004525557,10,100,0.5,2 +heuristic_maxsave,0.14934820000780746,10,100,0.5,2 +spreading_maxsave,0.06408270000247285,1,100,0.5,2 +heuristic_maxsave,0.03090619994327426,1,100,0.5,2 +spreading_maxsave,0.06072920002043247,2,100,0.5,3 +heuristic_maxsave,0.04085530003067106,2,100,0.5,3 +spreading_maxsave,0.07987610000418499,3,100,0.5,4 +heuristic_maxsave,0.11530750000383705,3,100,0.5,4 +spreading_maxsave,0.1165616000071168,5,100,0.5,5 +heuristic_maxsave,0.07545659999595955,5,100,0.5,5 +spreading_maxsave,0.13026910001644865,7,100,0.5,5 +heuristic_maxsave,0.08308420004323125,7,100,0.5,5 +spreading_maxsave,0.17481900000711903,10,100,0.5,5 +heuristic_maxsave,0.11439170001540333,10,100,0.5,5 +spreading_maxsave,0.053254199970979244,1,100,0.5,8 +heuristic_maxsave,0.030037300020921975,1,100,0.5,7 +spreading_maxsave,0.18127270002150908,2,100,0.5,9 +heuristic_maxsave,0.043439799977932125,2,100,0.5,9 +spreading_maxsave,0.09930640005040914,3,100,0.5,10 +heuristic_maxsave,0.07558389997575432,3,100,0.5,10 +spreading_maxsave,0.131768099963665,5,100,0.5,12 +heuristic_maxsave,0.06539930001599714,5,100,0.5,12 +spreading_maxsave,0.17641499999444932,7,100,0.5,14 +heuristic_maxsave,0.07780010002898052,7,100,0.5,14 +spreading_maxsave,0.28020009997999296,10,100,0.5,17 +heuristic_maxsave,0.11573760001920164,10,100,0.5,17 +spreading_maxsave,0.0787331000319682,1,100,0.5,7 +heuristic_maxsave,0.03256530000362545,1,100,0.5,7 +spreading_maxsave,0.07973589998437092,2,100,0.5,8 +heuristic_maxsave,0.04320840002037585,2,100,0.5,8 +spreading_maxsave,0.09341140004107729,3,100,0.5,9 +heuristic_maxsave,0.047693600005004555,3,100,0.5,9 +spreading_maxsave,0.10900880000554025,5,100,0.5,11 +heuristic_maxsave,0.06947390001732856,5,100,0.5,11 +spreading_maxsave,0.231234900013078,7,100,0.5,13 +heuristic_maxsave,0.12337139999726787,7,100,0.5,13 +spreading_maxsave,0.21824889996787533,10,100,0.5,13 +heuristic_maxsave,0.1412754000048153,10,100,0.5,13 +spreading_maxsave,0.06140519998734817,1,100,0.5,13 +heuristic_maxsave,0.0317409000126645,1,100,0.5,12 +spreading_maxsave,0.07061729999259114,2,100,0.5,16 +heuristic_maxsave,0.05003659997601062,2,100,0.5,17 +spreading_maxsave,0.08936240000184625,3,100,0.5,17 +heuristic_maxsave,0.054045299999415874,3,100,0.5,18 +spreading_maxsave,0.10788199998205528,5,100,0.5,19 +heuristic_maxsave,0.0894793999614194,5,100,0.5,20 +spreading_maxsave,0.14069249999010935,7,100,0.5,21 +heuristic_maxsave,0.08168610004941002,7,100,0.5,22 +spreading_maxsave,0.1994573000119999,10,100,0.5,24 +heuristic_maxsave,0.10976110002957284,10,100,0.5,25 +spreading_maxsave,0.06902890000492334,1,100,0.5,11 +heuristic_maxsave,0.03937189996941015,1,100,0.5,8 +spreading_maxsave,0.13829259999329224,2,100,0.5,14 +heuristic_maxsave,0.05026679998263717,2,100,0.5,15 +spreading_maxsave,0.08129939995706081,3,100,0.5,15 +heuristic_maxsave,0.057537199987564236,3,100,0.5,16 +spreading_maxsave,0.10051939997356385,5,100,0.5,17 +heuristic_maxsave,0.08894329995382577,5,100,0.5,18 +spreading_maxsave,0.1377288000076078,7,100,0.5,19 +heuristic_maxsave,0.0985215000109747,7,100,0.5,20 +spreading_maxsave,0.16376710002077743,10,100,0.5,22 +heuristic_maxsave,0.1098399999900721,10,100,0.5,23 +spreading_maxsave,0.07671419996768236,1,100,0.5,15 +heuristic_maxsave,0.03729390003718436,1,100,0.5,12 +spreading_maxsave,0.08707070001401007,2,100,0.5,18 +heuristic_maxsave,0.04316840000683442,2,100,0.5,19 +spreading_maxsave,0.0838279000017792,3,100,0.5,19 +heuristic_maxsave,0.05051539995474741,3,100,0.5,20 +spreading_maxsave,0.12549870001384988,5,100,0.5,21 +heuristic_maxsave,0.07244850002462044,5,100,0.5,22 +spreading_maxsave,0.1322290999814868,7,100,0.5,23 +heuristic_maxsave,0.14117989997612312,7,100,0.5,24 +spreading_maxsave,0.17085270001553,10,100,0.5,26 +heuristic_maxsave,0.1138308999943547,10,100,0.5,27 +spreading_maxsave,0.057962299964856356,1,100,0.8,8 +heuristic_maxsave,0.038476700021419674,1,100,0.8,8 +spreading_maxsave,0.06073510000715032,2,100,0.8,9 +heuristic_maxsave,0.04421990003902465,2,100,0.8,9 +spreading_maxsave,0.08853129995986819,3,100,0.8,10 +heuristic_maxsave,0.058759699983056635,3,100,0.8,10 +spreading_maxsave,0.10563980002189055,5,100,0.8,12 +heuristic_maxsave,0.17846879997523502,5,100,0.8,12 +spreading_maxsave,0.12380929995561019,7,100,0.8,14 +heuristic_maxsave,0.14281440002378076,7,100,0.8,14 +spreading_maxsave,0.1712345000123605,10,100,0.8,17 +heuristic_maxsave,0.18017519998829812,10,100,0.8,17 +spreading_maxsave,0.05870429996866733,1,100,0.8,7 +heuristic_maxsave,0.10255260003032163,1,100,0.8,7 +spreading_maxsave,0.06098569999448955,2,100,0.8,8 +heuristic_maxsave,0.05184699996607378,2,100,0.8,8 +spreading_maxsave,0.08204619999742135,3,100,0.8,9 +heuristic_maxsave,0.05927759996848181,3,100,0.8,9 +spreading_maxsave,0.10843790002400056,5,100,0.8,11 +heuristic_maxsave,0.08330570004181936,5,100,0.8,11 +spreading_maxsave,0.160705299989786,7,100,0.8,13 +heuristic_maxsave,0.11555729998508468,7,100,0.8,13 +spreading_maxsave,0.2277369000366889,10,100,0.8,16 +heuristic_maxsave,0.18807889998424798,10,100,0.8,16 +spreading_maxsave,0.060908199986442924,1,100,0.8,8 +heuristic_maxsave,0.045143900031689554,1,100,0.8,8 +spreading_maxsave,0.07495749997906387,2,100,0.8,9 +heuristic_maxsave,0.04526739998254925,2,100,0.8,9 +spreading_maxsave,0.07173000002512708,3,100,0.8,10 +heuristic_maxsave,0.09854169999016449,3,100,0.8,10 +spreading_maxsave,0.17520759999752045,5,100,0.8,12 +heuristic_maxsave,0.09582380001666024,5,100,0.8,12 +spreading_maxsave,0.13287800003308803,7,100,0.8,14 +heuristic_maxsave,0.12190960004227236,7,100,0.8,14 +spreading_maxsave,0.16030280000995845,10,100,0.8,17 +heuristic_maxsave,0.18633640004554763,10,100,0.8,17 +spreading_maxsave,0.04623219999484718,1,100,0.8,2 +heuristic_maxsave,0.0976912000332959,1,100,0.8,2 +spreading_maxsave,0.09053509996738285,2,100,0.8,3 +heuristic_maxsave,0.03963150002527982,2,100,0.8,3 +spreading_maxsave,0.06955489999381825,3,100,0.8,4 +heuristic_maxsave,0.0606514000101015,3,100,0.8,4 +spreading_maxsave,0.10245830001076683,5,100,0.8,6 +heuristic_maxsave,0.08290430001216009,5,100,0.8,6 +spreading_maxsave,0.12540369998896495,7,100,0.8,6 +heuristic_maxsave,0.16698340000584722,7,100,0.8,6 +spreading_maxsave,0.21991829999024048,10,100,0.8,6 +heuristic_maxsave,0.17120710003655404,10,100,0.8,6 +spreading_maxsave,0.0515482000191696,1,100,0.8,6 +heuristic_maxsave,0.030151299957651645,1,100,0.8,6 +spreading_maxsave,0.06041730003198609,2,100,0.8,7 +heuristic_maxsave,0.054642200004309416,2,100,0.8,7 +spreading_maxsave,0.09184649999951944,3,100,0.8,8 +heuristic_maxsave,0.060165799979586154,3,100,0.8,8 +spreading_maxsave,0.10587359999772161,5,100,0.8,10 +heuristic_maxsave,0.17415470001287758,5,100,0.8,10 +spreading_maxsave,0.1395321000018157,7,100,0.8,10 +heuristic_maxsave,0.1222694999887608,7,100,0.8,10 +spreading_maxsave,0.16090030001942068,10,100,0.8,10 +heuristic_maxsave,0.1723226999747567,10,100,0.8,10 +spreading_maxsave,0.05072229995857924,1,100,0.8,7 +heuristic_maxsave,0.035963899979833513,1,100,0.8,7 +spreading_maxsave,0.13861879997421056,2,100,0.8,8 +heuristic_maxsave,0.06461070000659674,2,100,0.8,8 +spreading_maxsave,0.09300130000337958,3,100,0.8,9 +heuristic_maxsave,0.05903629999374971,3,100,0.8,9 +spreading_maxsave,0.11417489999439567,5,100,0.8,11 +heuristic_maxsave,0.11661790002835914,5,100,0.8,11 +spreading_maxsave,0.13005350000457838,7,100,0.8,13 +heuristic_maxsave,0.1189691000035964,7,100,0.8,13 +spreading_maxsave,0.23720289999619126,10,100,0.8,16 +heuristic_maxsave,0.1895428000134416,10,100,0.8,16 +spreading_maxsave,0.046391500043682754,1,100,0.8,1 +heuristic_maxsave,0.032960699987597764,1,100,0.8,1 +spreading_maxsave,0.056882400007452816,2,100,0.8,2 +heuristic_maxsave,0.041347799997311085,2,100,0.8,2 +spreading_maxsave,0.10505459998967126,3,100,0.8,3 +heuristic_maxsave,0.058126999996602535,3,100,0.8,3 +spreading_maxsave,0.10147450002841651,5,100,0.8,5 +heuristic_maxsave,0.07909100002143532,5,100,0.8,5 +spreading_maxsave,0.1829336000373587,7,100,0.8,7 +heuristic_maxsave,0.1824219999834895,7,100,0.8,7 +spreading_maxsave,0.21091949997935444,10,100,0.8,8 +heuristic_maxsave,0.1449389000190422,10,100,0.8,8 +spreading_maxsave,0.06588090001605451,1,100,0.8,3 +heuristic_maxsave,0.0310767000191845,1,100,0.8,3 +spreading_maxsave,0.05584729998372495,2,100,0.8,4 +heuristic_maxsave,0.04399060003925115,2,100,0.8,4 +spreading_maxsave,0.07434110000031069,3,100,0.8,5 +heuristic_maxsave,0.0546135000186041,3,100,0.8,5 +spreading_maxsave,0.10366229998180643,5,100,0.8,7 +heuristic_maxsave,0.11076850001700222,5,100,0.8,7 +spreading_maxsave,0.11618509999243543,7,100,0.8,7 +heuristic_maxsave,0.11303469998529181,7,100,0.8,7 +spreading_maxsave,0.1587512000114657,10,100,0.8,7 +heuristic_maxsave,0.16867340001044795,10,100,0.8,7 +spreading_maxsave,0.05841629998758435,1,100,0.8,11 +heuristic_maxsave,0.045308300002943724,1,100,0.8,11 +spreading_maxsave,0.17853909998666495,2,100,0.8,12 +heuristic_maxsave,0.053165299992542714,2,100,0.8,12 +spreading_maxsave,0.07823159999679774,3,100,0.8,13 +heuristic_maxsave,0.07627799996407703,3,100,0.8,13 +spreading_maxsave,0.1042689000023529,5,100,0.8,15 +heuristic_maxsave,0.1089458999922499,5,100,0.8,15 +spreading_maxsave,0.12903929996537045,7,100,0.8,17 +heuristic_maxsave,0.12560229998780414,7,100,0.8,17 +spreading_maxsave,0.18077470001298934,10,100,0.8,20 +heuristic_maxsave,0.18033240002114326,10,100,0.8,20 +spreading_maxsave,0.046579300018493086,1,100,0.8,1 +heuristic_maxsave,0.030701299954671413,1,100,0.8,1 +spreading_maxsave,0.05852930003311485,2,100,0.8,1 +heuristic_maxsave,0.061761500022839755,2,100,0.8,1 +spreading_maxsave,0.08617700001923367,3,100,0.8,1 +heuristic_maxsave,0.060706499963998795,3,100,0.8,1 +spreading_maxsave,0.0999483999912627,5,100,0.8,1 +heuristic_maxsave,0.1699580000131391,5,100,0.8,1 +spreading_maxsave,0.13928439997835085,7,100,0.8,1 +heuristic_maxsave,0.12763410003390163,7,100,0.8,1 +spreading_maxsave,0.1581237000063993,10,100,0.8,1 +heuristic_maxsave,0.17142420000163838,10,100,0.8,1 +spreading_maxsave,0.20341960003133863,1,200,0.1,15 +heuristic_maxsave,0.140557800012175,1,200,0.1,13 +spreading_maxsave,0.2626188999856822,2,200,0.1,23 +heuristic_maxsave,0.08003869996173307,2,200,0.1,17 +spreading_maxsave,0.27273199998307973,3,200,0.1,30 +heuristic_maxsave,0.1140278999810107,3,200,0.1,21 +spreading_maxsave,0.5272406000294723,5,200,0.1,41 +heuristic_maxsave,0.11985319998348132,5,200,0.1,33 +spreading_maxsave,0.49218780000228435,7,200,0.1,44 +heuristic_maxsave,0.1246394999907352,7,200,0.1,44 +spreading_maxsave,0.8032811000011861,10,200,0.1,46 +heuristic_maxsave,0.1226862000185065,10,200,0.1,47 +spreading_maxsave,0.19924369995715097,1,200,0.1,31 +heuristic_maxsave,0.062235599965788424,1,200,0.1,31 +spreading_maxsave,0.3498484000447206,2,200,0.1,45 +heuristic_maxsave,0.0784918999997899,2,200,0.1,44 +spreading_maxsave,0.34298769995803013,3,200,0.1,57 +heuristic_maxsave,0.09382839995669201,3,200,0.1,53 +spreading_maxsave,0.4580061999731697,5,200,0.1,76 +heuristic_maxsave,0.0976029000012204,5,200,0.1,71 +spreading_maxsave,0.5484400000423193,7,200,0.1,89 +heuristic_maxsave,0.11530790000688285,7,200,0.1,81 +spreading_maxsave,0.5694460999802686,10,200,0.1,92 +heuristic_maxsave,0.21844149997923523,10,200,0.1,92 +spreading_maxsave,0.2398438000236638,1,200,0.1,10 +heuristic_maxsave,0.05897199996979907,1,200,0.1,6 +spreading_maxsave,0.3083875000011176,2,200,0.1,15 +heuristic_maxsave,0.07806309999432415,2,200,0.1,12 +spreading_maxsave,0.2816296000382863,3,200,0.1,18 +heuristic_maxsave,0.10942920000525191,3,200,0.1,17 +spreading_maxsave,0.42981460003647953,5,200,0.1,19 +heuristic_maxsave,0.10953089996473864,5,200,0.1,19 +spreading_maxsave,0.4193704000208527,7,200,0.1,19 +heuristic_maxsave,0.12374299997463822,7,200,0.1,19 +spreading_maxsave,0.5561525999801233,10,200,0.1,19 +heuristic_maxsave,0.10852969996631145,10,200,0.1,19 +spreading_maxsave,0.23703669995302334,1,200,0.1,24 +heuristic_maxsave,0.07296319998567924,1,200,0.1,24 +spreading_maxsave,0.2517604999593459,2,200,0.1,37 +heuristic_maxsave,0.10659300000406802,2,200,0.1,34 +spreading_maxsave,0.4076805000077002,3,200,0.1,49 +heuristic_maxsave,0.11074350000126287,3,200,0.1,42 +spreading_maxsave,0.4572325000190176,5,200,0.1,63 +heuristic_maxsave,0.10574430000269786,5,200,0.1,55 +spreading_maxsave,0.5332056999905035,7,200,0.1,71 +heuristic_maxsave,0.12314650003099814,7,200,0.1,63 +spreading_maxsave,0.6110409999964759,10,200,0.1,73 +heuristic_maxsave,0.11455469997599721,10,200,0.1,79 +spreading_maxsave,0.16822839999804273,1,200,0.1,15 +heuristic_maxsave,0.05124439997598529,1,200,0.1,12 +spreading_maxsave,0.2748029999784194,2,200,0.1,25 +heuristic_maxsave,0.15088510001078248,2,200,0.1,18 +spreading_maxsave,0.2755275999661535,3,200,0.1,33 +heuristic_maxsave,0.10477440000977367,3,200,0.1,24 +spreading_maxsave,0.4485907999915071,5,200,0.1,45 +heuristic_maxsave,0.11699609999777749,5,200,0.1,30 +spreading_maxsave,0.4879001999506727,7,200,0.1,46 +heuristic_maxsave,0.12443209998309612,7,200,0.1,45 +spreading_maxsave,0.6306231999769807,10,200,0.1,49 +heuristic_maxsave,0.1087235999875702,10,200,0.1,51 +spreading_maxsave,0.2438887999742292,1,200,0.1,20 +heuristic_maxsave,0.07715939998161048,1,200,0.1,18 +spreading_maxsave,0.25002979999408126,2,200,0.1,34 +heuristic_maxsave,0.10443879995727912,2,200,0.1,27 +spreading_maxsave,0.31098650000058115,3,200,0.1,44 +heuristic_maxsave,0.08787809999193996,3,200,0.1,37 +spreading_maxsave,0.6536024999804795,5,200,0.1,61 +heuristic_maxsave,0.10921149997739121,5,200,0.1,54 +spreading_maxsave,0.4697406000341289,7,200,0.1,72 +heuristic_maxsave,0.12009360000956804,7,200,0.1,66 +spreading_maxsave,0.672519400017336,10,200,0.1,75 +heuristic_maxsave,0.14132759999483824,10,200,0.1,76 +spreading_maxsave,0.19063139997888356,1,200,0.1,28 +heuristic_maxsave,0.05408689996693283,1,200,0.1,25 +spreading_maxsave,0.296982100000605,2,200,0.1,40 +heuristic_maxsave,0.07458260003477335,2,200,0.1,38 +spreading_maxsave,0.3882549999980256,3,200,0.1,50 +heuristic_maxsave,0.09245759999612346,3,200,0.1,46 +spreading_maxsave,0.3851208999985829,5,200,0.1,66 +heuristic_maxsave,0.13100950000807643,5,200,0.1,59 +spreading_maxsave,0.5501699000014924,7,200,0.1,77 +heuristic_maxsave,0.11196680000284687,7,200,0.1,69 +spreading_maxsave,0.6511672000051476,10,200,0.1,80 +heuristic_maxsave,0.13318209996214136,10,200,0.1,79 +spreading_maxsave,0.18269929999951273,1,200,0.1,15 +heuristic_maxsave,0.05740340001648292,1,200,0.1,9 +spreading_maxsave,0.39279429998714477,2,200,0.1,26 +heuristic_maxsave,0.08693560003302991,2,200,0.1,18 +spreading_maxsave,0.2891749999835156,3,200,0.1,35 +heuristic_maxsave,0.11712640000041574,3,200,0.1,26 +spreading_maxsave,0.4806969999917783,5,200,0.1,49 +heuristic_maxsave,0.11930510000092909,5,200,0.1,36 +spreading_maxsave,0.46506880002561957,7,200,0.1,59 +heuristic_maxsave,0.12343269999837503,7,200,0.1,49 +spreading_maxsave,0.5898283999995328,10,200,0.1,61 +heuristic_maxsave,0.1216880000429228,10,200,0.1,64 +spreading_maxsave,0.1767225000075996,1,200,0.1,15 +heuristic_maxsave,0.05553040001541376,1,200,0.1,14 +spreading_maxsave,0.2522677999804728,2,200,0.1,24 +heuristic_maxsave,0.08556350000435486,2,200,0.1,20 +spreading_maxsave,0.4057425999781117,3,200,0.1,31 +heuristic_maxsave,0.09662039997056127,3,200,0.1,25 +spreading_maxsave,0.4284159000380896,5,200,0.1,43 +heuristic_maxsave,0.11553880001883954,5,200,0.1,37 +spreading_maxsave,0.46696410002186894,7,200,0.1,45 +heuristic_maxsave,0.11888269998598844,7,200,0.1,46 +spreading_maxsave,0.5607535000308417,10,200,0.1,47 +heuristic_maxsave,0.10499140003230423,10,200,0.1,47 +spreading_maxsave,0.23917509999591857,1,200,0.1,23 +heuristic_maxsave,0.07652640005107969,1,200,0.1,23 +spreading_maxsave,0.24873749999096617,2,200,0.1,34 +heuristic_maxsave,0.06917840003734455,2,200,0.1,30 +spreading_maxsave,0.31675140000879765,3,200,0.1,43 +heuristic_maxsave,0.1606795000261627,3,200,0.1,35 +spreading_maxsave,0.3789206999936141,5,200,0.1,56 +heuristic_maxsave,0.13713420002022758,5,200,0.1,44 +spreading_maxsave,0.5711444999906234,7,200,0.1,62 +heuristic_maxsave,0.1419412000104785,7,200,0.1,52 +spreading_maxsave,0.6670626999693923,10,200,0.1,63 +heuristic_maxsave,0.12780170002952218,10,200,0.1,66 +spreading_maxsave,0.17311099998187274,1,200,0.5,10 +heuristic_maxsave,0.0788998999632895,1,200,0.5,9 +spreading_maxsave,0.26493740000296384,2,200,0.5,12 +heuristic_maxsave,0.11642450001090765,2,200,0.5,13 +spreading_maxsave,0.2894808000419289,3,200,0.5,13 +heuristic_maxsave,0.11290670000016689,3,200,0.5,14 +spreading_maxsave,0.35068069997942075,5,200,0.5,15 +heuristic_maxsave,0.1411962999845855,5,200,0.5,16 +spreading_maxsave,0.32925900002010167,7,200,0.5,17 +heuristic_maxsave,0.18706000002566725,7,200,0.5,18 +spreading_maxsave,0.49558609997620806,10,200,0.5,18 +heuristic_maxsave,0.21876110002631322,10,200,0.5,18 +spreading_maxsave,0.2270472999662161,1,200,0.5,24 +heuristic_maxsave,0.08888080000178888,1,200,0.5,17 +spreading_maxsave,0.4033233000081964,2,200,0.5,28 +heuristic_maxsave,0.11479399999370798,2,200,0.5,28 +spreading_maxsave,0.245236000046134,3,200,0.5,29 +heuristic_maxsave,0.1572133000008762,3,200,0.5,30 +spreading_maxsave,0.2968413000344299,5,200,0.5,31 +heuristic_maxsave,0.19483649998437613,5,200,0.5,32 +spreading_maxsave,0.3449677999597043,7,200,0.5,33 +heuristic_maxsave,0.2802219999721274,7,200,0.5,34 +spreading_maxsave,0.4639442000188865,10,200,0.5,36 +heuristic_maxsave,0.24565370002528653,10,200,0.5,37 +spreading_maxsave,0.2086282999953255,1,200,0.5,22 +heuristic_maxsave,0.07537609996506944,1,200,0.5,20 +spreading_maxsave,0.21657950000371784,2,200,0.5,29 +heuristic_maxsave,0.12791999999899417,2,200,0.5,30 +spreading_maxsave,0.3090492999763228,3,200,0.5,30 +heuristic_maxsave,0.16676630004076287,3,200,0.5,31 +spreading_maxsave,0.33121450000908226,5,200,0.5,32 +heuristic_maxsave,0.24986579996766523,5,200,0.5,33 +spreading_maxsave,0.4063476999872364,7,200,0.5,34 +heuristic_maxsave,0.18211739999242127,7,200,0.5,35 +spreading_maxsave,0.5284660999896005,10,200,0.5,37 +heuristic_maxsave,0.2370731999981217,10,200,0.5,38 +spreading_maxsave,0.2714187000528909,1,200,0.5,15 +heuristic_maxsave,0.09411840001121163,1,200,0.5,12 +spreading_maxsave,0.20913700002711266,2,200,0.5,18 +heuristic_maxsave,0.1287410999648273,2,200,0.5,18 +spreading_maxsave,0.26726410002447665,3,200,0.5,19 +heuristic_maxsave,0.1994836999801919,3,200,0.5,20 +spreading_maxsave,0.2981535000144504,5,200,0.5,21 +heuristic_maxsave,0.17896380001911893,5,200,0.5,22 +spreading_maxsave,0.46380690002115443,7,200,0.5,23 +heuristic_maxsave,0.2134313000133261,7,200,0.5,24 +spreading_maxsave,0.5427520999801345,10,200,0.5,26 +heuristic_maxsave,0.2393694000202231,10,200,0.5,27 +spreading_maxsave,0.21005410002544522,1,200,0.5,23 +heuristic_maxsave,0.08162710000760853,1,200,0.5,19 +spreading_maxsave,0.3068525000126101,2,200,0.5,30 +heuristic_maxsave,0.1222581000183709,2,200,0.5,29 +spreading_maxsave,0.3039056999841705,3,200,0.5,31 +heuristic_maxsave,0.10138700000243261,3,200,0.5,32 +spreading_maxsave,0.4060017999727279,5,200,0.5,33 +heuristic_maxsave,0.1509630000218749,5,200,0.5,34 +spreading_maxsave,0.38518699997803196,7,200,0.5,35 +heuristic_maxsave,0.33387329999823123,7,200,0.5,36 +spreading_maxsave,0.5281620000023395,10,200,0.5,38 +heuristic_maxsave,0.3236653999774717,10,200,0.5,39 +spreading_maxsave,0.24680199997965246,1,200,0.5,34 +heuristic_maxsave,0.0966533999890089,1,200,0.5,30 +spreading_maxsave,0.27348640002310276,2,200,0.5,47 +heuristic_maxsave,0.19376179995015264,2,200,0.5,47 +spreading_maxsave,0.2868445999920368,3,200,0.5,49 +heuristic_maxsave,0.16365860000951216,3,200,0.5,50 +spreading_maxsave,0.41779949999181554,5,200,0.5,51 +heuristic_maxsave,0.16417340002954006,5,200,0.5,52 +spreading_maxsave,0.3689600999932736,7,200,0.5,53 +heuristic_maxsave,0.29248880001250654,7,200,0.5,54 +spreading_maxsave,0.5096511000301689,10,200,0.5,56 +heuristic_maxsave,0.25243290001526475,10,200,0.5,57 +spreading_maxsave,0.26905850000912324,1,200,0.5,34 +heuristic_maxsave,0.11558689997764304,1,200,0.5,33 +spreading_maxsave,0.2672153999446891,2,200,0.5,48 +heuristic_maxsave,0.14364630001364276,2,200,0.5,43 +spreading_maxsave,0.35067400004481897,3,200,0.5,49 +heuristic_maxsave,0.1966035999939777,3,200,0.5,50 +spreading_maxsave,0.32578080001985654,5,200,0.5,51 +heuristic_maxsave,0.27724369999486953,5,200,0.5,52 +spreading_maxsave,0.4158801999874413,7,200,0.5,53 +heuristic_maxsave,0.20388340001227334,7,200,0.5,54 +spreading_maxsave,0.5159435999812558,10,200,0.5,56 +heuristic_maxsave,0.27886650001164526,10,200,0.5,57 +spreading_maxsave,0.20198610000079498,1,200,0.5,14 +heuristic_maxsave,0.14060520002385601,1,200,0.5,8 +spreading_maxsave,0.23266789998160675,2,200,0.5,15 +heuristic_maxsave,0.09457349998410791,2,200,0.5,16 +spreading_maxsave,0.3066790000302717,3,200,0.5,16 +heuristic_maxsave,0.12973490002332255,3,200,0.5,17 +spreading_maxsave,0.38382709998404607,5,200,0.5,18 +heuristic_maxsave,0.14897899999050424,5,200,0.5,19 +spreading_maxsave,0.36021919996710494,7,200,0.5,20 +heuristic_maxsave,0.28728940000291914,7,200,0.5,21 +spreading_maxsave,0.47887659998377785,10,200,0.5,23 +heuristic_maxsave,0.23146649997215718,10,200,0.5,24 +spreading_maxsave,0.2793437999789603,1,200,0.5,29 +heuristic_maxsave,0.07265919999917969,1,200,0.5,29 +spreading_maxsave,0.23680730001069605,2,200,0.5,41 +heuristic_maxsave,0.14153750002151355,2,200,0.5,41 +spreading_maxsave,0.3253047000034712,3,200,0.5,42 +heuristic_maxsave,0.1853941999725066,3,200,0.5,42 +spreading_maxsave,0.3316435999586247,5,200,0.5,44 +heuristic_maxsave,0.19933839997975156,5,200,0.5,44 +spreading_maxsave,0.5072257000138052,7,200,0.5,46 +heuristic_maxsave,0.2101610000245273,7,200,0.5,46 +spreading_maxsave,0.5774020999670029,10,200,0.5,49 +heuristic_maxsave,0.2867017000098713,10,200,0.5,49 +spreading_maxsave,0.20441920001758263,1,200,0.5,6 +heuristic_maxsave,0.0687661999836564,1,200,0.5,5 +spreading_maxsave,0.21520560001954436,2,200,0.5,7 +heuristic_maxsave,0.14815709996037185,2,200,0.5,8 +spreading_maxsave,0.23221839999314398,3,200,0.5,8 +heuristic_maxsave,0.10049330000765622,3,200,0.5,9 +spreading_maxsave,0.3455549000063911,5,200,0.5,10 +heuristic_maxsave,0.13615590002154931,5,200,0.5,11 +spreading_maxsave,0.4111096999840811,7,200,0.5,11 +heuristic_maxsave,0.19502980000106618,7,200,0.5,11 +spreading_maxsave,0.5645965000148863,10,200,0.5,11 +heuristic_maxsave,0.24206710001453757,10,200,0.5,11 +spreading_maxsave,0.24467009998625144,1,200,0.8,17 +heuristic_maxsave,0.16768809995846823,1,200,0.8,16 +spreading_maxsave,0.3239018000313081,2,200,0.8,18 +heuristic_maxsave,0.3605091000208631,2,200,0.8,18 +spreading_maxsave,0.32432129996595904,3,200,0.8,19 +heuristic_maxsave,0.22794069995870814,3,200,0.8,19 +spreading_maxsave,0.3939768999698572,5,200,0.8,21 +heuristic_maxsave,0.37632729997858405,5,200,0.8,21 +spreading_maxsave,0.4894497999921441,7,200,0.8,23 +heuristic_maxsave,0.5015065000043251,7,200,0.8,23 +spreading_maxsave,0.4849415000062436,10,200,0.8,26 +heuristic_maxsave,0.5283704000175931,10,200,0.8,26 +spreading_maxsave,0.16278260003309697,1,200,0.8,17 +heuristic_maxsave,0.11985359998652712,1,200,0.8,14 +spreading_maxsave,0.2756377999903634,2,200,0.8,18 +heuristic_maxsave,0.16894910001428798,2,200,0.8,18 +spreading_maxsave,0.23795589996734634,3,200,0.8,19 +heuristic_maxsave,0.18934040004387498,3,200,0.8,19 +spreading_maxsave,0.3514193999581039,5,200,0.8,21 +heuristic_maxsave,0.28049649996683,5,200,0.8,21 +spreading_maxsave,0.35181360004935414,7,200,0.8,23 +heuristic_maxsave,0.43209489999571815,7,200,0.8,23 +spreading_maxsave,0.5096444999799132,10,200,0.8,26 +heuristic_maxsave,0.5287143000168726,10,200,0.8,26 +spreading_maxsave,0.15775959996972233,1,200,0.8,13 +heuristic_maxsave,0.10997509997105226,1,200,0.8,12 +spreading_maxsave,0.21985059999860823,2,200,0.8,14 +heuristic_maxsave,0.23877259995788336,2,200,0.8,14 +spreading_maxsave,0.2554381999652833,3,200,0.8,15 +heuristic_maxsave,0.2075817000004463,3,200,0.8,15 +spreading_maxsave,0.32472799997776747,5,200,0.8,17 +heuristic_maxsave,0.2861352000036277,5,200,0.8,17 +spreading_maxsave,0.3513053000206128,7,200,0.8,19 +heuristic_maxsave,0.43761150003410876,7,200,0.8,19 +spreading_maxsave,0.4498962000361644,10,200,0.8,22 +heuristic_maxsave,0.5710637000156567,10,200,0.8,22 +spreading_maxsave,0.15579190000426024,1,200,0.8,2 +heuristic_maxsave,0.08184470003470778,1,200,0.8,2 +spreading_maxsave,0.19607629999518394,2,200,0.8,3 +heuristic_maxsave,0.12960729998303577,2,200,0.8,3 +spreading_maxsave,0.28095200000097975,3,200,0.8,4 +heuristic_maxsave,0.15784600004553795,3,200,0.8,4 +spreading_maxsave,0.2567032999941148,5,200,0.8,4 +heuristic_maxsave,0.23500600003171712,5,200,0.8,4 +spreading_maxsave,0.35566020000260323,7,200,0.8,4 +heuristic_maxsave,0.31088499998440966,7,200,0.8,4 +spreading_maxsave,0.5010427000233904,10,200,0.8,4 +heuristic_maxsave,0.40685430000303313,10,200,0.8,4 +spreading_maxsave,0.17057949997251853,1,200,0.8,21 +heuristic_maxsave,0.11399509996408597,1,200,0.8,20 +spreading_maxsave,0.29378529998939484,2,200,0.8,22 +heuristic_maxsave,0.18115999997826293,2,200,0.8,22 +spreading_maxsave,0.23125200002687052,3,200,0.8,23 +heuristic_maxsave,0.2537556000170298,3,200,0.8,23 +spreading_maxsave,0.37320559995714575,5,200,0.8,25 +heuristic_maxsave,0.2873711999855004,5,200,0.8,25 +spreading_maxsave,0.44698790000984445,7,200,0.8,27 +heuristic_maxsave,0.30873990000691265,7,200,0.8,27 +spreading_maxsave,0.4583666000398807,10,200,0.8,30 +heuristic_maxsave,0.5976279000169598,10,200,0.8,30 +spreading_maxsave,0.17005660000722855,1,200,0.8,10 +heuristic_maxsave,0.10861180000938475,1,200,0.8,10 +spreading_maxsave,0.31378930003847927,2,200,0.8,11 +heuristic_maxsave,0.21392790001118556,2,200,0.8,11 +spreading_maxsave,0.314260600018315,3,200,0.8,12 +heuristic_maxsave,0.18837230000644922,3,200,0.8,12 +spreading_maxsave,0.3502934999996796,5,200,0.8,14 +heuristic_maxsave,0.27132579998578876,5,200,0.8,14 +spreading_maxsave,0.37966970005072653,7,200,0.8,16 +heuristic_maxsave,0.36195310001494363,7,200,0.8,16 +spreading_maxsave,0.4287651000195183,10,200,0.8,19 +heuristic_maxsave,0.442568400001619,10,200,0.8,19 +spreading_maxsave,0.25963749998481944,1,200,0.8,4 +heuristic_maxsave,0.0917695999960415,1,200,0.8,4 +spreading_maxsave,0.203355300007388,2,200,0.8,5 +heuristic_maxsave,0.12362410000059754,2,200,0.8,5 +spreading_maxsave,0.20830619998741895,3,200,0.8,6 +heuristic_maxsave,0.20621770003344864,3,200,0.8,6 +spreading_maxsave,0.37182299996493384,5,200,0.8,6 +heuristic_maxsave,0.22684110002592206,5,200,0.8,6 +spreading_maxsave,0.35788569995202124,7,200,0.8,6 +heuristic_maxsave,0.42304959998000413,7,200,0.8,6 +spreading_maxsave,0.3909694000030868,10,200,0.8,6 +heuristic_maxsave,0.4305410999804735,10,200,0.8,6 +spreading_maxsave,0.14835169998696074,1,200,0.8,1 +heuristic_maxsave,0.09319310000864789,1,200,0.8,1 +spreading_maxsave,0.19742340000811964,2,200,0.8,2 +heuristic_maxsave,0.13829919998534024,2,200,0.8,2 +spreading_maxsave,0.30351140000857413,3,200,0.8,3 +heuristic_maxsave,0.21503750002011657,3,200,0.8,3 +spreading_maxsave,0.2912133000208996,5,200,0.8,3 +heuristic_maxsave,0.27579700003843755,5,200,0.8,3 +spreading_maxsave,0.4419707999913953,7,200,0.8,3 +heuristic_maxsave,0.3256087999907322,7,200,0.8,3 +spreading_maxsave,0.5010434000287205,10,200,0.8,3 +heuristic_maxsave,0.47702380002010614,10,200,0.8,3 +spreading_maxsave,0.14794589998200536,1,200,0.8,1 +heuristic_maxsave,0.08395420003216714,1,200,0.8,1 +spreading_maxsave,0.24917740002274513,2,200,0.8,2 +heuristic_maxsave,0.11463430000003427,2,200,0.8,2 +spreading_maxsave,0.20890130003681406,3,200,0.8,3 +heuristic_maxsave,0.15895249997265637,3,200,0.8,3 +spreading_maxsave,0.2656531000393443,5,200,0.8,3 +heuristic_maxsave,0.2957308000186458,5,200,0.8,3 +spreading_maxsave,0.391859499970451,7,200,0.8,3 +heuristic_maxsave,0.34575369994854555,7,200,0.8,3 +spreading_maxsave,0.5015684000100009,10,200,0.8,3 +heuristic_maxsave,0.4583000999991782,10,200,0.8,3 +spreading_maxsave,0.2605781000456773,1,200,0.8,13 +heuristic_maxsave,0.13408430002164096,1,200,0.8,12 +spreading_maxsave,0.22674280003411695,2,200,0.8,14 +heuristic_maxsave,0.15283520001685247,2,200,0.8,14 +spreading_maxsave,0.23604400001931936,3,200,0.8,15 +heuristic_maxsave,0.19458049995591864,3,200,0.8,15 +spreading_maxsave,0.29680549999466166,5,200,0.8,17 +heuristic_maxsave,0.3113440999877639,5,200,0.8,17 +spreading_maxsave,0.4118233000044711,7,200,0.8,19 +heuristic_maxsave,0.3212999000097625,7,200,0.8,19 +spreading_maxsave,0.5214633999858052,10,200,0.8,22 +heuristic_maxsave,0.5200631000334397,10,200,0.8,22 +spreading_maxsave,0.42765999998664483,1,400,0.1,10 +heuristic_maxsave,0.1492883000173606,1,400,0.1,8 +spreading_maxsave,0.6323594000423327,2,400,0.1,18 +heuristic_maxsave,0.20636070001637563,2,400,0.1,15 +spreading_maxsave,0.704987799981609,3,400,0.1,26 +heuristic_maxsave,0.24951699998928234,3,400,0.1,21 +spreading_maxsave,0.8821355999680236,5,400,0.1,34 +heuristic_maxsave,0.47665470000356436,5,400,0.1,29 +spreading_maxsave,1.116703099978622,7,400,0.1,35 +heuristic_maxsave,0.5398625999805517,7,400,0.1,38 +spreading_maxsave,1.3485814000014216,10,400,0.1,38 +heuristic_maxsave,0.3855633999919519,10,400,0.1,40 +spreading_maxsave,0.6049749999656342,1,400,0.1,6 +heuristic_maxsave,0.1435287999920547,1,400,0.1,4 +spreading_maxsave,0.6240496999816969,2,400,0.1,8 +heuristic_maxsave,0.2191406000056304,2,400,0.1,6 +spreading_maxsave,0.7023757999995723,3,400,0.1,9 +heuristic_maxsave,0.24785089999204502,3,400,0.1,10 +spreading_maxsave,1.1580646999645978,5,400,0.1,10 +heuristic_maxsave,0.3306579000200145,5,400,0.1,10 +spreading_maxsave,1.1748952000052668,7,400,0.1,10 +heuristic_maxsave,0.3617365999962203,7,400,0.1,10 +spreading_maxsave,1.26313559996197,10,400,0.1,10 +heuristic_maxsave,0.4780159000074491,10,400,0.1,10 +spreading_maxsave,0.4582809000276029,1,400,0.1,30 +heuristic_maxsave,0.2663825000054203,1,400,0.1,28 +spreading_maxsave,0.8567600999958813,2,400,0.1,55 +heuristic_maxsave,0.3901632000342943,2,400,0.1,46 +spreading_maxsave,0.8691420999821275,3,400,0.1,77 +heuristic_maxsave,0.30354749999241903,3,400,0.1,64 +spreading_maxsave,1.107374599960167,5,400,0.1,115 +heuristic_maxsave,0.38213709997944534,5,400,0.1,99 +spreading_maxsave,1.204921500000637,7,400,0.1,143 +heuristic_maxsave,0.5033570999512449,7,400,0.1,121 +spreading_maxsave,1.3851383999572136,10,400,0.1,168 +heuristic_maxsave,0.4066457999870181,10,400,0.1,148 +spreading_maxsave,0.47752069996204227,1,400,0.1,15 +heuristic_maxsave,0.15961309999693185,1,400,0.1,10 +spreading_maxsave,0.632251700037159,2,400,0.1,29 +heuristic_maxsave,0.17986510001355782,2,400,0.1,18 +spreading_maxsave,0.7331343999831006,3,400,0.1,40 +heuristic_maxsave,0.23259220004547387,3,400,0.1,26 +spreading_maxsave,1.0051480999682099,5,400,0.1,56 +heuristic_maxsave,0.3036951999529265,5,400,0.1,41 +spreading_maxsave,1.171053700032644,7,400,0.1,67 +heuristic_maxsave,0.3257984000374563,7,400,0.1,54 +spreading_maxsave,1.3093210000079125,10,400,0.1,68 +heuristic_maxsave,0.3843877999461256,10,400,0.1,71 +spreading_maxsave,0.5643018999835476,1,400,0.1,22 +heuristic_maxsave,0.17030870000598952,1,400,0.1,20 +spreading_maxsave,1.0122063999879174,2,400,0.1,42 +heuristic_maxsave,0.4224600999732502,2,400,0.1,35 +spreading_maxsave,0.7244173999642953,3,400,0.1,59 +heuristic_maxsave,0.3144646000000648,3,400,0.1,47 +spreading_maxsave,0.9571849000058137,5,400,0.1,86 +heuristic_maxsave,0.29574039997532964,5,400,0.1,71 +spreading_maxsave,1.3085287000285462,7,400,0.1,106 +heuristic_maxsave,0.5863110999925993,7,400,0.1,90 +spreading_maxsave,1.5827839000266977,10,400,0.1,122 +heuristic_maxsave,0.3893034000066109,10,400,0.1,110 +spreading_maxsave,0.5635352000244893,1,400,0.1,28 +heuristic_maxsave,0.17216430004918948,1,400,0.1,25 +spreading_maxsave,0.7714409999898635,2,400,0.1,54 +heuristic_maxsave,0.28708939999341965,2,400,0.1,47 +spreading_maxsave,1.1440602000220679,3,400,0.1,76 +heuristic_maxsave,0.4536575999809429,3,400,0.1,63 +spreading_maxsave,1.1517882000189275,5,400,0.1,111 +heuristic_maxsave,0.4404953000484966,5,400,0.1,92 +spreading_maxsave,1.2073612000094727,7,400,0.1,134 +heuristic_maxsave,0.36863340000854805,7,400,0.1,116 +spreading_maxsave,1.3385261000366881,10,400,0.1,159 +heuristic_maxsave,0.601250900013838,10,400,0.1,137 +spreading_maxsave,0.5026269999798387,1,400,0.1,29 +heuristic_maxsave,0.17745150002883747,1,400,0.1,23 +spreading_maxsave,0.6409444999881089,2,400,0.1,54 +heuristic_maxsave,0.21805419999873266,2,400,0.1,44 +spreading_maxsave,0.7625337000354193,3,400,0.1,75 +heuristic_maxsave,0.30355260003125295,3,400,0.1,62 +spreading_maxsave,0.8956204999703914,5,400,0.1,110 +heuristic_maxsave,0.315176900010556,5,400,0.1,92 +spreading_maxsave,1.3106273000012152,7,400,0.1,133 +heuristic_maxsave,0.4594922999967821,7,400,0.1,115 +spreading_maxsave,1.3869516999693587,10,400,0.1,157 +heuristic_maxsave,0.40207060001557693,10,400,0.1,138 +spreading_maxsave,0.4109003000194207,1,400,0.1,13 +heuristic_maxsave,0.13035689998650923,1,400,0.1,6 +spreading_maxsave,0.6568864000146277,2,400,0.1,23 +heuristic_maxsave,0.19629559997702017,2,400,0.1,12 +spreading_maxsave,0.7080241999938153,3,400,0.1,32 +heuristic_maxsave,0.23181029997067526,3,400,0.1,17 +spreading_maxsave,1.0378405000083148,5,400,0.1,44 +heuristic_maxsave,0.37497919995803386,5,400,0.1,24 +spreading_maxsave,0.9949636000092141,7,400,0.1,45 +heuristic_maxsave,0.39175889996113256,7,400,0.1,39 +spreading_maxsave,1.2170275000389665,10,400,0.1,48 +heuristic_maxsave,0.41554650000762194,10,400,0.1,49 +spreading_maxsave,0.47009479999542236,1,400,0.1,28 +heuristic_maxsave,0.2027403000392951,1,400,0.1,23 +spreading_maxsave,0.7103741000173613,2,400,0.1,54 +heuristic_maxsave,0.312370200001169,2,400,0.1,46 +spreading_maxsave,0.8472247999743558,3,400,0.1,76 +heuristic_maxsave,0.2734562000259757,3,400,0.1,62 +spreading_maxsave,0.952839599980507,5,400,0.1,109 +heuristic_maxsave,0.2962948000058532,5,400,0.1,93 +spreading_maxsave,1.120882899966091,7,400,0.1,135 +heuristic_maxsave,0.416954500018619,7,400,0.1,116 +spreading_maxsave,1.6903908000094816,10,400,0.1,159 +heuristic_maxsave,0.38046730001224205,10,400,0.1,142 +spreading_maxsave,0.48489030002383515,1,400,0.1,17 +heuristic_maxsave,0.13002149999374524,1,400,0.1,13 +spreading_maxsave,0.5428055999800563,2,400,0.1,32 +heuristic_maxsave,0.24578960001235828,2,400,0.1,26 +spreading_maxsave,0.6679781000129879,3,400,0.1,46 +heuristic_maxsave,0.3075420000241138,3,400,0.1,38 +spreading_maxsave,0.9831248000264168,5,400,0.1,64 +heuristic_maxsave,0.3502979999757372,5,400,0.1,58 +spreading_maxsave,1.1571738999919035,7,400,0.1,77 +heuristic_maxsave,0.3945752000436187,7,400,0.1,68 +spreading_maxsave,1.3243401999934576,10,400,0.1,81 +heuristic_maxsave,0.4195264999871142,10,400,0.1,83 +spreading_maxsave,0.6300575999775901,1,400,0.5,21 +heuristic_maxsave,0.19624290004139766,1,400,0.5,21 +spreading_maxsave,0.7100792999844998,2,400,0.5,25 +heuristic_maxsave,0.39336480002384633,2,400,0.5,25 +spreading_maxsave,0.8253624999779277,3,400,0.5,26 +heuristic_maxsave,0.2970519000082277,3,400,0.5,26 +spreading_maxsave,0.967457499995362,5,400,0.5,28 +heuristic_maxsave,0.3872476000105962,5,400,0.5,28 +spreading_maxsave,0.9869248999748379,7,400,0.5,30 +heuristic_maxsave,0.4718388000037521,7,400,0.5,30 +spreading_maxsave,1.4825164999929257,10,400,0.5,33 +heuristic_maxsave,0.6676626999978907,10,400,0.5,33 +spreading_maxsave,0.696589800005313,1,400,0.5,10 +heuristic_maxsave,0.26674769999226555,1,400,0.5,9 +spreading_maxsave,0.6684675000142306,2,400,0.5,11 +heuristic_maxsave,0.23055500001646578,2,400,0.5,11 +spreading_maxsave,0.7289986000396311,3,400,0.5,12 +heuristic_maxsave,0.2841276000253856,3,400,0.5,12 +spreading_maxsave,0.9098501999978907,5,400,0.5,14 +heuristic_maxsave,0.623745399992913,5,400,0.5,14 +spreading_maxsave,0.966344200016465,7,400,0.5,16 +heuristic_maxsave,0.4757868999731727,7,400,0.5,16 +spreading_maxsave,1.1371457999921404,10,400,0.5,19 +heuristic_maxsave,0.7268507999833673,10,400,0.5,19 +spreading_maxsave,0.748866900044959,1,400,0.5,62 +heuristic_maxsave,0.26476649998221546,1,400,0.5,58 +spreading_maxsave,0.9763952000066638,2,400,0.5,87 +heuristic_maxsave,0.4035986000089906,2,400,0.5,83 +spreading_maxsave,0.9502340000472032,3,400,0.5,95 +heuristic_maxsave,0.4505986000294797,3,400,0.5,96 +spreading_maxsave,1.1072708999854513,5,400,0.5,97 +heuristic_maxsave,0.47691730002406985,5,400,0.5,98 +spreading_maxsave,1.3947173000196926,7,400,0.5,99 +heuristic_maxsave,0.6062100999988616,7,400,0.5,100 +spreading_maxsave,1.4940172000206076,10,400,0.5,102 +heuristic_maxsave,0.7636698000133038,10,400,0.5,103 +spreading_maxsave,0.714410999964457,1,400,0.5,57 +heuristic_maxsave,0.2569395999889821,1,400,0.5,46 +spreading_maxsave,0.8866244999808259,2,400,0.5,79 +heuristic_maxsave,0.560739399981685,2,400,0.5,74 +spreading_maxsave,0.9469704999937676,3,400,0.5,85 +heuristic_maxsave,0.37933510000584647,3,400,0.5,86 +spreading_maxsave,1.0833743999828584,5,400,0.5,87 +heuristic_maxsave,0.4810797999962233,5,400,0.5,88 +spreading_maxsave,1.2787637999863364,7,400,0.5,89 +heuristic_maxsave,0.780480399960652,7,400,0.5,90 +spreading_maxsave,1.403326699975878,10,400,0.5,92 +heuristic_maxsave,0.7945015999721363,10,400,0.5,93 +spreading_maxsave,0.7733919000020251,1,400,0.5,53 +heuristic_maxsave,0.25048580003203824,1,400,0.5,47 +spreading_maxsave,0.8559090999769978,2,400,0.5,74 +heuristic_maxsave,0.3134200000204146,2,400,0.5,72 +spreading_maxsave,1.0852037000004202,3,400,0.5,79 +heuristic_maxsave,0.3802692999597639,3,400,0.5,81 +spreading_maxsave,1.0851624000351876,5,400,0.5,81 +heuristic_maxsave,0.5270821000449359,5,400,0.5,84 +spreading_maxsave,1.1482656000298448,7,400,0.5,83 +heuristic_maxsave,0.5939276999561116,7,400,0.5,86 +spreading_maxsave,1.6968992000329308,10,400,0.5,86 +heuristic_maxsave,0.7008178000105545,10,400,0.5,89 +spreading_maxsave,0.7308476999751292,1,400,0.5,49 +heuristic_maxsave,0.31305280001834035,1,400,0.5,45 +spreading_maxsave,0.8084814000176266,2,400,0.5,68 +heuristic_maxsave,0.3253227000241168,2,400,0.5,65 +spreading_maxsave,0.986151700024493,3,400,0.5,72 +heuristic_maxsave,0.577400799957104,3,400,0.5,74 +spreading_maxsave,1.0387342000030912,5,400,0.5,74 +heuristic_maxsave,0.47546290000900626,5,400,0.5,76 +spreading_maxsave,1.1369822999695316,7,400,0.5,76 +heuristic_maxsave,0.6264398999628611,7,400,0.5,78 +spreading_maxsave,1.3521505999960937,10,400,0.5,79 +heuristic_maxsave,0.8805881000007503,10,400,0.5,81 +spreading_maxsave,0.7544279000139795,1,400,0.5,47 +heuristic_maxsave,0.2463018000125885,1,400,0.5,44 +spreading_maxsave,0.8365135000203736,2,400,0.5,68 +heuristic_maxsave,0.38614690001122653,2,400,0.5,66 +spreading_maxsave,0.9377570999786258,3,400,0.5,71 +heuristic_maxsave,0.34193779999623075,3,400,0.5,72 +spreading_maxsave,1.0750787999713793,5,400,0.5,73 +heuristic_maxsave,0.5804534999770112,5,400,0.5,74 +spreading_maxsave,1.2203048000228591,7,400,0.5,75 +heuristic_maxsave,0.6325779999606311,7,400,0.5,76 +spreading_maxsave,1.3690156000084244,10,400,0.5,78 +heuristic_maxsave,0.725636699993629,10,400,0.5,79 +spreading_maxsave,0.7612699999590404,1,400,0.5,25 +heuristic_maxsave,0.373372100002598,1,400,0.5,22 +spreading_maxsave,0.8087179000140168,2,400,0.5,32 +heuristic_maxsave,0.26761759998044,2,400,0.5,31 +spreading_maxsave,0.7900566000025719,3,400,0.5,33 +heuristic_maxsave,0.32558320002863184,3,400,0.5,34 +spreading_maxsave,1.015544299967587,5,400,0.5,35 +heuristic_maxsave,0.4805785000207834,5,400,0.5,36 +spreading_maxsave,1.0640604000072926,7,400,0.5,37 +heuristic_maxsave,0.7079374000313692,7,400,0.5,38 +spreading_maxsave,1.2139823000179604,10,400,0.5,40 +heuristic_maxsave,0.8028046999825165,10,400,0.5,41 +spreading_maxsave,0.6447457000031136,1,400,0.5,8 +heuristic_maxsave,0.2019828000338748,1,400,0.5,7 +spreading_maxsave,0.6813996999990195,2,400,0.5,9 +heuristic_maxsave,0.2662311000167392,2,400,0.5,10 +spreading_maxsave,0.8293738000211306,3,400,0.5,10 +heuristic_maxsave,0.36656789999688044,3,400,0.5,11 +spreading_maxsave,1.032389100000728,5,400,0.5,12 +heuristic_maxsave,0.415726299979724,5,400,0.5,13 +spreading_maxsave,0.9772298000170849,7,400,0.5,14 +heuristic_maxsave,0.5138811999931931,7,400,0.5,15 +spreading_maxsave,1.1681202999898233,10,400,0.5,17 +heuristic_maxsave,0.8856589000206441,10,400,0.5,18 +spreading_maxsave,0.7188531000283547,1,400,0.5,28 +heuristic_maxsave,0.22263870004098862,1,400,0.5,22 +spreading_maxsave,0.7374191000126302,2,400,0.5,39 +heuristic_maxsave,0.3313815000001341,2,400,0.5,36 +spreading_maxsave,0.8521106999833137,3,400,0.5,40 +heuristic_maxsave,0.3593490000348538,3,400,0.5,42 +spreading_maxsave,1.1070543000241742,5,400,0.5,42 +heuristic_maxsave,0.603667100018356,5,400,0.5,44 +spreading_maxsave,1.1092445999966003,7,400,0.5,44 +heuristic_maxsave,0.5214662000071257,7,400,0.5,46 +spreading_maxsave,1.4144794000312686,10,400,0.5,47 +heuristic_maxsave,0.7488946000230499,10,400,0.5,49 +spreading_maxsave,0.4546741000376642,1,400,0.8,22 +heuristic_maxsave,0.39130860002478585,1,400,0.8,21 +spreading_maxsave,0.7420145999640226,2,400,0.8,23 +heuristic_maxsave,0.4996032000053674,2,400,0.8,24 +spreading_maxsave,0.7148914000135846,3,400,0.8,24 +heuristic_maxsave,0.6197518000262789,3,400,0.8,25 +spreading_maxsave,0.8555290999938734,5,400,0.8,26 +heuristic_maxsave,0.7347938999882899,5,400,0.8,27 +spreading_maxsave,0.9098711000406183,7,400,0.8,28 +heuristic_maxsave,1.3575864000013098,7,400,0.8,29 +spreading_maxsave,1.2100104000419378,10,400,0.8,31 +heuristic_maxsave,1.3580646999762394,10,400,0.8,32 +spreading_maxsave,0.6270783999934793,1,400,0.8,13 +heuristic_maxsave,0.3315930000389926,1,400,0.8,13 +spreading_maxsave,0.7386583999614231,2,400,0.8,14 +heuristic_maxsave,0.45718850003322586,2,400,0.8,14 +spreading_maxsave,0.6330662000109442,3,400,0.8,15 +heuristic_maxsave,0.5102048999979161,3,400,0.8,15 +spreading_maxsave,0.7864257000037469,5,400,0.8,17 +heuristic_maxsave,0.9193274000426754,5,400,0.8,17 +spreading_maxsave,0.9387901999871247,7,400,0.8,19 +heuristic_maxsave,1.0922084000194445,7,400,0.8,19 +spreading_maxsave,1.2340592999826185,10,400,0.8,22 +heuristic_maxsave,1.6207878999994136,10,400,0.8,22 +spreading_maxsave,0.5463835999835283,1,400,0.8,25 +heuristic_maxsave,0.3230739000136964,1,400,0.8,24 +spreading_maxsave,0.6372343999682926,2,400,0.8,26 +heuristic_maxsave,0.46751580003183335,2,400,0.8,26 +spreading_maxsave,0.9016374000348151,3,400,0.8,27 +heuristic_maxsave,0.7039541000267491,3,400,0.8,27 +spreading_maxsave,0.8118607000214979,5,400,0.8,29 +heuristic_maxsave,0.798025400028564,5,400,0.8,29 +spreading_maxsave,0.9860856999875978,7,400,0.8,31 +heuristic_maxsave,1.133234899956733,7,400,0.8,31 +spreading_maxsave,1.2846410000347532,10,400,0.8,34 +heuristic_maxsave,1.390135299996473,10,400,0.8,34 +spreading_maxsave,0.5272687000106089,1,400,0.8,1 +heuristic_maxsave,0.24706099997274578,1,400,0.8,1 +spreading_maxsave,0.5451471999986097,2,400,0.8,2 +heuristic_maxsave,0.35336990002542734,2,400,0.8,2 +spreading_maxsave,0.6268494999967515,3,400,0.8,2 +heuristic_maxsave,0.5695582000189461,3,400,0.8,2 +spreading_maxsave,0.7679243999882601,5,400,0.8,2 +heuristic_maxsave,0.7665662000072189,5,400,0.8,2 +spreading_maxsave,0.8858205999713391,7,400,0.8,2 +heuristic_maxsave,0.8670242000371218,7,400,0.8,2 +spreading_maxsave,1.0695048000197858,10,400,0.8,2 +heuristic_maxsave,1.4619727000244893,10,400,0.8,2 +spreading_maxsave,0.650798799993936,1,400,0.8,28 +heuristic_maxsave,0.424418099981267,1,400,0.8,24 +spreading_maxsave,0.639764700026717,2,400,0.8,29 +heuristic_maxsave,0.561322099994868,2,400,0.8,29 +spreading_maxsave,0.750844300026074,3,400,0.8,30 +heuristic_maxsave,0.8612866999465041,3,400,0.8,30 +spreading_maxsave,0.8810389999998733,5,400,0.8,32 +heuristic_maxsave,0.9824450999731198,5,400,0.8,32 +spreading_maxsave,0.994032500020694,7,400,0.8,34 +heuristic_maxsave,1.4041685000411235,7,400,0.8,34 +spreading_maxsave,1.2991919000050984,10,400,0.8,37 +heuristic_maxsave,1.4545534999924712,10,400,0.8,37 +spreading_maxsave,0.5250599000137299,1,400,0.8,28 +heuristic_maxsave,0.5180497000110336,1,400,0.8,26 +spreading_maxsave,0.8211904999916442,2,400,0.8,29 +heuristic_maxsave,0.5510774999856949,2,400,0.8,30 +spreading_maxsave,0.6918721999973059,3,400,0.8,30 +heuristic_maxsave,0.7125151000218466,3,400,0.8,31 +spreading_maxsave,0.9501300000119954,5,400,0.8,32 +heuristic_maxsave,0.9478267999948002,5,400,0.8,33 +spreading_maxsave,1.1618390000076033,7,400,0.8,34 +heuristic_maxsave,1.1687081000418402,7,400,0.8,35 +spreading_maxsave,1.266055200016126,10,400,0.8,37 +heuristic_maxsave,1.5378542999969795,10,400,0.8,38 +spreading_maxsave,0.7371526000206359,1,400,0.8,38 +heuristic_maxsave,0.4823686999734491,1,400,0.8,37 +spreading_maxsave,0.7708653000299819,2,400,0.8,39 +heuristic_maxsave,0.6473940000287257,2,400,0.8,39 +spreading_maxsave,0.7680094999959692,3,400,0.8,40 +heuristic_maxsave,0.6768079000175931,3,400,0.8,40 +spreading_maxsave,0.8872507000342011,5,400,0.8,42 +heuristic_maxsave,1.0556261999881826,5,400,0.8,42 +spreading_maxsave,1.0770621999981813,7,400,0.8,44 +heuristic_maxsave,1.3023541000438854,7,400,0.8,44 +spreading_maxsave,1.2428558999672532,10,400,0.8,47 +heuristic_maxsave,1.6261427999706939,10,400,0.8,47 +spreading_maxsave,0.5139283000025898,1,400,0.8,24 +heuristic_maxsave,0.4053445999743417,1,400,0.8,25 +spreading_maxsave,0.8104822000022978,2,400,0.8,25 +heuristic_maxsave,0.5418617999530397,2,400,0.8,26 +spreading_maxsave,0.7324352000141516,3,400,0.8,26 +heuristic_maxsave,0.6905009999754839,3,400,0.8,27 +spreading_maxsave,0.8381816999753937,5,400,0.8,28 +heuristic_maxsave,0.8317198000149801,5,400,0.8,29 +spreading_maxsave,1.244214300008025,7,400,0.8,30 +heuristic_maxsave,1.1850657999748364,7,400,0.8,31 +spreading_maxsave,1.1552618999849074,10,400,0.8,33 +heuristic_maxsave,1.4665315999882296,10,400,0.8,34 +spreading_maxsave,0.6030600999947637,1,400,0.8,24 +heuristic_maxsave,0.5900598000152968,1,400,0.8,24 +spreading_maxsave,0.6390509000048041,2,400,0.8,25 +heuristic_maxsave,0.5277437000186183,2,400,0.8,25 +spreading_maxsave,0.6820443999604322,3,400,0.8,26 +heuristic_maxsave,0.6277904000016861,3,400,0.8,26 +spreading_maxsave,0.877071299997624,5,400,0.8,28 +heuristic_maxsave,0.8866336999926716,5,400,0.8,28 +spreading_maxsave,0.9528527000220492,7,400,0.8,30 +heuristic_maxsave,1.0869454000494443,7,400,0.8,30 +spreading_maxsave,1.376034599961713,10,400,0.8,33 +heuristic_maxsave,1.5075808999827132,10,400,0.8,33 +spreading_maxsave,0.4860744000179693,1,400,0.8,15 +heuristic_maxsave,0.39861390000442043,1,400,0.8,15 +spreading_maxsave,0.5634443000308238,2,400,0.8,16 +heuristic_maxsave,0.5430100000230595,2,400,0.8,16 +spreading_maxsave,0.6728860000148416,3,400,0.8,17 +heuristic_maxsave,0.5303234999882989,3,400,0.8,17 +spreading_maxsave,0.9196489000460133,5,400,0.8,19 +heuristic_maxsave,0.8112997999996878,5,400,0.8,19 +spreading_maxsave,1.0027675000019372,7,400,0.8,21 +heuristic_maxsave,1.032043799990788,7,400,0.8,21 +spreading_maxsave,1.082156100019347,10,400,0.8,24 +heuristic_maxsave,1.66049690003274,10,400,0.8,24 +,405.1742781000212,,,, diff --git a/experiments/firefighter_problem/spreading_maxsave_100_edge_prob.png b/experiments/firefighter_problem/spreading_maxsave_100_edge_prob.png new file mode 100644 index 0000000..95ea7ed Binary files /dev/null and b/experiments/firefighter_problem/spreading_maxsave_100_edge_prob.png differ diff --git a/experiments/firefighter_problem/spreading_maxsave_200_edge_prob.png b/experiments/firefighter_problem/spreading_maxsave_200_edge_prob.png new file mode 100644 index 0000000..dec3be5 Binary files /dev/null and b/experiments/firefighter_problem/spreading_maxsave_200_edge_prob.png differ diff --git a/experiments/firefighter_problem/spreading_maxsave_400_edge_prob.png b/experiments/firefighter_problem/spreading_maxsave_400_edge_prob.png new file mode 100644 index 0000000..dd0855d Binary files /dev/null and b/experiments/firefighter_problem/spreading_maxsave_400_edge_prob.png differ diff --git a/experiments/firefighter_problem/spreading_maxsave_budget.png b/experiments/firefighter_problem/spreading_maxsave_budget.png new file mode 100644 index 0000000..08ff707 Binary files /dev/null and b/experiments/firefighter_problem/spreading_maxsave_budget.png differ diff --git a/experiments/firefighter_problem/spreading_maxsave_preprocessed.csv b/experiments/firefighter_problem/spreading_maxsave_preprocessed.csv new file mode 100644 index 0000000..1a0c099 --- /dev/null +++ b/experiments/firefighter_problem/spreading_maxsave_preprocessed.csv @@ -0,0 +1,1081 @@ +algorithm,runtime,Budget,graph_nodes,edge_probability,Nodes_Saved +spreading_maxsave,0.0871678999974392,1,100.0,0.1,17 +heuristic_maxsave,0.0326152000343427,1,100.0,0.1,17 +spreading_maxsave,0.0824773000204004,2,100.0,0.1,24 +heuristic_maxsave,0.0324931000359356,2,100.0,0.1,25 +spreading_maxsave,0.260543999960646,3,100.0,0.1,31 +heuristic_maxsave,0.0392658999771811,3,100.0,0.1,31 +spreading_maxsave,0.1369477999978698,5,100.0,0.1,42 +heuristic_maxsave,0.1110940999933518,5,100.0,0.1,40 +spreading_maxsave,0.1628885000245645,7,100.0,0.1,44 +heuristic_maxsave,0.0541671000537462,7,100.0,0.1,46 +spreading_maxsave,0.2001562000368721,10,100.0,0.1,47 +heuristic_maxsave,0.0439562000101432,10,100.0,0.1,48 +spreading_maxsave,0.0564981999923475,1,100.0,0.1,5 +heuristic_maxsave,0.0294644000241532,1,100.0,0.1,5 +spreading_maxsave,0.0798642999725416,2,100.0,0.1,5 +heuristic_maxsave,0.0335905000101774,2,100.0,0.1,5 +spreading_maxsave,0.098236599995289,3,100.0,0.1,5 +heuristic_maxsave,0.0867586000240407,3,100.0,0.1,5 +spreading_maxsave,0.1370233999914489,5,100.0,0.1,5 +heuristic_maxsave,0.0499644999508746,5,100.0,0.1,5 +spreading_maxsave,0.1549528000177815,7,100.0,0.1,5 +heuristic_maxsave,0.0442304000025615,7,100.0,0.1,5 +spreading_maxsave,0.1916928999708034,10,100.0,0.1,5 +heuristic_maxsave,0.0413843999849632,10,100.0,0.1,5 +spreading_maxsave,0.0643041000002995,1,100.0,0.1,9 +heuristic_maxsave,0.0254370000329799,1,100.0,0.1,6 +spreading_maxsave,0.1398453000001609,2,100.0,0.1,12 +heuristic_maxsave,0.0326421999488957,2,100.0,0.1,9 +spreading_maxsave,0.1005105000222101,3,100.0,0.1,12 +heuristic_maxsave,0.0389373999787494,3,100.0,0.1,12 +spreading_maxsave,0.1355808000080287,5,100.0,0.1,13 +heuristic_maxsave,0.0530560999759472,5,100.0,0.1,16 +spreading_maxsave,0.2431689999648369,7,100.0,0.1,15 +heuristic_maxsave,0.064148599980399,7,100.0,0.1,17 +spreading_maxsave,0.2313140000333078,10,100.0,0.1,17 +heuristic_maxsave,0.0631910000229254,10,100.0,0.1,17 +spreading_maxsave,0.0598829999798908,1,100.0,0.1,6 +heuristic_maxsave,0.0257739999797195,1,100.0,0.1,6 +spreading_maxsave,0.0754482999909669,2,100.0,0.1,9 +heuristic_maxsave,0.034269800002221,2,100.0,0.1,9 +spreading_maxsave,0.0929622999974526,3,100.0,0.1,9 +heuristic_maxsave,0.1232490999973379,3,100.0,0.1,9 +spreading_maxsave,0.1467754999757744,5,100.0,0.1,9 +heuristic_maxsave,0.0495435000048019,5,100.0,0.1,9 +spreading_maxsave,0.1772472999873571,7,100.0,0.1,9 +heuristic_maxsave,0.0558750000200234,7,100.0,0.1,9 +spreading_maxsave,0.2268023999640718,10,100.0,0.1,9 +heuristic_maxsave,0.0559674000251106,10,100.0,0.1,9 +spreading_maxsave,0.0624477999517694,1,100.0,0.1,15 +heuristic_maxsave,0.0255588000291027,1,100.0,0.1,15 +spreading_maxsave,0.1430039000115357,2,100.0,0.1,22 +heuristic_maxsave,0.0418598999967798,2,100.0,0.1,20 +spreading_maxsave,0.1418998000444844,3,100.0,0.1,28 +heuristic_maxsave,0.0702529000118374,3,100.0,0.1,25 +spreading_maxsave,0.1975085999583825,5,100.0,0.1,33 +heuristic_maxsave,0.0481990000116638,5,100.0,0.1,32 +spreading_maxsave,0.239706499967724,7,100.0,0.1,35 +heuristic_maxsave,0.071809499990195,7,100.0,0.1,38 +spreading_maxsave,0.3098434999701567,10,100.0,0.1,38 +heuristic_maxsave,0.0411629999871365,10,100.0,0.1,39 +spreading_maxsave,0.0670214999699965,1,100.0,0.1,8 +heuristic_maxsave,0.0247258999734185,1,100.0,0.1,7 +spreading_maxsave,0.0748811999801546,2,100.0,0.1,12 +heuristic_maxsave,0.0354103000136092,2,100.0,0.1,9 +spreading_maxsave,0.1097750999615527,3,100.0,0.1,12 +heuristic_maxsave,0.0348783999797888,3,100.0,0.1,13 +spreading_maxsave,0.14335279999068,5,100.0,0.1,13 +heuristic_maxsave,0.0484541000332683,5,100.0,0.1,13 +spreading_maxsave,0.2263516000239178,7,100.0,0.1,13 +heuristic_maxsave,0.0464422999648377,7,100.0,0.1,13 +spreading_maxsave,0.1958923999918624,10,100.0,0.1,13 +heuristic_maxsave,0.0472616999759338,10,100.0,0.1,13 +spreading_maxsave,0.0579044999903999,1,100.0,0.1,18 +heuristic_maxsave,0.0233305000001564,1,100.0,0.1,16 +spreading_maxsave,0.0936477999784983,2,100.0,0.1,26 +heuristic_maxsave,0.0360745000070892,2,100.0,0.1,24 +spreading_maxsave,0.1140745000448077,3,100.0,0.1,33 +heuristic_maxsave,0.0380808000336401,3,100.0,0.1,30 +spreading_maxsave,0.2105161999934353,5,100.0,0.1,42 +heuristic_maxsave,0.1154998999554663,5,100.0,0.1,40 +spreading_maxsave,0.2302723999600857,7,100.0,0.1,45 +heuristic_maxsave,0.051699900010135,7,100.0,0.1,46 +spreading_maxsave,0.3037123000249266,10,100.0,0.1,47 +heuristic_maxsave,0.0679948999895714,10,100.0,0.1,50 +spreading_maxsave,0.0643683999660424,1,100.0,0.1,4 +heuristic_maxsave,0.0273929000250063,1,100.0,0.1,4 +spreading_maxsave,0.0790696000331081,2,100.0,0.1,6 +heuristic_maxsave,0.0321416999795474,2,100.0,0.1,6 +spreading_maxsave,0.1043478000210598,3,100.0,0.1,6 +heuristic_maxsave,0.1028783999499864,3,100.0,0.1,6 +spreading_maxsave,0.185642700002063,5,100.0,0.1,6 +heuristic_maxsave,0.0467560000251978,5,100.0,0.1,6 +spreading_maxsave,0.1958016999997198,7,100.0,0.1,6 +heuristic_maxsave,0.0579560999758541,7,100.0,0.1,6 +spreading_maxsave,0.2484250999987125,10,100.0,0.1,6 +heuristic_maxsave,0.0536347000161185,10,100.0,0.1,6 +spreading_maxsave,0.0823748999973759,1,100.0,0.1,11 +heuristic_maxsave,0.0384565999847836,1,100.0,0.1,10 +spreading_maxsave,0.0974326000432483,2,100.0,0.1,17 +heuristic_maxsave,0.0391667999792844,2,100.0,0.1,15 +spreading_maxsave,0.1427152000251226,3,100.0,0.1,22 +heuristic_maxsave,0.0455337999737821,3,100.0,0.1,19 +spreading_maxsave,0.1616103000123985,5,100.0,0.1,28 +heuristic_maxsave,0.1175424000248313,5,100.0,0.1,28 +spreading_maxsave,0.158801699988544,7,100.0,0.1,28 +heuristic_maxsave,0.0478477000142447,7,100.0,0.1,31 +spreading_maxsave,0.2047046999796293,10,100.0,0.1,31 +heuristic_maxsave,0.0371760999551042,10,100.0,0.1,31 +spreading_maxsave,0.0614874999737367,1,100.0,0.1,13 +heuristic_maxsave,0.0254712000023573,1,100.0,0.1,12 +spreading_maxsave,0.0936295000137761,2,100.0,0.1,17 +heuristic_maxsave,0.0315680000348947,2,100.0,0.1,16 +spreading_maxsave,0.1537959999986924,3,100.0,0.1,21 +heuristic_maxsave,0.0383208999992348,3,100.0,0.1,19 +spreading_maxsave,0.140881499974057,5,100.0,0.1,22 +heuristic_maxsave,0.0494594000047072,5,100.0,0.1,24 +spreading_maxsave,0.1497899999958463,7,100.0,0.1,24 +heuristic_maxsave,0.0549229999887757,7,100.0,0.1,28 +spreading_maxsave,0.1897194000193849,10,100.0,0.1,27 +heuristic_maxsave,0.1168007999658584,10,100.0,0.1,29 +spreading_maxsave,0.0947915000142529,1,100.0,0.5,17 +heuristic_maxsave,0.0385419999947771,1,100.0,0.5,17 +spreading_maxsave,0.0684305999893695,2,100.0,0.5,22 +heuristic_maxsave,0.0561150000430643,2,100.0,0.5,23 +spreading_maxsave,0.0871860000188462,3,100.0,0.5,23 +heuristic_maxsave,0.04609800002072,3,100.0,0.5,24 +spreading_maxsave,0.1230454999604262,5,100.0,0.5,25 +heuristic_maxsave,0.0679362000082619,5,100.0,0.5,26 +spreading_maxsave,0.1341255000443197,7,100.0,0.5,27 +heuristic_maxsave,0.1418993999832309,7,100.0,0.5,28 +spreading_maxsave,0.1636091000400483,10,100.0,0.5,30 +heuristic_maxsave,0.1386838000034913,10,100.0,0.5,31 +spreading_maxsave,0.047473800019361,1,100.0,0.5,4 +heuristic_maxsave,0.0249955000472255,1,100.0,0.5,5 +spreading_maxsave,0.0605437000049278,2,100.0,0.5,5 +heuristic_maxsave,0.0397808999987319,2,100.0,0.5,6 +spreading_maxsave,0.094061599986162,3,100.0,0.5,6 +heuristic_maxsave,0.0453524999902583,3,100.0,0.5,7 +spreading_maxsave,0.1553810999612324,5,100.0,0.5,8 +heuristic_maxsave,0.087660200020764,5,100.0,0.5,8 +spreading_maxsave,0.1218708000378683,7,100.0,0.5,8 +heuristic_maxsave,0.0768394999904558,7,100.0,0.5,8 +spreading_maxsave,0.1666290999855846,10,100.0,0.5,8 +heuristic_maxsave,0.1088300999836064,10,100.0,0.5,8 +spreading_maxsave,0.0595833999686874,1,100.0,0.5,14 +heuristic_maxsave,0.0353497000178322,1,100.0,0.5,12 +spreading_maxsave,0.0718957000062801,2,100.0,0.5,18 +heuristic_maxsave,0.0926236999803222,2,100.0,0.5,18 +spreading_maxsave,0.1232718999963253,3,100.0,0.5,19 +heuristic_maxsave,0.0566532000084407,3,100.0,0.5,19 +spreading_maxsave,0.1142411999753676,5,100.0,0.5,21 +heuristic_maxsave,0.0706681000301614,5,100.0,0.5,21 +spreading_maxsave,0.1371160999988205,7,100.0,0.5,23 +heuristic_maxsave,0.0789570999913849,7,100.0,0.5,23 +spreading_maxsave,0.1697548999800346,10,100.0,0.5,26 +heuristic_maxsave,0.2281501999823376,10,100.0,0.5,26 +spreading_maxsave,0.049964000005275,1,100.0,0.5,1 +heuristic_maxsave,0.0303960000164806,1,100.0,0.5,1 +spreading_maxsave,0.0949655000003986,2,100.0,0.5,2 +heuristic_maxsave,0.0580743000027723,2,100.0,0.5,2 +spreading_maxsave,0.0774058000533841,3,100.0,0.5,2 +heuristic_maxsave,0.0455300000030547,3,100.0,0.5,2 +spreading_maxsave,0.0996114999870769,5,100.0,0.5,2 +heuristic_maxsave,0.0618575999978929,5,100.0,0.5,2 +spreading_maxsave,0.2010184999671764,7,100.0,0.5,2 +heuristic_maxsave,0.1332833000342361,7,100.0,0.5,2 +spreading_maxsave,0.1469528000452555,10,100.0,0.5,2 +heuristic_maxsave,0.1493482000078074,10,100.0,0.5,2 +spreading_maxsave,0.0640827000024728,1,100.0,0.5,2 +heuristic_maxsave,0.0309061999432742,1,100.0,0.5,2 +spreading_maxsave,0.0607292000204324,2,100.0,0.5,3 +heuristic_maxsave,0.040855300030671,2,100.0,0.5,3 +spreading_maxsave,0.0798761000041849,3,100.0,0.5,4 +heuristic_maxsave,0.115307500003837,3,100.0,0.5,4 +spreading_maxsave,0.1165616000071168,5,100.0,0.5,5 +heuristic_maxsave,0.0754565999959595,5,100.0,0.5,5 +spreading_maxsave,0.1302691000164486,7,100.0,0.5,5 +heuristic_maxsave,0.0830842000432312,7,100.0,0.5,5 +spreading_maxsave,0.174819000007119,10,100.0,0.5,5 +heuristic_maxsave,0.1143917000154033,10,100.0,0.5,5 +spreading_maxsave,0.0532541999709792,1,100.0,0.5,8 +heuristic_maxsave,0.0300373000209219,1,100.0,0.5,7 +spreading_maxsave,0.181272700021509,2,100.0,0.5,9 +heuristic_maxsave,0.0434397999779321,2,100.0,0.5,9 +spreading_maxsave,0.0993064000504091,3,100.0,0.5,10 +heuristic_maxsave,0.0755838999757543,3,100.0,0.5,10 +spreading_maxsave,0.131768099963665,5,100.0,0.5,12 +heuristic_maxsave,0.0653993000159971,5,100.0,0.5,12 +spreading_maxsave,0.1764149999944493,7,100.0,0.5,14 +heuristic_maxsave,0.0778001000289805,7,100.0,0.5,14 +spreading_maxsave,0.2802000999799929,10,100.0,0.5,17 +heuristic_maxsave,0.1157376000192016,10,100.0,0.5,17 +spreading_maxsave,0.0787331000319682,1,100.0,0.5,7 +heuristic_maxsave,0.0325653000036254,1,100.0,0.5,7 +spreading_maxsave,0.0797358999843709,2,100.0,0.5,8 +heuristic_maxsave,0.0432084000203758,2,100.0,0.5,8 +spreading_maxsave,0.0934114000410772,3,100.0,0.5,9 +heuristic_maxsave,0.0476936000050045,3,100.0,0.5,9 +spreading_maxsave,0.1090088000055402,5,100.0,0.5,11 +heuristic_maxsave,0.0694739000173285,5,100.0,0.5,11 +spreading_maxsave,0.231234900013078,7,100.0,0.5,13 +heuristic_maxsave,0.1233713999972678,7,100.0,0.5,13 +spreading_maxsave,0.2182488999678753,10,100.0,0.5,13 +heuristic_maxsave,0.1412754000048153,10,100.0,0.5,13 +spreading_maxsave,0.0614051999873481,1,100.0,0.5,13 +heuristic_maxsave,0.0317409000126645,1,100.0,0.5,12 +spreading_maxsave,0.0706172999925911,2,100.0,0.5,16 +heuristic_maxsave,0.0500365999760106,2,100.0,0.5,17 +spreading_maxsave,0.0893624000018462,3,100.0,0.5,17 +heuristic_maxsave,0.0540452999994158,3,100.0,0.5,18 +spreading_maxsave,0.1078819999820552,5,100.0,0.5,19 +heuristic_maxsave,0.0894793999614194,5,100.0,0.5,20 +spreading_maxsave,0.1406924999901093,7,100.0,0.5,21 +heuristic_maxsave,0.08168610004941,7,100.0,0.5,22 +spreading_maxsave,0.1994573000119999,10,100.0,0.5,24 +heuristic_maxsave,0.1097611000295728,10,100.0,0.5,25 +spreading_maxsave,0.0690289000049233,1,100.0,0.5,11 +heuristic_maxsave,0.0393718999694101,1,100.0,0.5,8 +spreading_maxsave,0.1382925999932922,2,100.0,0.5,14 +heuristic_maxsave,0.0502667999826371,2,100.0,0.5,15 +spreading_maxsave,0.0812993999570608,3,100.0,0.5,15 +heuristic_maxsave,0.0575371999875642,3,100.0,0.5,16 +spreading_maxsave,0.1005193999735638,5,100.0,0.5,17 +heuristic_maxsave,0.0889432999538257,5,100.0,0.5,18 +spreading_maxsave,0.1377288000076078,7,100.0,0.5,19 +heuristic_maxsave,0.0985215000109747,7,100.0,0.5,20 +spreading_maxsave,0.1637671000207774,10,100.0,0.5,22 +heuristic_maxsave,0.1098399999900721,10,100.0,0.5,23 +spreading_maxsave,0.0767141999676823,1,100.0,0.5,15 +heuristic_maxsave,0.0372939000371843,1,100.0,0.5,12 +spreading_maxsave,0.08707070001401,2,100.0,0.5,18 +heuristic_maxsave,0.0431684000068344,2,100.0,0.5,19 +spreading_maxsave,0.0838279000017792,3,100.0,0.5,19 +heuristic_maxsave,0.0505153999547474,3,100.0,0.5,20 +spreading_maxsave,0.1254987000138498,5,100.0,0.5,21 +heuristic_maxsave,0.0724485000246204,5,100.0,0.5,22 +spreading_maxsave,0.1322290999814868,7,100.0,0.5,23 +heuristic_maxsave,0.1411798999761231,7,100.0,0.5,24 +spreading_maxsave,0.17085270001553,10,100.0,0.5,26 +heuristic_maxsave,0.1138308999943547,10,100.0,0.5,27 +spreading_maxsave,0.0579622999648563,1,100.0,0.8,8 +heuristic_maxsave,0.0384767000214196,1,100.0,0.8,8 +spreading_maxsave,0.0607351000071503,2,100.0,0.8,9 +heuristic_maxsave,0.0442199000390246,2,100.0,0.8,9 +spreading_maxsave,0.0885312999598681,3,100.0,0.8,10 +heuristic_maxsave,0.0587596999830566,3,100.0,0.8,10 +spreading_maxsave,0.1056398000218905,5,100.0,0.8,12 +heuristic_maxsave,0.178468799975235,5,100.0,0.8,12 +spreading_maxsave,0.1238092999556101,7,100.0,0.8,14 +heuristic_maxsave,0.1428144000237807,7,100.0,0.8,14 +spreading_maxsave,0.1712345000123605,10,100.0,0.8,17 +heuristic_maxsave,0.1801751999882981,10,100.0,0.8,17 +spreading_maxsave,0.0587042999686673,1,100.0,0.8,7 +heuristic_maxsave,0.1025526000303216,1,100.0,0.8,7 +spreading_maxsave,0.0609856999944895,2,100.0,0.8,8 +heuristic_maxsave,0.0518469999660737,2,100.0,0.8,8 +spreading_maxsave,0.0820461999974213,3,100.0,0.8,9 +heuristic_maxsave,0.0592775999684818,3,100.0,0.8,9 +spreading_maxsave,0.1084379000240005,5,100.0,0.8,11 +heuristic_maxsave,0.0833057000418193,5,100.0,0.8,11 +spreading_maxsave,0.160705299989786,7,100.0,0.8,13 +heuristic_maxsave,0.1155572999850846,7,100.0,0.8,13 +spreading_maxsave,0.2277369000366889,10,100.0,0.8,16 +heuristic_maxsave,0.1880788999842479,10,100.0,0.8,16 +spreading_maxsave,0.0609081999864429,1,100.0,0.8,8 +heuristic_maxsave,0.0451439000316895,1,100.0,0.8,8 +spreading_maxsave,0.0749574999790638,2,100.0,0.8,9 +heuristic_maxsave,0.0452673999825492,2,100.0,0.8,9 +spreading_maxsave,0.071730000025127,3,100.0,0.8,10 +heuristic_maxsave,0.0985416999901644,3,100.0,0.8,10 +spreading_maxsave,0.1752075999975204,5,100.0,0.8,12 +heuristic_maxsave,0.0958238000166602,5,100.0,0.8,12 +spreading_maxsave,0.132878000033088,7,100.0,0.8,14 +heuristic_maxsave,0.1219096000422723,7,100.0,0.8,14 +spreading_maxsave,0.1603028000099584,10,100.0,0.8,17 +heuristic_maxsave,0.1863364000455476,10,100.0,0.8,17 +spreading_maxsave,0.0462321999948471,1,100.0,0.8,2 +heuristic_maxsave,0.0976912000332959,1,100.0,0.8,2 +spreading_maxsave,0.0905350999673828,2,100.0,0.8,3 +heuristic_maxsave,0.0396315000252798,2,100.0,0.8,3 +spreading_maxsave,0.0695548999938182,3,100.0,0.8,4 +heuristic_maxsave,0.0606514000101015,3,100.0,0.8,4 +spreading_maxsave,0.1024583000107668,5,100.0,0.8,6 +heuristic_maxsave,0.08290430001216,5,100.0,0.8,6 +spreading_maxsave,0.1254036999889649,7,100.0,0.8,6 +heuristic_maxsave,0.1669834000058472,7,100.0,0.8,6 +spreading_maxsave,0.2199182999902404,10,100.0,0.8,6 +heuristic_maxsave,0.171207100036554,10,100.0,0.8,6 +spreading_maxsave,0.0515482000191696,1,100.0,0.8,6 +heuristic_maxsave,0.0301512999576516,1,100.0,0.8,6 +spreading_maxsave,0.060417300031986,2,100.0,0.8,7 +heuristic_maxsave,0.0546422000043094,2,100.0,0.8,7 +spreading_maxsave,0.0918464999995194,3,100.0,0.8,8 +heuristic_maxsave,0.0601657999795861,3,100.0,0.8,8 +spreading_maxsave,0.1058735999977216,5,100.0,0.8,10 +heuristic_maxsave,0.1741547000128775,5,100.0,0.8,10 +spreading_maxsave,0.1395321000018157,7,100.0,0.8,10 +heuristic_maxsave,0.1222694999887608,7,100.0,0.8,10 +spreading_maxsave,0.1609003000194206,10,100.0,0.8,10 +heuristic_maxsave,0.1723226999747567,10,100.0,0.8,10 +spreading_maxsave,0.0507222999585792,1,100.0,0.8,7 +heuristic_maxsave,0.0359638999798335,1,100.0,0.8,7 +spreading_maxsave,0.1386187999742105,2,100.0,0.8,8 +heuristic_maxsave,0.0646107000065967,2,100.0,0.8,8 +spreading_maxsave,0.0930013000033795,3,100.0,0.8,9 +heuristic_maxsave,0.0590362999937497,3,100.0,0.8,9 +spreading_maxsave,0.1141748999943956,5,100.0,0.8,11 +heuristic_maxsave,0.1166179000283591,5,100.0,0.8,11 +spreading_maxsave,0.1300535000045783,7,100.0,0.8,13 +heuristic_maxsave,0.1189691000035964,7,100.0,0.8,13 +spreading_maxsave,0.2372028999961912,10,100.0,0.8,16 +heuristic_maxsave,0.1895428000134416,10,100.0,0.8,16 +spreading_maxsave,0.0463915000436827,1,100.0,0.8,1 +heuristic_maxsave,0.0329606999875977,1,100.0,0.8,1 +spreading_maxsave,0.0568824000074528,2,100.0,0.8,2 +heuristic_maxsave,0.041347799997311,2,100.0,0.8,2 +spreading_maxsave,0.1050545999896712,3,100.0,0.8,3 +heuristic_maxsave,0.0581269999966025,3,100.0,0.8,3 +spreading_maxsave,0.1014745000284165,5,100.0,0.8,5 +heuristic_maxsave,0.0790910000214353,5,100.0,0.8,5 +spreading_maxsave,0.1829336000373587,7,100.0,0.8,7 +heuristic_maxsave,0.1824219999834895,7,100.0,0.8,7 +spreading_maxsave,0.2109194999793544,10,100.0,0.8,8 +heuristic_maxsave,0.1449389000190422,10,100.0,0.8,8 +spreading_maxsave,0.0658809000160545,1,100.0,0.8,3 +heuristic_maxsave,0.0310767000191845,1,100.0,0.8,3 +spreading_maxsave,0.0558472999837249,2,100.0,0.8,4 +heuristic_maxsave,0.0439906000392511,2,100.0,0.8,4 +spreading_maxsave,0.0743411000003106,3,100.0,0.8,5 +heuristic_maxsave,0.0546135000186041,3,100.0,0.8,5 +spreading_maxsave,0.1036622999818064,5,100.0,0.8,7 +heuristic_maxsave,0.1107685000170022,5,100.0,0.8,7 +spreading_maxsave,0.1161850999924354,7,100.0,0.8,7 +heuristic_maxsave,0.1130346999852918,7,100.0,0.8,7 +spreading_maxsave,0.1587512000114657,10,100.0,0.8,7 +heuristic_maxsave,0.1686734000104479,10,100.0,0.8,7 +spreading_maxsave,0.0584162999875843,1,100.0,0.8,11 +heuristic_maxsave,0.0453083000029437,1,100.0,0.8,11 +spreading_maxsave,0.1785390999866649,2,100.0,0.8,12 +heuristic_maxsave,0.0531652999925427,2,100.0,0.8,12 +spreading_maxsave,0.0782315999967977,3,100.0,0.8,13 +heuristic_maxsave,0.076277999964077,3,100.0,0.8,13 +spreading_maxsave,0.1042689000023529,5,100.0,0.8,15 +heuristic_maxsave,0.1089458999922499,5,100.0,0.8,15 +spreading_maxsave,0.1290392999653704,7,100.0,0.8,17 +heuristic_maxsave,0.1256022999878041,7,100.0,0.8,17 +spreading_maxsave,0.1807747000129893,10,100.0,0.8,20 +heuristic_maxsave,0.1803324000211432,10,100.0,0.8,20 +spreading_maxsave,0.046579300018493,1,100.0,0.8,1 +heuristic_maxsave,0.0307012999546714,1,100.0,0.8,1 +spreading_maxsave,0.0585293000331148,2,100.0,0.8,1 +heuristic_maxsave,0.0617615000228397,2,100.0,0.8,1 +spreading_maxsave,0.0861770000192336,3,100.0,0.8,1 +heuristic_maxsave,0.0607064999639987,3,100.0,0.8,1 +spreading_maxsave,0.0999483999912627,5,100.0,0.8,1 +heuristic_maxsave,0.1699580000131391,5,100.0,0.8,1 +spreading_maxsave,0.1392843999783508,7,100.0,0.8,1 +heuristic_maxsave,0.1276341000339016,7,100.0,0.8,1 +spreading_maxsave,0.1581237000063993,10,100.0,0.8,1 +heuristic_maxsave,0.1714242000016383,10,100.0,0.8,1 +spreading_maxsave,0.2034196000313386,1,200.0,0.1,15 +heuristic_maxsave,0.140557800012175,1,200.0,0.1,13 +spreading_maxsave,0.2626188999856822,2,200.0,0.1,23 +heuristic_maxsave,0.080038699961733,2,200.0,0.1,17 +spreading_maxsave,0.2727319999830797,3,200.0,0.1,30 +heuristic_maxsave,0.1140278999810107,3,200.0,0.1,21 +spreading_maxsave,0.5272406000294723,5,200.0,0.1,41 +heuristic_maxsave,0.1198531999834813,5,200.0,0.1,33 +spreading_maxsave,0.4921878000022843,7,200.0,0.1,44 +heuristic_maxsave,0.1246394999907352,7,200.0,0.1,44 +spreading_maxsave,0.8032811000011861,10,200.0,0.1,46 +heuristic_maxsave,0.1226862000185065,10,200.0,0.1,47 +spreading_maxsave,0.1992436999571509,1,200.0,0.1,31 +heuristic_maxsave,0.0622355999657884,1,200.0,0.1,31 +spreading_maxsave,0.3498484000447206,2,200.0,0.1,45 +heuristic_maxsave,0.0784918999997899,2,200.0,0.1,44 +spreading_maxsave,0.3429876999580301,3,200.0,0.1,57 +heuristic_maxsave,0.093828399956692,3,200.0,0.1,53 +spreading_maxsave,0.4580061999731697,5,200.0,0.1,76 +heuristic_maxsave,0.0976029000012204,5,200.0,0.1,71 +spreading_maxsave,0.5484400000423193,7,200.0,0.1,89 +heuristic_maxsave,0.1153079000068828,7,200.0,0.1,81 +spreading_maxsave,0.5694460999802686,10,200.0,0.1,92 +heuristic_maxsave,0.2184414999792352,10,200.0,0.1,92 +spreading_maxsave,0.2398438000236638,1,200.0,0.1,10 +heuristic_maxsave,0.058971999969799,1,200.0,0.1,6 +spreading_maxsave,0.3083875000011176,2,200.0,0.1,15 +heuristic_maxsave,0.0780630999943241,2,200.0,0.1,12 +spreading_maxsave,0.2816296000382863,3,200.0,0.1,18 +heuristic_maxsave,0.1094292000052519,3,200.0,0.1,17 +spreading_maxsave,0.4298146000364795,5,200.0,0.1,19 +heuristic_maxsave,0.1095308999647386,5,200.0,0.1,19 +spreading_maxsave,0.4193704000208527,7,200.0,0.1,19 +heuristic_maxsave,0.1237429999746382,7,200.0,0.1,19 +spreading_maxsave,0.5561525999801233,10,200.0,0.1,19 +heuristic_maxsave,0.1085296999663114,10,200.0,0.1,19 +spreading_maxsave,0.2370366999530233,1,200.0,0.1,24 +heuristic_maxsave,0.0729631999856792,1,200.0,0.1,24 +spreading_maxsave,0.2517604999593459,2,200.0,0.1,37 +heuristic_maxsave,0.106593000004068,2,200.0,0.1,34 +spreading_maxsave,0.4076805000077002,3,200.0,0.1,49 +heuristic_maxsave,0.1107435000012628,3,200.0,0.1,42 +spreading_maxsave,0.4572325000190176,5,200.0,0.1,63 +heuristic_maxsave,0.1057443000026978,5,200.0,0.1,55 +spreading_maxsave,0.5332056999905035,7,200.0,0.1,71 +heuristic_maxsave,0.1231465000309981,7,200.0,0.1,63 +spreading_maxsave,0.6110409999964759,10,200.0,0.1,73 +heuristic_maxsave,0.1145546999759972,10,200.0,0.1,79 +spreading_maxsave,0.1682283999980427,1,200.0,0.1,15 +heuristic_maxsave,0.0512443999759852,1,200.0,0.1,12 +spreading_maxsave,0.2748029999784194,2,200.0,0.1,25 +heuristic_maxsave,0.1508851000107824,2,200.0,0.1,18 +spreading_maxsave,0.2755275999661535,3,200.0,0.1,33 +heuristic_maxsave,0.1047744000097736,3,200.0,0.1,24 +spreading_maxsave,0.4485907999915071,5,200.0,0.1,45 +heuristic_maxsave,0.1169960999977774,5,200.0,0.1,30 +spreading_maxsave,0.4879001999506727,7,200.0,0.1,46 +heuristic_maxsave,0.1244320999830961,7,200.0,0.1,45 +spreading_maxsave,0.6306231999769807,10,200.0,0.1,49 +heuristic_maxsave,0.1087235999875702,10,200.0,0.1,51 +spreading_maxsave,0.2438887999742292,1,200.0,0.1,20 +heuristic_maxsave,0.0771593999816104,1,200.0,0.1,18 +spreading_maxsave,0.2500297999940812,2,200.0,0.1,34 +heuristic_maxsave,0.1044387999572791,2,200.0,0.1,27 +spreading_maxsave,0.3109865000005811,3,200.0,0.1,44 +heuristic_maxsave,0.0878780999919399,3,200.0,0.1,37 +spreading_maxsave,0.6536024999804795,5,200.0,0.1,61 +heuristic_maxsave,0.1092114999773912,5,200.0,0.1,54 +spreading_maxsave,0.4697406000341289,7,200.0,0.1,72 +heuristic_maxsave,0.120093600009568,7,200.0,0.1,66 +spreading_maxsave,0.672519400017336,10,200.0,0.1,75 +heuristic_maxsave,0.1413275999948382,10,200.0,0.1,76 +spreading_maxsave,0.1906313999788835,1,200.0,0.1,28 +heuristic_maxsave,0.0540868999669328,1,200.0,0.1,25 +spreading_maxsave,0.296982100000605,2,200.0,0.1,40 +heuristic_maxsave,0.0745826000347733,2,200.0,0.1,38 +spreading_maxsave,0.3882549999980256,3,200.0,0.1,50 +heuristic_maxsave,0.0924575999961234,3,200.0,0.1,46 +spreading_maxsave,0.3851208999985829,5,200.0,0.1,66 +heuristic_maxsave,0.1310095000080764,5,200.0,0.1,59 +spreading_maxsave,0.5501699000014924,7,200.0,0.1,77 +heuristic_maxsave,0.1119668000028468,7,200.0,0.1,69 +spreading_maxsave,0.6511672000051476,10,200.0,0.1,80 +heuristic_maxsave,0.1331820999621413,10,200.0,0.1,79 +spreading_maxsave,0.1826992999995127,1,200.0,0.1,15 +heuristic_maxsave,0.0574034000164829,1,200.0,0.1,9 +spreading_maxsave,0.3927942999871447,2,200.0,0.1,26 +heuristic_maxsave,0.0869356000330299,2,200.0,0.1,18 +spreading_maxsave,0.2891749999835156,3,200.0,0.1,35 +heuristic_maxsave,0.1171264000004157,3,200.0,0.1,26 +spreading_maxsave,0.4806969999917783,5,200.0,0.1,49 +heuristic_maxsave,0.119305100000929,5,200.0,0.1,36 +spreading_maxsave,0.4650688000256195,7,200.0,0.1,59 +heuristic_maxsave,0.123432699998375,7,200.0,0.1,49 +spreading_maxsave,0.5898283999995328,10,200.0,0.1,61 +heuristic_maxsave,0.1216880000429228,10,200.0,0.1,64 +spreading_maxsave,0.1767225000075996,1,200.0,0.1,15 +heuristic_maxsave,0.0555304000154137,1,200.0,0.1,14 +spreading_maxsave,0.2522677999804728,2,200.0,0.1,24 +heuristic_maxsave,0.0855635000043548,2,200.0,0.1,20 +spreading_maxsave,0.4057425999781117,3,200.0,0.1,31 +heuristic_maxsave,0.0966203999705612,3,200.0,0.1,25 +spreading_maxsave,0.4284159000380896,5,200.0,0.1,43 +heuristic_maxsave,0.1155388000188395,5,200.0,0.1,37 +spreading_maxsave,0.4669641000218689,7,200.0,0.1,45 +heuristic_maxsave,0.1188826999859884,7,200.0,0.1,46 +spreading_maxsave,0.5607535000308417,10,200.0,0.1,47 +heuristic_maxsave,0.1049914000323042,10,200.0,0.1,47 +spreading_maxsave,0.2391750999959185,1,200.0,0.1,23 +heuristic_maxsave,0.0765264000510796,1,200.0,0.1,23 +spreading_maxsave,0.2487374999909661,2,200.0,0.1,34 +heuristic_maxsave,0.0691784000373445,2,200.0,0.1,30 +spreading_maxsave,0.3167514000087976,3,200.0,0.1,43 +heuristic_maxsave,0.1606795000261627,3,200.0,0.1,35 +spreading_maxsave,0.3789206999936141,5,200.0,0.1,56 +heuristic_maxsave,0.1371342000202275,5,200.0,0.1,44 +spreading_maxsave,0.5711444999906234,7,200.0,0.1,62 +heuristic_maxsave,0.1419412000104785,7,200.0,0.1,52 +spreading_maxsave,0.6670626999693923,10,200.0,0.1,63 +heuristic_maxsave,0.1278017000295221,10,200.0,0.1,66 +spreading_maxsave,0.1731109999818727,1,200.0,0.5,10 +heuristic_maxsave,0.0788998999632895,1,200.0,0.5,9 +spreading_maxsave,0.2649374000029638,2,200.0,0.5,12 +heuristic_maxsave,0.1164245000109076,2,200.0,0.5,13 +spreading_maxsave,0.2894808000419289,3,200.0,0.5,13 +heuristic_maxsave,0.1129067000001668,3,200.0,0.5,14 +spreading_maxsave,0.3506806999794207,5,200.0,0.5,15 +heuristic_maxsave,0.1411962999845855,5,200.0,0.5,16 +spreading_maxsave,0.3292590000201016,7,200.0,0.5,17 +heuristic_maxsave,0.1870600000256672,7,200.0,0.5,18 +spreading_maxsave,0.495586099976208,10,200.0,0.5,18 +heuristic_maxsave,0.2187611000263132,10,200.0,0.5,18 +spreading_maxsave,0.2270472999662161,1,200.0,0.5,24 +heuristic_maxsave,0.0888808000017888,1,200.0,0.5,17 +spreading_maxsave,0.4033233000081964,2,200.0,0.5,28 +heuristic_maxsave,0.1147939999937079,2,200.0,0.5,28 +spreading_maxsave,0.245236000046134,3,200.0,0.5,29 +heuristic_maxsave,0.1572133000008762,3,200.0,0.5,30 +spreading_maxsave,0.2968413000344299,5,200.0,0.5,31 +heuristic_maxsave,0.1948364999843761,5,200.0,0.5,32 +spreading_maxsave,0.3449677999597043,7,200.0,0.5,33 +heuristic_maxsave,0.2802219999721274,7,200.0,0.5,34 +spreading_maxsave,0.4639442000188865,10,200.0,0.5,36 +heuristic_maxsave,0.2456537000252865,10,200.0,0.5,37 +spreading_maxsave,0.2086282999953255,1,200.0,0.5,22 +heuristic_maxsave,0.0753760999650694,1,200.0,0.5,20 +spreading_maxsave,0.2165795000037178,2,200.0,0.5,29 +heuristic_maxsave,0.1279199999989941,2,200.0,0.5,30 +spreading_maxsave,0.3090492999763228,3,200.0,0.5,30 +heuristic_maxsave,0.1667663000407628,3,200.0,0.5,31 +spreading_maxsave,0.3312145000090822,5,200.0,0.5,32 +heuristic_maxsave,0.2498657999676652,5,200.0,0.5,33 +spreading_maxsave,0.4063476999872364,7,200.0,0.5,34 +heuristic_maxsave,0.1821173999924212,7,200.0,0.5,35 +spreading_maxsave,0.5284660999896005,10,200.0,0.5,37 +heuristic_maxsave,0.2370731999981217,10,200.0,0.5,38 +spreading_maxsave,0.2714187000528909,1,200.0,0.5,15 +heuristic_maxsave,0.0941184000112116,1,200.0,0.5,12 +spreading_maxsave,0.2091370000271126,2,200.0,0.5,18 +heuristic_maxsave,0.1287410999648273,2,200.0,0.5,18 +spreading_maxsave,0.2672641000244766,3,200.0,0.5,19 +heuristic_maxsave,0.1994836999801919,3,200.0,0.5,20 +spreading_maxsave,0.2981535000144504,5,200.0,0.5,21 +heuristic_maxsave,0.1789638000191189,5,200.0,0.5,22 +spreading_maxsave,0.4638069000211544,7,200.0,0.5,23 +heuristic_maxsave,0.2134313000133261,7,200.0,0.5,24 +spreading_maxsave,0.5427520999801345,10,200.0,0.5,26 +heuristic_maxsave,0.2393694000202231,10,200.0,0.5,27 +spreading_maxsave,0.2100541000254452,1,200.0,0.5,23 +heuristic_maxsave,0.0816271000076085,1,200.0,0.5,19 +spreading_maxsave,0.3068525000126101,2,200.0,0.5,30 +heuristic_maxsave,0.1222581000183709,2,200.0,0.5,29 +spreading_maxsave,0.3039056999841705,3,200.0,0.5,31 +heuristic_maxsave,0.1013870000024326,3,200.0,0.5,32 +spreading_maxsave,0.4060017999727279,5,200.0,0.5,33 +heuristic_maxsave,0.1509630000218749,5,200.0,0.5,34 +spreading_maxsave,0.3851869999780319,7,200.0,0.5,35 +heuristic_maxsave,0.3338732999982312,7,200.0,0.5,36 +spreading_maxsave,0.5281620000023395,10,200.0,0.5,38 +heuristic_maxsave,0.3236653999774717,10,200.0,0.5,39 +spreading_maxsave,0.2468019999796524,1,200.0,0.5,34 +heuristic_maxsave,0.0966533999890089,1,200.0,0.5,30 +spreading_maxsave,0.2734864000231027,2,200.0,0.5,47 +heuristic_maxsave,0.1937617999501526,2,200.0,0.5,47 +spreading_maxsave,0.2868445999920368,3,200.0,0.5,49 +heuristic_maxsave,0.1636586000095121,3,200.0,0.5,50 +spreading_maxsave,0.4177994999918155,5,200.0,0.5,51 +heuristic_maxsave,0.16417340002954,5,200.0,0.5,52 +spreading_maxsave,0.3689600999932736,7,200.0,0.5,53 +heuristic_maxsave,0.2924888000125065,7,200.0,0.5,54 +spreading_maxsave,0.5096511000301689,10,200.0,0.5,56 +heuristic_maxsave,0.2524329000152647,10,200.0,0.5,57 +spreading_maxsave,0.2690585000091232,1,200.0,0.5,34 +heuristic_maxsave,0.115586899977643,1,200.0,0.5,33 +spreading_maxsave,0.2672153999446891,2,200.0,0.5,48 +heuristic_maxsave,0.1436463000136427,2,200.0,0.5,43 +spreading_maxsave,0.3506740000448189,3,200.0,0.5,49 +heuristic_maxsave,0.1966035999939777,3,200.0,0.5,50 +spreading_maxsave,0.3257808000198565,5,200.0,0.5,51 +heuristic_maxsave,0.2772436999948695,5,200.0,0.5,52 +spreading_maxsave,0.4158801999874413,7,200.0,0.5,53 +heuristic_maxsave,0.2038834000122733,7,200.0,0.5,54 +spreading_maxsave,0.5159435999812558,10,200.0,0.5,56 +heuristic_maxsave,0.2788665000116452,10,200.0,0.5,57 +spreading_maxsave,0.2019861000007949,1,200.0,0.5,14 +heuristic_maxsave,0.140605200023856,1,200.0,0.5,8 +spreading_maxsave,0.2326678999816067,2,200.0,0.5,15 +heuristic_maxsave,0.0945734999841079,2,200.0,0.5,16 +spreading_maxsave,0.3066790000302717,3,200.0,0.5,16 +heuristic_maxsave,0.1297349000233225,3,200.0,0.5,17 +spreading_maxsave,0.383827099984046,5,200.0,0.5,18 +heuristic_maxsave,0.1489789999905042,5,200.0,0.5,19 +spreading_maxsave,0.3602191999671049,7,200.0,0.5,20 +heuristic_maxsave,0.2872894000029191,7,200.0,0.5,21 +spreading_maxsave,0.4788765999837778,10,200.0,0.5,23 +heuristic_maxsave,0.2314664999721571,10,200.0,0.5,24 +spreading_maxsave,0.2793437999789603,1,200.0,0.5,29 +heuristic_maxsave,0.0726591999991796,1,200.0,0.5,29 +spreading_maxsave,0.236807300010696,2,200.0,0.5,41 +heuristic_maxsave,0.1415375000215135,2,200.0,0.5,41 +spreading_maxsave,0.3253047000034712,3,200.0,0.5,42 +heuristic_maxsave,0.1853941999725066,3,200.0,0.5,42 +spreading_maxsave,0.3316435999586247,5,200.0,0.5,44 +heuristic_maxsave,0.1993383999797515,5,200.0,0.5,44 +spreading_maxsave,0.5072257000138052,7,200.0,0.5,46 +heuristic_maxsave,0.2101610000245273,7,200.0,0.5,46 +spreading_maxsave,0.5774020999670029,10,200.0,0.5,49 +heuristic_maxsave,0.2867017000098713,10,200.0,0.5,49 +spreading_maxsave,0.2044192000175826,1,200.0,0.5,6 +heuristic_maxsave,0.0687661999836564,1,200.0,0.5,5 +spreading_maxsave,0.2152056000195443,2,200.0,0.5,7 +heuristic_maxsave,0.1481570999603718,2,200.0,0.5,8 +spreading_maxsave,0.2322183999931439,3,200.0,0.5,8 +heuristic_maxsave,0.1004933000076562,3,200.0,0.5,9 +spreading_maxsave,0.3455549000063911,5,200.0,0.5,10 +heuristic_maxsave,0.1361559000215493,5,200.0,0.5,11 +spreading_maxsave,0.4111096999840811,7,200.0,0.5,11 +heuristic_maxsave,0.1950298000010661,7,200.0,0.5,11 +spreading_maxsave,0.5645965000148863,10,200.0,0.5,11 +heuristic_maxsave,0.2420671000145375,10,200.0,0.5,11 +spreading_maxsave,0.2446700999862514,1,200.0,0.8,17 +heuristic_maxsave,0.1676880999584682,1,200.0,0.8,16 +spreading_maxsave,0.3239018000313081,2,200.0,0.8,18 +heuristic_maxsave,0.3605091000208631,2,200.0,0.8,18 +spreading_maxsave,0.324321299965959,3,200.0,0.8,19 +heuristic_maxsave,0.2279406999587081,3,200.0,0.8,19 +spreading_maxsave,0.3939768999698572,5,200.0,0.8,21 +heuristic_maxsave,0.376327299978584,5,200.0,0.8,21 +spreading_maxsave,0.4894497999921441,7,200.0,0.8,23 +heuristic_maxsave,0.5015065000043251,7,200.0,0.8,23 +spreading_maxsave,0.4849415000062436,10,200.0,0.8,26 +heuristic_maxsave,0.5283704000175931,10,200.0,0.8,26 +spreading_maxsave,0.1627826000330969,1,200.0,0.8,17 +heuristic_maxsave,0.1198535999865271,1,200.0,0.8,14 +spreading_maxsave,0.2756377999903634,2,200.0,0.8,18 +heuristic_maxsave,0.1689491000142879,2,200.0,0.8,18 +spreading_maxsave,0.2379558999673463,3,200.0,0.8,19 +heuristic_maxsave,0.1893404000438749,3,200.0,0.8,19 +spreading_maxsave,0.3514193999581039,5,200.0,0.8,21 +heuristic_maxsave,0.28049649996683,5,200.0,0.8,21 +spreading_maxsave,0.3518136000493541,7,200.0,0.8,23 +heuristic_maxsave,0.4320948999957181,7,200.0,0.8,23 +spreading_maxsave,0.5096444999799132,10,200.0,0.8,26 +heuristic_maxsave,0.5287143000168726,10,200.0,0.8,26 +spreading_maxsave,0.1577595999697223,1,200.0,0.8,13 +heuristic_maxsave,0.1099750999710522,1,200.0,0.8,12 +spreading_maxsave,0.2198505999986082,2,200.0,0.8,14 +heuristic_maxsave,0.2387725999578833,2,200.0,0.8,14 +spreading_maxsave,0.2554381999652833,3,200.0,0.8,15 +heuristic_maxsave,0.2075817000004463,3,200.0,0.8,15 +spreading_maxsave,0.3247279999777674,5,200.0,0.8,17 +heuristic_maxsave,0.2861352000036277,5,200.0,0.8,17 +spreading_maxsave,0.3513053000206128,7,200.0,0.8,19 +heuristic_maxsave,0.4376115000341087,7,200.0,0.8,19 +spreading_maxsave,0.4498962000361644,10,200.0,0.8,22 +heuristic_maxsave,0.5710637000156567,10,200.0,0.8,22 +spreading_maxsave,0.1557919000042602,1,200.0,0.8,2 +heuristic_maxsave,0.0818447000347077,1,200.0,0.8,2 +spreading_maxsave,0.1960762999951839,2,200.0,0.8,3 +heuristic_maxsave,0.1296072999830357,2,200.0,0.8,3 +spreading_maxsave,0.2809520000009797,3,200.0,0.8,4 +heuristic_maxsave,0.1578460000455379,3,200.0,0.8,4 +spreading_maxsave,0.2567032999941148,5,200.0,0.8,4 +heuristic_maxsave,0.2350060000317171,5,200.0,0.8,4 +spreading_maxsave,0.3556602000026032,7,200.0,0.8,4 +heuristic_maxsave,0.3108849999844096,7,200.0,0.8,4 +spreading_maxsave,0.5010427000233904,10,200.0,0.8,4 +heuristic_maxsave,0.4068543000030331,10,200.0,0.8,4 +spreading_maxsave,0.1705794999725185,1,200.0,0.8,21 +heuristic_maxsave,0.1139950999640859,1,200.0,0.8,20 +spreading_maxsave,0.2937852999893948,2,200.0,0.8,22 +heuristic_maxsave,0.1811599999782629,2,200.0,0.8,22 +spreading_maxsave,0.2312520000268705,3,200.0,0.8,23 +heuristic_maxsave,0.2537556000170298,3,200.0,0.8,23 +spreading_maxsave,0.3732055999571457,5,200.0,0.8,25 +heuristic_maxsave,0.2873711999855004,5,200.0,0.8,25 +spreading_maxsave,0.4469879000098444,7,200.0,0.8,27 +heuristic_maxsave,0.3087399000069126,7,200.0,0.8,27 +spreading_maxsave,0.4583666000398807,10,200.0,0.8,30 +heuristic_maxsave,0.5976279000169598,10,200.0,0.8,30 +spreading_maxsave,0.1700566000072285,1,200.0,0.8,10 +heuristic_maxsave,0.1086118000093847,1,200.0,0.8,10 +spreading_maxsave,0.3137893000384792,2,200.0,0.8,11 +heuristic_maxsave,0.2139279000111855,2,200.0,0.8,11 +spreading_maxsave,0.314260600018315,3,200.0,0.8,12 +heuristic_maxsave,0.1883723000064492,3,200.0,0.8,12 +spreading_maxsave,0.3502934999996796,5,200.0,0.8,14 +heuristic_maxsave,0.2713257999857887,5,200.0,0.8,14 +spreading_maxsave,0.3796697000507265,7,200.0,0.8,16 +heuristic_maxsave,0.3619531000149436,7,200.0,0.8,16 +spreading_maxsave,0.4287651000195183,10,200.0,0.8,19 +heuristic_maxsave,0.442568400001619,10,200.0,0.8,19 +spreading_maxsave,0.2596374999848194,1,200.0,0.8,4 +heuristic_maxsave,0.0917695999960415,1,200.0,0.8,4 +spreading_maxsave,0.203355300007388,2,200.0,0.8,5 +heuristic_maxsave,0.1236241000005975,2,200.0,0.8,5 +spreading_maxsave,0.2083061999874189,3,200.0,0.8,6 +heuristic_maxsave,0.2062177000334486,3,200.0,0.8,6 +spreading_maxsave,0.3718229999649338,5,200.0,0.8,6 +heuristic_maxsave,0.226841100025922,5,200.0,0.8,6 +spreading_maxsave,0.3578856999520212,7,200.0,0.8,6 +heuristic_maxsave,0.4230495999800041,7,200.0,0.8,6 +spreading_maxsave,0.3909694000030868,10,200.0,0.8,6 +heuristic_maxsave,0.4305410999804735,10,200.0,0.8,6 +spreading_maxsave,0.1483516999869607,1,200.0,0.8,1 +heuristic_maxsave,0.0931931000086478,1,200.0,0.8,1 +spreading_maxsave,0.1974234000081196,2,200.0,0.8,2 +heuristic_maxsave,0.1382991999853402,2,200.0,0.8,2 +spreading_maxsave,0.3035114000085741,3,200.0,0.8,3 +heuristic_maxsave,0.2150375000201165,3,200.0,0.8,3 +spreading_maxsave,0.2912133000208996,5,200.0,0.8,3 +heuristic_maxsave,0.2757970000384375,5,200.0,0.8,3 +spreading_maxsave,0.4419707999913953,7,200.0,0.8,3 +heuristic_maxsave,0.3256087999907322,7,200.0,0.8,3 +spreading_maxsave,0.5010434000287205,10,200.0,0.8,3 +heuristic_maxsave,0.4770238000201061,10,200.0,0.8,3 +spreading_maxsave,0.1479458999820053,1,200.0,0.8,1 +heuristic_maxsave,0.0839542000321671,1,200.0,0.8,1 +spreading_maxsave,0.2491774000227451,2,200.0,0.8,2 +heuristic_maxsave,0.1146343000000342,2,200.0,0.8,2 +spreading_maxsave,0.208901300036814,3,200.0,0.8,3 +heuristic_maxsave,0.1589524999726563,3,200.0,0.8,3 +spreading_maxsave,0.2656531000393443,5,200.0,0.8,3 +heuristic_maxsave,0.2957308000186458,5,200.0,0.8,3 +spreading_maxsave,0.391859499970451,7,200.0,0.8,3 +heuristic_maxsave,0.3457536999485455,7,200.0,0.8,3 +spreading_maxsave,0.5015684000100009,10,200.0,0.8,3 +heuristic_maxsave,0.4583000999991782,10,200.0,0.8,3 +spreading_maxsave,0.2605781000456773,1,200.0,0.8,13 +heuristic_maxsave,0.1340843000216409,1,200.0,0.8,12 +spreading_maxsave,0.2267428000341169,2,200.0,0.8,14 +heuristic_maxsave,0.1528352000168524,2,200.0,0.8,14 +spreading_maxsave,0.2360440000193193,3,200.0,0.8,15 +heuristic_maxsave,0.1945804999559186,3,200.0,0.8,15 +spreading_maxsave,0.2968054999946616,5,200.0,0.8,17 +heuristic_maxsave,0.3113440999877639,5,200.0,0.8,17 +spreading_maxsave,0.4118233000044711,7,200.0,0.8,19 +heuristic_maxsave,0.3212999000097625,7,200.0,0.8,19 +spreading_maxsave,0.5214633999858052,10,200.0,0.8,22 +heuristic_maxsave,0.5200631000334397,10,200.0,0.8,22 +spreading_maxsave,0.4276599999866448,1,400.0,0.1,10 +heuristic_maxsave,0.1492883000173606,1,400.0,0.1,8 +spreading_maxsave,0.6323594000423327,2,400.0,0.1,18 +heuristic_maxsave,0.2063607000163756,2,400.0,0.1,15 +spreading_maxsave,0.704987799981609,3,400.0,0.1,26 +heuristic_maxsave,0.2495169999892823,3,400.0,0.1,21 +spreading_maxsave,0.8821355999680236,5,400.0,0.1,34 +heuristic_maxsave,0.4766547000035643,5,400.0,0.1,29 +spreading_maxsave,1.116703099978622,7,400.0,0.1,35 +heuristic_maxsave,0.5398625999805517,7,400.0,0.1,38 +spreading_maxsave,1.3485814000014216,10,400.0,0.1,38 +heuristic_maxsave,0.3855633999919519,10,400.0,0.1,40 +spreading_maxsave,0.6049749999656342,1,400.0,0.1,6 +heuristic_maxsave,0.1435287999920547,1,400.0,0.1,4 +spreading_maxsave,0.6240496999816969,2,400.0,0.1,8 +heuristic_maxsave,0.2191406000056304,2,400.0,0.1,6 +spreading_maxsave,0.7023757999995723,3,400.0,0.1,9 +heuristic_maxsave,0.247850899992045,3,400.0,0.1,10 +spreading_maxsave,1.1580646999645978,5,400.0,0.1,10 +heuristic_maxsave,0.3306579000200145,5,400.0,0.1,10 +spreading_maxsave,1.1748952000052668,7,400.0,0.1,10 +heuristic_maxsave,0.3617365999962203,7,400.0,0.1,10 +spreading_maxsave,1.26313559996197,10,400.0,0.1,10 +heuristic_maxsave,0.4780159000074491,10,400.0,0.1,10 +spreading_maxsave,0.4582809000276029,1,400.0,0.1,30 +heuristic_maxsave,0.2663825000054203,1,400.0,0.1,28 +spreading_maxsave,0.8567600999958813,2,400.0,0.1,55 +heuristic_maxsave,0.3901632000342943,2,400.0,0.1,46 +spreading_maxsave,0.8691420999821275,3,400.0,0.1,77 +heuristic_maxsave,0.303547499992419,3,400.0,0.1,64 +spreading_maxsave,1.107374599960167,5,400.0,0.1,115 +heuristic_maxsave,0.3821370999794453,5,400.0,0.1,99 +spreading_maxsave,1.204921500000637,7,400.0,0.1,143 +heuristic_maxsave,0.5033570999512449,7,400.0,0.1,121 +spreading_maxsave,1.3851383999572136,10,400.0,0.1,168 +heuristic_maxsave,0.4066457999870181,10,400.0,0.1,148 +spreading_maxsave,0.4775206999620422,1,400.0,0.1,15 +heuristic_maxsave,0.1596130999969318,1,400.0,0.1,10 +spreading_maxsave,0.632251700037159,2,400.0,0.1,29 +heuristic_maxsave,0.1798651000135578,2,400.0,0.1,18 +spreading_maxsave,0.7331343999831006,3,400.0,0.1,40 +heuristic_maxsave,0.2325922000454738,3,400.0,0.1,26 +spreading_maxsave,1.00514809996821,5,400.0,0.1,56 +heuristic_maxsave,0.3036951999529265,5,400.0,0.1,41 +spreading_maxsave,1.171053700032644,7,400.0,0.1,67 +heuristic_maxsave,0.3257984000374563,7,400.0,0.1,54 +spreading_maxsave,1.3093210000079123,10,400.0,0.1,68 +heuristic_maxsave,0.3843877999461256,10,400.0,0.1,71 +spreading_maxsave,0.5643018999835476,1,400.0,0.1,22 +heuristic_maxsave,0.1703087000059895,1,400.0,0.1,20 +spreading_maxsave,1.0122063999879174,2,400.0,0.1,42 +heuristic_maxsave,0.4224600999732502,2,400.0,0.1,35 +spreading_maxsave,0.7244173999642953,3,400.0,0.1,59 +heuristic_maxsave,0.3144646000000648,3,400.0,0.1,47 +spreading_maxsave,0.9571849000058136,5,400.0,0.1,86 +heuristic_maxsave,0.2957403999753296,5,400.0,0.1,71 +spreading_maxsave,1.3085287000285462,7,400.0,0.1,106 +heuristic_maxsave,0.5863110999925993,7,400.0,0.1,90 +spreading_maxsave,1.5827839000266977,10,400.0,0.1,122 +heuristic_maxsave,0.3893034000066109,10,400.0,0.1,110 +spreading_maxsave,0.5635352000244893,1,400.0,0.1,28 +heuristic_maxsave,0.1721643000491894,1,400.0,0.1,25 +spreading_maxsave,0.7714409999898635,2,400.0,0.1,54 +heuristic_maxsave,0.2870893999934196,2,400.0,0.1,47 +spreading_maxsave,1.144060200022068,3,400.0,0.1,76 +heuristic_maxsave,0.4536575999809429,3,400.0,0.1,63 +spreading_maxsave,1.1517882000189277,5,400.0,0.1,111 +heuristic_maxsave,0.4404953000484966,5,400.0,0.1,92 +spreading_maxsave,1.207361200009473,7,400.0,0.1,134 +heuristic_maxsave,0.368633400008548,7,400.0,0.1,116 +spreading_maxsave,1.338526100036688,10,400.0,0.1,159 +heuristic_maxsave,0.601250900013838,10,400.0,0.1,137 +spreading_maxsave,0.5026269999798387,1,400.0,0.1,29 +heuristic_maxsave,0.1774515000288374,1,400.0,0.1,23 +spreading_maxsave,0.6409444999881089,2,400.0,0.1,54 +heuristic_maxsave,0.2180541999987326,2,400.0,0.1,44 +spreading_maxsave,0.7625337000354193,3,400.0,0.1,75 +heuristic_maxsave,0.3035526000312529,3,400.0,0.1,62 +spreading_maxsave,0.8956204999703914,5,400.0,0.1,110 +heuristic_maxsave,0.315176900010556,5,400.0,0.1,92 +spreading_maxsave,1.3106273000012152,7,400.0,0.1,133 +heuristic_maxsave,0.4594922999967821,7,400.0,0.1,115 +spreading_maxsave,1.3869516999693587,10,400.0,0.1,157 +heuristic_maxsave,0.4020706000155769,10,400.0,0.1,138 +spreading_maxsave,0.4109003000194207,1,400.0,0.1,13 +heuristic_maxsave,0.1303568999865092,1,400.0,0.1,6 +spreading_maxsave,0.6568864000146277,2,400.0,0.1,23 +heuristic_maxsave,0.1962955999770201,2,400.0,0.1,12 +spreading_maxsave,0.7080241999938153,3,400.0,0.1,32 +heuristic_maxsave,0.2318102999706752,3,400.0,0.1,17 +spreading_maxsave,1.0378405000083148,5,400.0,0.1,44 +heuristic_maxsave,0.3749791999580338,5,400.0,0.1,24 +spreading_maxsave,0.994963600009214,7,400.0,0.1,45 +heuristic_maxsave,0.3917588999611325,7,400.0,0.1,39 +spreading_maxsave,1.2170275000389663,10,400.0,0.1,48 +heuristic_maxsave,0.4155465000076219,10,400.0,0.1,49 +spreading_maxsave,0.4700947999954223,1,400.0,0.1,28 +heuristic_maxsave,0.2027403000392951,1,400.0,0.1,23 +spreading_maxsave,0.7103741000173613,2,400.0,0.1,54 +heuristic_maxsave,0.312370200001169,2,400.0,0.1,46 +spreading_maxsave,0.8472247999743558,3,400.0,0.1,76 +heuristic_maxsave,0.2734562000259757,3,400.0,0.1,62 +spreading_maxsave,0.952839599980507,5,400.0,0.1,109 +heuristic_maxsave,0.2962948000058532,5,400.0,0.1,93 +spreading_maxsave,1.120882899966091,7,400.0,0.1,135 +heuristic_maxsave,0.416954500018619,7,400.0,0.1,116 +spreading_maxsave,1.6903908000094816,10,400.0,0.1,159 +heuristic_maxsave,0.380467300012242,10,400.0,0.1,142 +spreading_maxsave,0.4848903000238351,1,400.0,0.1,17 +heuristic_maxsave,0.1300214999937452,1,400.0,0.1,13 +spreading_maxsave,0.5428055999800563,2,400.0,0.1,32 +heuristic_maxsave,0.2457896000123582,2,400.0,0.1,26 +spreading_maxsave,0.6679781000129879,3,400.0,0.1,46 +heuristic_maxsave,0.3075420000241138,3,400.0,0.1,38 +spreading_maxsave,0.9831248000264168,5,400.0,0.1,64 +heuristic_maxsave,0.3502979999757372,5,400.0,0.1,58 +spreading_maxsave,1.1571738999919037,7,400.0,0.1,77 +heuristic_maxsave,0.3945752000436187,7,400.0,0.1,68 +spreading_maxsave,1.3243401999934576,10,400.0,0.1,81 +heuristic_maxsave,0.4195264999871142,10,400.0,0.1,83 +spreading_maxsave,0.6300575999775901,1,400.0,0.5,21 +heuristic_maxsave,0.1962429000413976,1,400.0,0.5,21 +spreading_maxsave,0.7100792999844998,2,400.0,0.5,25 +heuristic_maxsave,0.3933648000238463,2,400.0,0.5,25 +spreading_maxsave,0.8253624999779277,3,400.0,0.5,26 +heuristic_maxsave,0.2970519000082277,3,400.0,0.5,26 +spreading_maxsave,0.967457499995362,5,400.0,0.5,28 +heuristic_maxsave,0.3872476000105962,5,400.0,0.5,28 +spreading_maxsave,0.986924899974838,7,400.0,0.5,30 +heuristic_maxsave,0.4718388000037521,7,400.0,0.5,30 +spreading_maxsave,1.4825164999929257,10,400.0,0.5,33 +heuristic_maxsave,0.6676626999978907,10,400.0,0.5,33 +spreading_maxsave,0.696589800005313,1,400.0,0.5,10 +heuristic_maxsave,0.2667476999922655,1,400.0,0.5,9 +spreading_maxsave,0.6684675000142306,2,400.0,0.5,11 +heuristic_maxsave,0.2305550000164657,2,400.0,0.5,11 +spreading_maxsave,0.7289986000396311,3,400.0,0.5,12 +heuristic_maxsave,0.2841276000253856,3,400.0,0.5,12 +spreading_maxsave,0.9098501999978909,5,400.0,0.5,14 +heuristic_maxsave,0.623745399992913,5,400.0,0.5,14 +spreading_maxsave,0.966344200016465,7,400.0,0.5,16 +heuristic_maxsave,0.4757868999731727,7,400.0,0.5,16 +spreading_maxsave,1.1371457999921404,10,400.0,0.5,19 +heuristic_maxsave,0.7268507999833673,10,400.0,0.5,19 +spreading_maxsave,0.748866900044959,1,400.0,0.5,62 +heuristic_maxsave,0.2647664999822154,1,400.0,0.5,58 +spreading_maxsave,0.9763952000066638,2,400.0,0.5,87 +heuristic_maxsave,0.4035986000089906,2,400.0,0.5,83 +spreading_maxsave,0.9502340000472032,3,400.0,0.5,95 +heuristic_maxsave,0.4505986000294797,3,400.0,0.5,96 +spreading_maxsave,1.1072708999854513,5,400.0,0.5,97 +heuristic_maxsave,0.4769173000240698,5,400.0,0.5,98 +spreading_maxsave,1.3947173000196926,7,400.0,0.5,99 +heuristic_maxsave,0.6062100999988616,7,400.0,0.5,100 +spreading_maxsave,1.4940172000206076,10,400.0,0.5,102 +heuristic_maxsave,0.7636698000133038,10,400.0,0.5,103 +spreading_maxsave,0.714410999964457,1,400.0,0.5,57 +heuristic_maxsave,0.2569395999889821,1,400.0,0.5,46 +spreading_maxsave,0.8866244999808259,2,400.0,0.5,79 +heuristic_maxsave,0.560739399981685,2,400.0,0.5,74 +spreading_maxsave,0.9469704999937676,3,400.0,0.5,85 +heuristic_maxsave,0.3793351000058464,3,400.0,0.5,86 +spreading_maxsave,1.0833743999828584,5,400.0,0.5,87 +heuristic_maxsave,0.4810797999962233,5,400.0,0.5,88 +spreading_maxsave,1.2787637999863364,7,400.0,0.5,89 +heuristic_maxsave,0.780480399960652,7,400.0,0.5,90 +spreading_maxsave,1.403326699975878,10,400.0,0.5,92 +heuristic_maxsave,0.7945015999721363,10,400.0,0.5,93 +spreading_maxsave,0.7733919000020251,1,400.0,0.5,53 +heuristic_maxsave,0.2504858000320382,1,400.0,0.5,47 +spreading_maxsave,0.8559090999769978,2,400.0,0.5,74 +heuristic_maxsave,0.3134200000204146,2,400.0,0.5,72 +spreading_maxsave,1.0852037000004202,3,400.0,0.5,79 +heuristic_maxsave,0.3802692999597639,3,400.0,0.5,81 +spreading_maxsave,1.0851624000351876,5,400.0,0.5,81 +heuristic_maxsave,0.5270821000449359,5,400.0,0.5,84 +spreading_maxsave,1.1482656000298448,7,400.0,0.5,83 +heuristic_maxsave,0.5939276999561116,7,400.0,0.5,86 +spreading_maxsave,1.6968992000329308,10,400.0,0.5,86 +heuristic_maxsave,0.7008178000105545,10,400.0,0.5,89 +spreading_maxsave,0.7308476999751292,1,400.0,0.5,49 +heuristic_maxsave,0.3130528000183403,1,400.0,0.5,45 +spreading_maxsave,0.8084814000176266,2,400.0,0.5,68 +heuristic_maxsave,0.3253227000241168,2,400.0,0.5,65 +spreading_maxsave,0.986151700024493,3,400.0,0.5,72 +heuristic_maxsave,0.577400799957104,3,400.0,0.5,74 +spreading_maxsave,1.0387342000030912,5,400.0,0.5,74 +heuristic_maxsave,0.4754629000090062,5,400.0,0.5,76 +spreading_maxsave,1.1369822999695316,7,400.0,0.5,76 +heuristic_maxsave,0.6264398999628611,7,400.0,0.5,78 +spreading_maxsave,1.3521505999960937,10,400.0,0.5,79 +heuristic_maxsave,0.8805881000007503,10,400.0,0.5,81 +spreading_maxsave,0.7544279000139795,1,400.0,0.5,47 +heuristic_maxsave,0.2463018000125885,1,400.0,0.5,44 +spreading_maxsave,0.8365135000203736,2,400.0,0.5,68 +heuristic_maxsave,0.3861469000112265,2,400.0,0.5,66 +spreading_maxsave,0.9377570999786258,3,400.0,0.5,71 +heuristic_maxsave,0.3419377999962307,3,400.0,0.5,72 +spreading_maxsave,1.0750787999713791,5,400.0,0.5,73 +heuristic_maxsave,0.5804534999770112,5,400.0,0.5,74 +spreading_maxsave,1.2203048000228591,7,400.0,0.5,75 +heuristic_maxsave,0.6325779999606311,7,400.0,0.5,76 +spreading_maxsave,1.3690156000084244,10,400.0,0.5,78 +heuristic_maxsave,0.725636699993629,10,400.0,0.5,79 +spreading_maxsave,0.7612699999590404,1,400.0,0.5,25 +heuristic_maxsave,0.373372100002598,1,400.0,0.5,22 +spreading_maxsave,0.8087179000140168,2,400.0,0.5,32 +heuristic_maxsave,0.26761759998044,2,400.0,0.5,31 +spreading_maxsave,0.7900566000025719,3,400.0,0.5,33 +heuristic_maxsave,0.3255832000286318,3,400.0,0.5,34 +spreading_maxsave,1.015544299967587,5,400.0,0.5,35 +heuristic_maxsave,0.4805785000207834,5,400.0,0.5,36 +spreading_maxsave,1.0640604000072926,7,400.0,0.5,37 +heuristic_maxsave,0.7079374000313692,7,400.0,0.5,38 +spreading_maxsave,1.2139823000179604,10,400.0,0.5,40 +heuristic_maxsave,0.8028046999825165,10,400.0,0.5,41 +spreading_maxsave,0.6447457000031136,1,400.0,0.5,8 +heuristic_maxsave,0.2019828000338748,1,400.0,0.5,7 +spreading_maxsave,0.6813996999990195,2,400.0,0.5,9 +heuristic_maxsave,0.2662311000167392,2,400.0,0.5,10 +spreading_maxsave,0.8293738000211306,3,400.0,0.5,10 +heuristic_maxsave,0.3665678999968804,3,400.0,0.5,11 +spreading_maxsave,1.032389100000728,5,400.0,0.5,12 +heuristic_maxsave,0.415726299979724,5,400.0,0.5,13 +spreading_maxsave,0.9772298000170848,7,400.0,0.5,14 +heuristic_maxsave,0.5138811999931931,7,400.0,0.5,15 +spreading_maxsave,1.1681202999898233,10,400.0,0.5,17 +heuristic_maxsave,0.8856589000206441,10,400.0,0.5,18 +spreading_maxsave,0.7188531000283547,1,400.0,0.5,28 +heuristic_maxsave,0.2226387000409886,1,400.0,0.5,22 +spreading_maxsave,0.7374191000126302,2,400.0,0.5,39 +heuristic_maxsave,0.3313815000001341,2,400.0,0.5,36 +spreading_maxsave,0.8521106999833137,3,400.0,0.5,40 +heuristic_maxsave,0.3593490000348538,3,400.0,0.5,42 +spreading_maxsave,1.1070543000241742,5,400.0,0.5,42 +heuristic_maxsave,0.603667100018356,5,400.0,0.5,44 +spreading_maxsave,1.1092445999966003,7,400.0,0.5,44 +heuristic_maxsave,0.5214662000071257,7,400.0,0.5,46 +spreading_maxsave,1.4144794000312686,10,400.0,0.5,47 +heuristic_maxsave,0.7488946000230499,10,400.0,0.5,49 +spreading_maxsave,0.4546741000376642,1,400.0,0.8,22 +heuristic_maxsave,0.3913086000247858,1,400.0,0.8,21 +spreading_maxsave,0.7420145999640226,2,400.0,0.8,23 +heuristic_maxsave,0.4996032000053674,2,400.0,0.8,24 +spreading_maxsave,0.7148914000135846,3,400.0,0.8,24 +heuristic_maxsave,0.6197518000262789,3,400.0,0.8,25 +spreading_maxsave,0.8555290999938734,5,400.0,0.8,26 +heuristic_maxsave,0.7347938999882899,5,400.0,0.8,27 +spreading_maxsave,0.9098711000406184,7,400.0,0.8,28 +heuristic_maxsave,1.3575864000013098,7,400.0,0.8,29 +spreading_maxsave,1.2100104000419378,10,400.0,0.8,31 +heuristic_maxsave,1.3580646999762394,10,400.0,0.8,32 +spreading_maxsave,0.6270783999934793,1,400.0,0.8,13 +heuristic_maxsave,0.3315930000389926,1,400.0,0.8,13 +spreading_maxsave,0.7386583999614231,2,400.0,0.8,14 +heuristic_maxsave,0.4571885000332258,2,400.0,0.8,14 +spreading_maxsave,0.6330662000109442,3,400.0,0.8,15 +heuristic_maxsave,0.5102048999979161,3,400.0,0.8,15 +spreading_maxsave,0.7864257000037469,5,400.0,0.8,17 +heuristic_maxsave,0.9193274000426754,5,400.0,0.8,17 +spreading_maxsave,0.9387901999871248,7,400.0,0.8,19 +heuristic_maxsave,1.0922084000194443,7,400.0,0.8,19 +spreading_maxsave,1.2340592999826183,10,400.0,0.8,22 +heuristic_maxsave,1.6207878999994136,10,400.0,0.8,22 +spreading_maxsave,0.5463835999835283,1,400.0,0.8,25 +heuristic_maxsave,0.3230739000136964,1,400.0,0.8,24 +spreading_maxsave,0.6372343999682926,2,400.0,0.8,26 +heuristic_maxsave,0.4675158000318333,2,400.0,0.8,26 +spreading_maxsave,0.9016374000348152,3,400.0,0.8,27 +heuristic_maxsave,0.7039541000267491,3,400.0,0.8,27 +spreading_maxsave,0.8118607000214979,5,400.0,0.8,29 +heuristic_maxsave,0.798025400028564,5,400.0,0.8,29 +spreading_maxsave,0.9860856999875978,7,400.0,0.8,31 +heuristic_maxsave,1.133234899956733,7,400.0,0.8,31 +spreading_maxsave,1.2846410000347532,10,400.0,0.8,34 +heuristic_maxsave,1.390135299996473,10,400.0,0.8,34 +spreading_maxsave,0.5272687000106089,1,400.0,0.8,1 +heuristic_maxsave,0.2470609999727457,1,400.0,0.8,1 +spreading_maxsave,0.5451471999986097,2,400.0,0.8,2 +heuristic_maxsave,0.3533699000254273,2,400.0,0.8,2 +spreading_maxsave,0.6268494999967515,3,400.0,0.8,2 +heuristic_maxsave,0.5695582000189461,3,400.0,0.8,2 +spreading_maxsave,0.7679243999882601,5,400.0,0.8,2 +heuristic_maxsave,0.7665662000072189,5,400.0,0.8,2 +spreading_maxsave,0.8858205999713391,7,400.0,0.8,2 +heuristic_maxsave,0.8670242000371218,7,400.0,0.8,2 +spreading_maxsave,1.0695048000197858,10,400.0,0.8,2 +heuristic_maxsave,1.461972700024489,10,400.0,0.8,2 +spreading_maxsave,0.650798799993936,1,400.0,0.8,28 +heuristic_maxsave,0.424418099981267,1,400.0,0.8,24 +spreading_maxsave,0.639764700026717,2,400.0,0.8,29 +heuristic_maxsave,0.561322099994868,2,400.0,0.8,29 +spreading_maxsave,0.750844300026074,3,400.0,0.8,30 +heuristic_maxsave,0.8612866999465041,3,400.0,0.8,30 +spreading_maxsave,0.8810389999998733,5,400.0,0.8,32 +heuristic_maxsave,0.9824450999731198,5,400.0,0.8,32 +spreading_maxsave,0.994032500020694,7,400.0,0.8,34 +heuristic_maxsave,1.4041685000411237,7,400.0,0.8,34 +spreading_maxsave,1.2991919000050984,10,400.0,0.8,37 +heuristic_maxsave,1.4545534999924712,10,400.0,0.8,37 +spreading_maxsave,0.5250599000137299,1,400.0,0.8,28 +heuristic_maxsave,0.5180497000110336,1,400.0,0.8,26 +spreading_maxsave,0.8211904999916442,2,400.0,0.8,29 +heuristic_maxsave,0.5510774999856949,2,400.0,0.8,30 +spreading_maxsave,0.6918721999973059,3,400.0,0.8,30 +heuristic_maxsave,0.7125151000218466,3,400.0,0.8,31 +spreading_maxsave,0.9501300000119954,5,400.0,0.8,32 +heuristic_maxsave,0.9478267999948002,5,400.0,0.8,33 +spreading_maxsave,1.161839000007603,7,400.0,0.8,34 +heuristic_maxsave,1.1687081000418402,7,400.0,0.8,35 +spreading_maxsave,1.266055200016126,10,400.0,0.8,37 +heuristic_maxsave,1.5378542999969795,10,400.0,0.8,38 +spreading_maxsave,0.7371526000206359,1,400.0,0.8,38 +heuristic_maxsave,0.4823686999734491,1,400.0,0.8,37 +spreading_maxsave,0.7708653000299819,2,400.0,0.8,39 +heuristic_maxsave,0.6473940000287257,2,400.0,0.8,39 +spreading_maxsave,0.7680094999959692,3,400.0,0.8,40 +heuristic_maxsave,0.6768079000175931,3,400.0,0.8,40 +spreading_maxsave,0.8872507000342011,5,400.0,0.8,42 +heuristic_maxsave,1.0556261999881826,5,400.0,0.8,42 +spreading_maxsave,1.077062199998181,7,400.0,0.8,44 +heuristic_maxsave,1.3023541000438854,7,400.0,0.8,44 +spreading_maxsave,1.2428558999672532,10,400.0,0.8,47 +heuristic_maxsave,1.626142799970694,10,400.0,0.8,47 +spreading_maxsave,0.5139283000025898,1,400.0,0.8,24 +heuristic_maxsave,0.4053445999743417,1,400.0,0.8,25 +spreading_maxsave,0.8104822000022978,2,400.0,0.8,25 +heuristic_maxsave,0.5418617999530397,2,400.0,0.8,26 +spreading_maxsave,0.7324352000141516,3,400.0,0.8,26 +heuristic_maxsave,0.6905009999754839,3,400.0,0.8,27 +spreading_maxsave,0.8381816999753937,5,400.0,0.8,28 +heuristic_maxsave,0.8317198000149801,5,400.0,0.8,29 +spreading_maxsave,1.244214300008025,7,400.0,0.8,30 +heuristic_maxsave,1.1850657999748364,7,400.0,0.8,31 +spreading_maxsave,1.1552618999849074,10,400.0,0.8,33 +heuristic_maxsave,1.4665315999882296,10,400.0,0.8,34 +spreading_maxsave,0.6030600999947637,1,400.0,0.8,24 +heuristic_maxsave,0.5900598000152968,1,400.0,0.8,24 +spreading_maxsave,0.6390509000048041,2,400.0,0.8,25 +heuristic_maxsave,0.5277437000186183,2,400.0,0.8,25 +spreading_maxsave,0.6820443999604322,3,400.0,0.8,26 +heuristic_maxsave,0.6277904000016861,3,400.0,0.8,26 +spreading_maxsave,0.877071299997624,5,400.0,0.8,28 +heuristic_maxsave,0.8866336999926716,5,400.0,0.8,28 +spreading_maxsave,0.9528527000220492,7,400.0,0.8,30 +heuristic_maxsave,1.0869454000494445,7,400.0,0.8,30 +spreading_maxsave,1.376034599961713,10,400.0,0.8,33 +heuristic_maxsave,1.5075808999827132,10,400.0,0.8,33 +spreading_maxsave,0.4860744000179693,1,400.0,0.8,15 +heuristic_maxsave,0.3986139000044204,1,400.0,0.8,15 +spreading_maxsave,0.5634443000308238,2,400.0,0.8,16 +heuristic_maxsave,0.5430100000230595,2,400.0,0.8,16 +spreading_maxsave,0.6728860000148416,3,400.0,0.8,17 +heuristic_maxsave,0.5303234999882989,3,400.0,0.8,17 +spreading_maxsave,0.9196489000460132,5,400.0,0.8,19 +heuristic_maxsave,0.8112997999996878,5,400.0,0.8,19 +spreading_maxsave,1.0027675000019372,7,400.0,0.8,21 +heuristic_maxsave,1.032043799990788,7,400.0,0.8,21 +spreading_maxsave,1.082156100019347,10,400.0,0.8,24 +heuristic_maxsave,1.66049690003274,10,400.0,0.8,24 diff --git a/experiments/firefighter_problem/spreading_minbudget.csv b/experiments/firefighter_problem/spreading_minbudget.csv new file mode 100644 index 0000000..7c2b261 --- /dev/null +++ b/experiments/firefighter_problem/spreading_minbudget.csv @@ -0,0 +1,20 @@ +algorithm,runtime,graph_nodes,Budget +spreading_minbudget,0.4963123999768868,100,"(4, [(89, 1), (47, 1), (84, 1), (30, 1), (38, 2), (50, 2), (3, 2), (26, 2)])" +heuristic_minbudget,0.12413459992967546,100,"(4, [(47, 1), (92, 1), (44, 1), (17, 1), (83, 2), (62, 2), (50, 2), (26, 2), (69, 3), (29, 3)])" +spreading_minbudget,0.39317540009506047,100,"(11, [(3, 1), (15, 1), (28, 1), (54, 1), (71, 1), (96, 1), (97, 1), (17, 1), (35, 1), (45, 1), (22, 1)])" +heuristic_minbudget,1.0460371000226587,100,"(10, [(22, 1), (35, 1), (28, 1), (54, 1), (96, 1), (17, 1), (97, 1), (15, 1), (45, 1), (71, 1)])" +spreading_minbudget,0.2668848999310285,100,"(14, [(14, 1), (20, 1), (30, 1), (40, 1), (48, 1), (57, 1), (71, 1), (80, 1), (86, 1), (91, 1), (92, 1), (96, 1), (5, 1), (89, 1)])" +heuristic_minbudget,3.6302230999572203,100,"(14, [(14, 1), (40, 1), (48, 1), (86, 1), (96, 1), (20, 1), (91, 1), (80, 1), (92, 1), (71, 1), (30, 1), (5, 1), (57, 1), (89, 1)])" +spreading_minbudget,1.212209300021641,200,"(22, [(70, 1), (128, 1), (53, 1), (55, 1), (125, 1), (152, 1), (28, 1), (104, 1), (17, 1), (20, 1), (174, 1), (5, 1), (31, 1), (35, 1), (44, 1), (120, 1), (151, 1), (172, 1), (175, 1), (190, 1), (146, 1), (168, 1)])" +heuristic_minbudget,1.0129838000284508,200,"(14, [(174, 1), (151, 1), (146, 1), (168, 1), (17, 1), (172, 1), (152, 1), (190, 1), (35, 1), (5, 1), (44, 1), (175, 1), (120, 1), (52, 1), (128, 2), (109, 2), (148, 2), (16, 2), (76, 2), (32, 2), (114, 2), (8, 2), (95, 2), (39, 2), (48, 2), (138, 2), (116, 2), (157, 2)])" +spreading_minbudget,0.5931069999933243,200,"(5, [(5, 1), (44, 1), (193, 1), (170, 1), (24, 1)])" +heuristic_minbudget,5.592074999934994,200,"(4, [(44, 1), (24, 1), (193, 1), (170, 1)])" +spreading_minbudget,1.2939483999507502,200,"(40, [(89, 1), (3, 1), (4, 1), (13, 1), (17, 1), (19, 1), (27, 1), (45, 1), (50, 1), (62, 1), (74, 1), (84, 1), (92, 1), (95, 1), (97, 1), (118, 1), (119, 1), (123, 1), (124, 1), (128, 1), (138, 1), (142, 1), (144, 1), (146, 1), (152, 1), (153, 1), (180, 1), (191, 1), (198, 1), (11, 1), (29, 1), (93, 1), (100, 1), (141, 1), (164, 1), (167, 1), (173, 1), (184, 1), (102, 1), (86, 1)])" +heuristic_minbudget,20.179923600051552,200,"(40, [(4, 1), (146, 1), (144, 1), (153, 1), (152, 1), (62, 1), (173, 1), (119, 1), (13, 1), (89, 1), (142, 1), (164, 1), (27, 1), (45, 1), (102, 1), (95, 1), (141, 1), (128, 1), (29, 1), (167, 1), (86, 1), (191, 1), (74, 1), (100, 1), (11, 1), (84, 1), (3, 1), (118, 1), (93, 1), (180, 1), (92, 1), (50, 1), (138, 1), (17, 1), (184, 1), (19, 1), (124, 1), (123, 1), (198, 1), (97, 1)])" +spreading_minbudget,3.5869039999088272,400,"(21, [(69, 1), (116, 1), (239, 1), (159, 1), (250, 1), (37, 1), (192, 1), (144, 1), (387, 1), (29, 1), (287, 1), (7, 1), (63, 1), (300, 1), (305, 1), (93, 1), (280, 1), (112, 1), (149, 1), (11, 1), (230, 1)])" +heuristic_minbudget,2.8195147999795154,400,"(15, [(287, 1), (305, 1), (300, 1), (149, 1), (63, 1), (11, 1), (93, 1), (280, 1), (112, 1), (230, 1), (29, 1), (343, 1), (103, 1), (364, 1), (339, 1), (190, 2), (110, 2), (121, 2), (393, 2), (193, 2), (200, 2), (354, 2), (1, 2), (147, 2), (159, 2), (367, 2), (267, 2), (204, 2), (50, 2), (373, 2)])" +spreading_minbudget,6.544073999975808,400,"(63, [(103, 1), (333, 1), (88, 1), (2, 1), (17, 1), (27, 1), (29, 1), (66, 1), (72, 1), (76, 1), (89, 1), (135, 1), (143, 1), (148, 1), (150, 1), (152, 1), (165, 1), (166, 1), (190, 1), (222, 1), (250, 1), (257, 1), (275, 1), (289, 1), (291, 1), (292, 1), (293, 1), (306, 1), (315, 1), (326, 1), (327, 1), (363, 1), (373, 1), (380, 1), (386, 1), (40, 1), (109, 1), (112, 1), (140, 1), (182, 1), (229, 1), (238, 1), (239, 1), (325, 1), (390, 1), (9, 1), (90, 1), (171, 1), (184, 1), (359, 1), (385, 1), (393, 1), (11, 1), (51, 1), (71, 1), (212, 1), (364, 1), (230, 1), (368, 1), (391, 1), (52, 1), (353, 1), (276, 1)])" +heuristic_minbudget,45.2434607000323,400,"(62, [(327, 1), (150, 1), (364, 1), (166, 1), (291, 1), (143, 1), (229, 1), (315, 1), (17, 1), (109, 1), (212, 1), (27, 1), (2, 1), (11, 1), (257, 1), (306, 1), (148, 1), (239, 1), (390, 1), (363, 1), (71, 1), (76, 1), (275, 1), (276, 1), (72, 1), (184, 1), (325, 1), (353, 1), (51, 1), (135, 1), (112, 1), (165, 1), (238, 1), (293, 1), (289, 1), (385, 1), (9, 1), (140, 1), (222, 1), (250, 1), (386, 1), (359, 1), (29, 1), (373, 1), (292, 1), (391, 1), (326, 1), (40, 1), (380, 1), (171, 1), (230, 1), (393, 1), (182, 1), (368, 1), (52, 1), (66, 1), (152, 1), (88, 1), (89, 1), (333, 1), (190, 1), (90, 1)])" +spreading_minbudget,4.017668400076218,400,"(43, [(44, 1), (56, 1), (71, 1), (104, 1), (105, 1), (110, 1), (130, 1), (142, 1), (151, 1), (157, 1), (171, 1), (179, 1), (189, 1), (214, 1), (222, 1), (229, 1), (232, 1), (271, 1), (281, 1), (296, 1), (297, 1), (308, 1), (309, 1), (335, 1), (339, 1), (344, 1), (354, 1), (355, 1), (359, 1), (371, 1), (373, 1), (382, 1), (385, 1), (68, 1), (89, 1), (98, 1), (150, 1), (253, 1), (254, 1), (307, 1), (369, 1), (378, 1), (84, 1)])" +heuristic_minbudget,96.92596789996605,400,"(43, [(56, 1), (84, 1), (222, 1), (214, 1), (307, 1), (335, 1), (369, 1), (371, 1), (309, 1), (339, 1), (104, 1), (189, 1), (229, 1), (232, 1), (382, 1), (296, 1), (130, 1), (151, 1), (171, 1), (110, 1), (179, 1), (271, 1), (71, 1), (344, 1), (354, 1), (378, 1), (254, 1), (385, 1), (68, 1), (157, 1), (281, 1), (308, 1), (44, 1), (373, 1), (105, 1), (359, 1), (142, 1), (253, 1), (297, 1), (150, 1), (355, 1), (89, 1), (98, 1)])" +,195.34563290001824,, diff --git a/experiments/firefighter_problem/spreading_minbudget.png b/experiments/firefighter_problem/spreading_minbudget.png new file mode 100644 index 0000000..a42e7c2 Binary files /dev/null and b/experiments/firefighter_problem/spreading_minbudget.png differ diff --git a/experiments/firefighter_problem/spreading_minbudget_preprocessed.csv b/experiments/firefighter_problem/spreading_minbudget_preprocessed.csv new file mode 100644 index 0000000..48b6414 --- /dev/null +++ b/experiments/firefighter_problem/spreading_minbudget_preprocessed.csv @@ -0,0 +1,19 @@ +algorithm,runtime,graph_nodes,Budget,Budget_numeric +spreading_minbudget,0.4963123999768868,100.0,"(4, [(89, 1), (47, 1), (84, 1), (30, 1), (38, 2), (50, 2), (3, 2), (26, 2)])",4.0 +heuristic_minbudget,0.1241345999296754,100.0,"(4, [(47, 1), (92, 1), (44, 1), (17, 1), (83, 2), (62, 2), (50, 2), (26, 2), (69, 3), (29, 3)])",4.0 +spreading_minbudget,0.3931754000950604,100.0,"(11, [(3, 1), (15, 1), (28, 1), (54, 1), (71, 1), (96, 1), (97, 1), (17, 1), (35, 1), (45, 1), (22, 1)])",11.0 +heuristic_minbudget,1.0460371000226587,100.0,"(10, [(22, 1), (35, 1), (28, 1), (54, 1), (96, 1), (17, 1), (97, 1), (15, 1), (45, 1), (71, 1)])",10.0 +spreading_minbudget,0.2668848999310285,100.0,"(14, [(14, 1), (20, 1), (30, 1), (40, 1), (48, 1), (57, 1), (71, 1), (80, 1), (86, 1), (91, 1), (92, 1), (96, 1), (5, 1), (89, 1)])",14.0 +heuristic_minbudget,3.63022309995722,100.0,"(14, [(14, 1), (40, 1), (48, 1), (86, 1), (96, 1), (20, 1), (91, 1), (80, 1), (92, 1), (71, 1), (30, 1), (5, 1), (57, 1), (89, 1)])",14.0 +spreading_minbudget,1.212209300021641,200.0,"(22, [(70, 1), (128, 1), (53, 1), (55, 1), (125, 1), (152, 1), (28, 1), (104, 1), (17, 1), (20, 1), (174, 1), (5, 1), (31, 1), (35, 1), (44, 1), (120, 1), (151, 1), (172, 1), (175, 1), (190, 1), (146, 1), (168, 1)])",22.0 +heuristic_minbudget,1.0129838000284508,200.0,"(14, [(174, 1), (151, 1), (146, 1), (168, 1), (17, 1), (172, 1), (152, 1), (190, 1), (35, 1), (5, 1), (44, 1), (175, 1), (120, 1), (52, 1), (128, 2), (109, 2), (148, 2), (16, 2), (76, 2), (32, 2), (114, 2), (8, 2), (95, 2), (39, 2), (48, 2), (138, 2), (116, 2), (157, 2)])",14.0 +spreading_minbudget,0.5931069999933243,200.0,"(5, [(5, 1), (44, 1), (193, 1), (170, 1), (24, 1)])",5.0 +heuristic_minbudget,5.592074999934994,200.0,"(4, [(44, 1), (24, 1), (193, 1), (170, 1)])",4.0 +spreading_minbudget,1.2939483999507502,200.0,"(40, [(89, 1), (3, 1), (4, 1), (13, 1), (17, 1), (19, 1), (27, 1), (45, 1), (50, 1), (62, 1), (74, 1), (84, 1), (92, 1), (95, 1), (97, 1), (118, 1), (119, 1), (123, 1), (124, 1), (128, 1), (138, 1), (142, 1), (144, 1), (146, 1), (152, 1), (153, 1), (180, 1), (191, 1), (198, 1), (11, 1), (29, 1), (93, 1), (100, 1), (141, 1), (164, 1), (167, 1), (173, 1), (184, 1), (102, 1), (86, 1)])",40.0 +heuristic_minbudget,20.179923600051552,200.0,"(40, [(4, 1), (146, 1), (144, 1), (153, 1), (152, 1), (62, 1), (173, 1), (119, 1), (13, 1), (89, 1), (142, 1), (164, 1), (27, 1), (45, 1), (102, 1), (95, 1), (141, 1), (128, 1), (29, 1), (167, 1), (86, 1), (191, 1), (74, 1), (100, 1), (11, 1), (84, 1), (3, 1), (118, 1), (93, 1), (180, 1), (92, 1), (50, 1), (138, 1), (17, 1), (184, 1), (19, 1), (124, 1), (123, 1), (198, 1), (97, 1)])",40.0 +spreading_minbudget,3.5869039999088272,400.0,"(21, [(69, 1), (116, 1), (239, 1), (159, 1), (250, 1), (37, 1), (192, 1), (144, 1), (387, 1), (29, 1), (287, 1), (7, 1), (63, 1), (300, 1), (305, 1), (93, 1), (280, 1), (112, 1), (149, 1), (11, 1), (230, 1)])",21.0 +heuristic_minbudget,2.819514799979516,400.0,"(15, [(287, 1), (305, 1), (300, 1), (149, 1), (63, 1), (11, 1), (93, 1), (280, 1), (112, 1), (230, 1), (29, 1), (343, 1), (103, 1), (364, 1), (339, 1), (190, 2), (110, 2), (121, 2), (393, 2), (193, 2), (200, 2), (354, 2), (1, 2), (147, 2), (159, 2), (367, 2), (267, 2), (204, 2), (50, 2), (373, 2)])",15.0 +spreading_minbudget,6.544073999975808,400.0,"(63, [(103, 1), (333, 1), (88, 1), (2, 1), (17, 1), (27, 1), (29, 1), (66, 1), (72, 1), (76, 1), (89, 1), (135, 1), (143, 1), (148, 1), (150, 1), (152, 1), (165, 1), (166, 1), (190, 1), (222, 1), (250, 1), (257, 1), (275, 1), (289, 1), (291, 1), (292, 1), (293, 1), (306, 1), (315, 1), (326, 1), (327, 1), (363, 1), (373, 1), (380, 1), (386, 1), (40, 1), (109, 1), (112, 1), (140, 1), (182, 1), (229, 1), (238, 1), (239, 1), (325, 1), (390, 1), (9, 1), (90, 1), (171, 1), (184, 1), (359, 1), (385, 1), (393, 1), (11, 1), (51, 1), (71, 1), (212, 1), (364, 1), (230, 1), (368, 1), (391, 1), (52, 1), (353, 1), (276, 1)])",63.0 +heuristic_minbudget,45.2434607000323,400.0,"(62, [(327, 1), (150, 1), (364, 1), (166, 1), (291, 1), (143, 1), (229, 1), (315, 1), (17, 1), (109, 1), (212, 1), (27, 1), (2, 1), (11, 1), (257, 1), (306, 1), (148, 1), (239, 1), (390, 1), (363, 1), (71, 1), (76, 1), (275, 1), (276, 1), (72, 1), (184, 1), (325, 1), (353, 1), (51, 1), (135, 1), (112, 1), (165, 1), (238, 1), (293, 1), (289, 1), (385, 1), (9, 1), (140, 1), (222, 1), (250, 1), (386, 1), (359, 1), (29, 1), (373, 1), (292, 1), (391, 1), (326, 1), (40, 1), (380, 1), (171, 1), (230, 1), (393, 1), (182, 1), (368, 1), (52, 1), (66, 1), (152, 1), (88, 1), (89, 1), (333, 1), (190, 1), (90, 1)])",62.0 +spreading_minbudget,4.017668400076218,400.0,"(43, [(44, 1), (56, 1), (71, 1), (104, 1), (105, 1), (110, 1), (130, 1), (142, 1), (151, 1), (157, 1), (171, 1), (179, 1), (189, 1), (214, 1), (222, 1), (229, 1), (232, 1), (271, 1), (281, 1), (296, 1), (297, 1), (308, 1), (309, 1), (335, 1), (339, 1), (344, 1), (354, 1), (355, 1), (359, 1), (371, 1), (373, 1), (382, 1), (385, 1), (68, 1), (89, 1), (98, 1), (150, 1), (253, 1), (254, 1), (307, 1), (369, 1), (378, 1), (84, 1)])",43.0 +heuristic_minbudget,96.92596789996604,400.0,"(43, [(56, 1), (84, 1), (222, 1), (214, 1), (307, 1), (335, 1), (369, 1), (371, 1), (309, 1), (339, 1), (104, 1), (189, 1), (229, 1), (232, 1), (382, 1), (296, 1), (130, 1), (151, 1), (171, 1), (110, 1), (179, 1), (271, 1), (71, 1), (344, 1), (354, 1), (378, 1), (254, 1), (385, 1), (68, 1), (157, 1), (281, 1), (308, 1), (44, 1), (373, 1), (105, 1), (359, 1), (142, 1), (253, 1), (297, 1), (150, 1), (355, 1), (89, 1), (98, 1)])",43.0 diff --git a/experiments/spreading_minbudget.csv b/experiments/spreading_minbudget.csv new file mode 100644 index 0000000..ab7013e --- /dev/null +++ b/experiments/spreading_minbudget.csv @@ -0,0 +1,114 @@ +algorithm,runtime,graph_nodes,edge_probability,Budget +spreading_minbudget,0.6043815999873914,100,0.1,"(4, [(6, 1), (23, 1), (27, 1), (25, 1)])" +heuristic_minbudget,0.08351690000563394,100,0.1,"(2, [(25, 1), (6, 1), (27, 2), (23, 2), (41, 3), (72, 3)])" +spreading_minbudget,0.798920300003374,100,0.1,"(3, [(94, 1), (6, 1), (76, 1), (79, 2), (16, 2), (99, 2)])" +heuristic_minbudget,0.0549452000122983,100,0.1,"(3, [(6, 1), (19, 1), (85, 1), (18, 2), (87, 2), (17, 2), (81, 3)])" +spreading_minbudget,1.2247725000052014,100,0.1,"(7, [(6, 1), (70, 1), (23, 1), (36, 1), (47, 1), (2, 1), (25, 1)])" +heuristic_minbudget,0.20194240000273567,100,0.1,"(4, [(47, 1), (25, 1), (19, 1), (85, 1), (17, 2), (96, 2), (61, 2), (67, 2), (42, 3)])" +spreading_minbudget,0.5262910000019474,100,0.1,"(1, [(26, 1), (52, 2)])" +heuristic_minbudget,0.09640729999227915,100,0.1,"(2, [(19, 1), (14, 1), (52, 2), (76, 2), (22, 3), (60, 3)])" +spreading_minbudget,1.2042019000073196,100,0.1,"(6, [(72, 1), (91, 1), (16, 1), (14, 1), (38, 1), (25, 1)])" +heuristic_minbudget,0.12059449999651406,100,0.1,"(4, [(14, 1), (25, 1), (19, 1), (47, 1), (90, 2), (65, 2), (91, 2), (21, 2), (42, 3), (70, 3)])" +spreading_minbudget,0.1407623999984935,100,0.1,"(1, [(6, 1)])" +heuristic_minbudget,0.07592089999525342,100,0.1,"(1, [(6, 1), (84, 2)])" +spreading_minbudget,1.4573968000040622,100,0.1,"(6, [(9, 1), (13, 1), (19, 1), (23, 1), (3, 1), (47, 1)])" +heuristic_minbudget,0.07776210000156425,100,0.1,"(4, [(19, 1), (47, 1), (6, 1), (85, 1), (78, 2), (87, 2), (71, 2), (39, 2)])" +spreading_minbudget,0.8562765999959083,100,0.1,"(3, [(30, 1), (10, 1), (11, 1), (33, 2), (1, 2), (55, 2)])" +heuristic_minbudget,0.05599090000032447,100,0.1,"(3, [(6, 1), (85, 1), (14, 1), (11, 2), (89, 2), (78, 2), (69, 3)])" +spreading_minbudget,0.5544522999989567,100,0.1,"(1, [(6, 1), (78, 2)])" +heuristic_minbudget,0.09719980000227224,100,0.1,"(2, [(25, 1), (6, 1), (93, 2), (11, 2), (72, 3), (64, 3)])" +spreading_minbudget,0.4506552999955602,100,0.1,"(2, [(6, 1), (2, 1), (84, 2), (1, 2)])" +heuristic_minbudget,0.08434780000243336,100,0.1,"(2, [(6, 1), (19, 1), (84, 2), (17, 2), (72, 3), (69, 3)])" +spreading_minbudget,2.9608414999966044,100,0.5,"(29, [(54, 1), (37, 1), (9, 1), (11, 1), (12, 1), (23, 1), (31, 1), (46, 1), (60, 1), (61, 1), (88, 1), (90, 1), (2, 1), (15, 1), (24, 1), (27, 1), (45, 1), (62, 1), (20, 1), (26, 1), (32, 1), (86, 1), (94, 1), (97, 1), (28, 1), (66, 1), (93, 1), (13, 1), (65, 1)])" +heuristic_minbudget,2.033734099997673,100,0.5,"(29, [(37, 1), (45, 1), (65, 1), (12, 1), (46, 1), (88, 1), (24, 1), (54, 1), (93, 1), (28, 1), (26, 1), (13, 1), (60, 1), (62, 1), (31, 1), (61, 1), (27, 1), (90, 1), (2, 1), (9, 1), (23, 1), (20, 1), (66, 1), (94, 1), (97, 1), (15, 1), (86, 1), (32, 1), (11, 1)])" +spreading_minbudget,2.7890169999882346,100,0.5,"(24, [(31, 1), (38, 1), (16, 1), (46, 1), (48, 1), (61, 1), (82, 1), (84, 1), (98, 1), (2, 1), (15, 1), (45, 1), (54, 1), (62, 1), (64, 1), (77, 1), (79, 1), (85, 1), (26, 1), (32, 1), (34, 1), (78, 1), (28, 1), (93, 1)])" +heuristic_minbudget,1.3695207999990089,100,0.5,"(22, [(85, 1), (98, 1), (54, 1), (84, 1), (46, 1), (28, 1), (45, 1), (48, 1), (15, 1), (26, 1), (93, 1), (34, 1), (61, 1), (62, 1), (79, 1), (82, 1), (16, 1), (78, 1), (2, 1), (32, 1), (77, 1), (64, 1)])" +spreading_minbudget,0.29501640000671614,100,0.5,"(2, [(34, 1), (82, 1)])" +heuristic_minbudget,0.8983767999889096,100,0.5,"(2, [(34, 1), (82, 1)])" +spreading_minbudget,1.612422099991818,100,0.5,"(16, [(60, 1), (9, 1), (11, 1), (30, 1), (46, 1), (90, 1), (2, 1), (15, 1), (29, 1), (37, 1), (77, 1), (85, 1), (52, 1), (78, 1), (28, 1), (13, 1)])" +heuristic_minbudget,1.2286775999964448,100,0.5,"(16, [(52, 1), (28, 1), (85, 1), (29, 1), (37, 1), (46, 1), (13, 1), (60, 1), (90, 1), (2, 1), (30, 1), (15, 1), (78, 1), (9, 1), (77, 1), (11, 1)])" +spreading_minbudget,1.9392723999917507,100,0.5,"(18, [(58, 1), (22, 1), (46, 1), (48, 1), (61, 1), (2, 1), (19, 1), (37, 1), (64, 1), (77, 1), (79, 1), (85, 1), (32, 1), (72, 1), (78, 1), (28, 1), (66, 1), (13, 1)])" +heuristic_minbudget,1.2242184999922756,100,0.5,"(17, [(22, 1), (72, 1), (13, 1), (37, 1), (46, 1), (28, 1), (48, 1), (61, 1), (85, 1), (19, 1), (32, 1), (78, 1), (2, 1), (79, 1), (77, 1), (66, 1), (64, 1)])" +spreading_minbudget,2.1627451999956975,100,0.5,"(19, [(67, 1), (7, 1), (9, 1), (11, 1), (31, 1), (88, 1), (90, 1), (91, 1), (17, 1), (37, 1), (45, 1), (62, 1), (64, 1), (20, 1), (22, 1), (72, 1), (97, 1), (92, 1), (65, 1)])" +heuristic_minbudget,1.7830877999949735,100,0.5,"(17, [(88, 1), (22, 1), (91, 1), (37, 1), (45, 1), (65, 1), (20, 1), (31, 1), (9, 1), (72, 1), (90, 1), (17, 1), (62, 1), (92, 1), (11, 1), (97, 1), (64, 1)])" +spreading_minbudget,3.6650694999989355,100,0.5,"(29, [(30, 1), (46, 1), (11, 1), (12, 1), (16, 1), (41, 1), (61, 1), (82, 1), (84, 1), (88, 1), (98, 1), (2, 1), (15, 1), (24, 1), (27, 1), (45, 1), (77, 1), (79, 1), (85, 1), (22, 1), (43, 1), (72, 1), (74, 1), (78, 1), (86, 1), (97, 1), (92, 1), (13, 1), (65, 1)])" +heuristic_minbudget,2.367954000001191,100,0.5,"(29, [(98, 1), (85, 1), (24, 1), (84, 1), (46, 1), (88, 1), (22, 1), (12, 1), (27, 1), (65, 1), (45, 1), (41, 1), (61, 1), (72, 1), (13, 1), (2, 1), (43, 1), (79, 1), (86, 1), (92, 1), (15, 1), (30, 1), (77, 1), (82, 1), (97, 1), (11, 1), (16, 1), (74, 1), (78, 1)])" +spreading_minbudget,1.6317382999986876,100,0.5,"(13, [(12, 1), (7, 1), (11, 1), (16, 1), (88, 1), (15, 1), (19, 1), (27, 1), (54, 1), (20, 1), (26, 1), (43, 1), (28, 1)])" +heuristic_minbudget,1.2327431000012439,100,0.5,"(13, [(27, 1), (20, 1), (88, 1), (12, 1), (28, 1), (54, 1), (26, 1), (7, 1), (43, 1), (15, 1), (19, 1), (16, 1), (11, 1)])" +spreading_minbudget,1.377598899998702,100,0.5,"(9, [(23, 1), (82, 1), (30, 1), (40, 1), (62, 1), (79, 1), (85, 1), (22, 1), (92, 1)])" +heuristic_minbudget,1.0871489999990445,100,0.5,"(8, [(85, 1), (79, 1), (82, 1), (40, 1), (22, 1), (62, 1), (30, 1), (92, 1)])" +spreading_minbudget,1.249198300007265,100,0.5,"(12, [(31, 1), (16, 1), (41, 1), (84, 1), (90, 1), (24, 1), (29, 1), (37, 1), (40, 1), (85, 1), (13, 1), (65, 1)])" +heuristic_minbudget,1.291403099996387,100,0.5,"(11, [(84, 1), (29, 1), (37, 1), (40, 1), (24, 1), (85, 1), (65, 1), (41, 1), (13, 1), (90, 1), (16, 1)])" +spreading_minbudget,0.8987213000073098,100,0.8,"(8, [(84, 1), (16, 1), (21, 1), (68, 1), (86, 1), (87, 1), (44, 1), (52, 1)])" +heuristic_minbudget,2.5706658999988576,100,0.8,"(8, [(52, 1), (84, 1), (21, 1), (87, 1), (16, 1), (86, 1), (44, 1), (68, 1)])" +spreading_minbudget,0.5972516000038013,100,0.8,"(7, [(19, 1), (6, 1), (24, 1), (42, 1), (66, 1), (71, 1), (72, 1)])" +heuristic_minbudget,2.627842400004738,100,0.8,"(7, [(24, 1), (6, 1), (71, 1), (19, 1), (66, 1), (72, 1), (42, 1)])" +spreading_minbudget,2.4423267999954987,100,0.8,"(25, [(22, 1), (1, 1), (6, 1), (8, 1), (9, 1), (23, 1), (25, 1), (27, 1), (42, 1), (51, 1), (56, 1), (58, 1), (63, 1), (72, 1), (76, 1), (79, 1), (86, 1), (93, 1), (4, 1), (15, 1), (33, 1), (34, 1), (41, 1), (44, 1), (11, 1)])" +heuristic_minbudget,3.5214248999982374,100,0.8,"(25, [(27, 1), (76, 1), (6, 1), (4, 1), (25, 1), (58, 1), (34, 1), (51, 1), (9, 1), (8, 1), (22, 1), (11, 1), (15, 1), (23, 1), (33, 1), (44, 1), (56, 1), (86, 1), (93, 1), (1, 1), (79, 1), (41, 1), (63, 1), (72, 1), (42, 1)])" +spreading_minbudget,2.2762453999894205,100,0.8,"(23, [(21, 1), (2, 1), (8, 1), (9, 1), (16, 1), (22, 1), (29, 1), (37, 1), (48, 1), (53, 1), (65, 1), (71, 1), (76, 1), (85, 1), (86, 1), (89, 1), (91, 1), (95, 1), (96, 1), (97, 1), (98, 1), (74, 1), (94, 1)])" +heuristic_minbudget,3.9915353000105824,100,0.8,"(23, [(76, 1), (2, 1), (48, 1), (98, 1), (9, 1), (29, 1), (21, 1), (22, 1), (91, 1), (37, 1), (16, 1), (65, 1), (8, 1), (71, 1), (85, 1), (89, 1), (86, 1), (94, 1), (74, 1), (97, 1), (95, 1), (53, 1), (96, 1)])" +spreading_minbudget,3.2877872999961255,100,0.8,"(33, [(69, 1), (1, 1), (2, 1), (6, 1), (8, 1), (10, 1), (12, 1), (22, 1), (23, 1), (24, 1), (25, 1), (27, 1), (29, 1), (31, 1), (37, 1), (43, 1), (45, 1), (46, 1), (48, 1), (53, 1), (58, 1), (65, 1), (66, 1), (67, 1), (82, 1), (89, 1), (95, 1), (98, 1), (4, 1), (33, 1), (41, 1), (52, 1), (94, 1)])" +heuristic_minbudget,4.246031399990898,100,0.8,"(33, [(6, 1), (4, 1), (25, 1), (48, 1), (2, 1), (24, 1), (52, 1), (58, 1), (27, 1), (69, 1), (22, 1), (37, 1), (29, 1), (94, 1), (43, 1), (46, 1), (65, 1), (82, 1), (98, 1), (89, 1), (8, 1), (45, 1), (10, 1), (66, 1), (12, 1), (23, 1), (33, 1), (41, 1), (1, 1), (31, 1), (67, 1), (53, 1), (95, 1)])" +spreading_minbudget,2.8299892999930307,100,0.8,"(27, [(5, 1), (1, 1), (6, 1), (8, 1), (9, 1), (20, 1), (27, 1), (31, 1), (37, 1), (46, 1), (51, 1), (53, 1), (55, 1), (58, 1), (63, 1), (64, 1), (66, 1), (73, 1), (79, 1), (81, 1), (83, 1), (85, 1), (91, 1), (98, 1), (41, 1), (44, 1), (18, 1)])" +heuristic_minbudget,4.0879720999946585,100,0.8,"(27, [(58, 1), (6, 1), (51, 1), (20, 1), (98, 1), (27, 1), (64, 1), (8, 1), (9, 1), (73, 1), (46, 1), (37, 1), (5, 1), (83, 1), (55, 1), (41, 1), (81, 1), (18, 1), (31, 1), (91, 1), (53, 1), (1, 1), (63, 1), (44, 1), (85, 1), (66, 1), (79, 1)])" +spreading_minbudget,3.92984680000518,100,0.8,"(41, [(16, 1), (1, 1), (2, 1), (10, 1), (13, 1), (19, 1), (23, 1), (24, 1), (27, 1), (29, 1), (32, 1), (39, 1), (46, 1), (51, 1), (53, 1), (56, 1), (59, 1), (62, 1), (64, 1), (66, 1), (67, 1), (68, 1), (77, 1), (79, 1), (82, 1), (85, 1), (87, 1), (89, 1), (93, 1), (95, 1), (96, 1), (98, 1), (99, 1), (33, 1), (34, 1), (41, 1), (44, 1), (94, 1), (11, 1), (40, 1), (18, 1)])" +heuristic_minbudget,3.953235400011181,100,0.8,"(41, [(67, 1), (39, 1), (34, 1), (24, 1), (2, 1), (40, 1), (51, 1), (82, 1), (29, 1), (27, 1), (46, 1), (87, 1), (64, 1), (56, 1), (16, 1), (19, 1), (23, 1), (53, 1), (94, 1), (10, 1), (98, 1), (66, 1), (1, 1), (44, 1), (33, 1), (11, 1), (13, 1), (18, 1), (32, 1), (59, 1), (93, 1), (85, 1), (41, 1), (79, 1), (89, 1), (62, 1), (68, 1), (95, 1), (96, 1), (77, 1), (99, 1)])" +spreading_minbudget,1.3322335999982897,100,0.8,"(14, [(6, 1), (1, 1), (22, 1), (29, 1), (46, 1), (58, 1), (69, 1), (75, 1), (77, 1), (82, 1), (85, 1), (92, 1), (95, 1), (40, 1)])" +heuristic_minbudget,2.7363971000013407,100,0.8,"(14, [(6, 1), (40, 1), (58, 1), (29, 1), (82, 1), (69, 1), (22, 1), (46, 1), (92, 1), (85, 1), (77, 1), (1, 1), (75, 1), (95, 1)])" +spreading_minbudget,0.8161610999959521,100,0.8,"(8, [(22, 1), (31, 1), (45, 1), (85, 1), (86, 1), (91, 1), (96, 1), (44, 1)])" +heuristic_minbudget,2.7852620000048773,100,0.8,"(8, [(45, 1), (22, 1), (91, 1), (31, 1), (86, 1), (44, 1), (85, 1), (96, 1)])" +spreading_minbudget,1.302543899990269,100,0.8,"(14, [(2, 1), (10, 1), (45, 1), (63, 1), (64, 1), (65, 1), (79, 1), (85, 1), (91, 1), (92, 1), (96, 1), (52, 1), (74, 1), (40, 1)])" +heuristic_minbudget,4.053526600007899,100,0.8,"(14, [(2, 1), (40, 1), (52, 1), (64, 1), (65, 1), (91, 1), (45, 1), (92, 1), (10, 1), (74, 1), (85, 1), (63, 1), (79, 1), (96, 1)])" +spreading_minbudget,6.874619900001562,200,0.1,"(13, [(48, 1), (24, 1), (157, 1), (42, 1), (196, 1), (33, 1), (21, 1), (59, 1), (153, 1), (28, 1), (52, 1), (136, 1), (99, 1)])" +heuristic_minbudget,0.3828627999901073,200,0.1,"(8, [(99, 1), (52, 1), (153, 1), (136, 1), (28, 1), (48, 1), (147, 1), (194, 1), (92, 2), (91, 2), (50, 2), (1, 2), (186, 2), (82, 2), (42, 2), (178, 2)])" +spreading_minbudget,3.6053887000016402,200,0.1,"(8, [(116, 1), (153, 1), (45, 1), (49, 1), (105, 1), (95, 1), (65, 1), (99, 1)])" +heuristic_minbudget,0.43296489999920595,200,0.1,"(5, [(99, 1), (65, 1), (153, 1), (194, 1), (76, 1), (64, 2), (29, 2), (91, 2), (168, 2), (80, 2)])" +spreading_minbudget,6.127774299995508,200,0.1,"(12, [(57, 1), (164, 1), (21, 1), (49, 1), (108, 1), (194, 1), (11, 1), (42, 1), (68, 1), (153, 1), (65, 1), (28, 1)])" +heuristic_minbudget,0.5014686999929836,200,0.1,"(8, [(194, 1), (153, 1), (28, 1), (65, 1), (106, 1), (48, 1), (52, 1), (76, 1), (29, 2), (177, 2), (142, 2), (171, 2), (178, 2), (120, 2), (16, 2), (128, 2)])" +spreading_minbudget,6.081753100006608,200,0.1,"(14, [(155, 1), (131, 1), (185, 1), (6, 1), (44, 1), (76, 1), (147, 1), (153, 1), (79, 1), (161, 1), (28, 1), (112, 1), (52, 1), (106, 1)])" +heuristic_minbudget,0.3598169000033522,200,0.1,"(8, [(147, 1), (153, 1), (52, 1), (76, 1), (106, 1), (112, 1), (28, 1), (48, 1), (192, 2), (3, 2), (101, 2), (22, 2), (122, 2), (78, 2), (195, 2), (17, 2)])" +spreading_minbudget,6.416437199994107,200,0.1,"(10, [(194, 1), (6, 1), (52, 1), (101, 1), (4, 1), (170, 1), (46, 1), (9, 1), (41, 1), (28, 1)])" +heuristic_minbudget,0.5401426000025822,200,0.1,"(8, [(52, 1), (4, 1), (28, 1), (194, 1), (106, 1), (147, 1), (76, 1), (48, 1), (17, 2), (2, 2), (61, 2), (50, 2), (115, 2), (143, 2), (16, 2), (93, 2)])" +spreading_minbudget,7.155516500002705,200,0.1,"(13, [(124, 1), (196, 1), (116, 1), (66, 1), (21, 1), (120, 1), (128, 1), (138, 1), (44, 1), (72, 1), (48, 1), (65, 1), (136, 1)])" +heuristic_minbudget,0.45384590000321623,200,0.1,"(9, [(48, 1), (44, 1), (136, 1), (65, 1), (147, 1), (52, 1), (194, 1), (76, 1), (106, 1), (170, 2), (184, 2), (12, 2), (50, 2), (2, 2), (57, 2), (129, 2), (87, 2), (69, 2)])" +spreading_minbudget,5.644121200006339,200,0.1,"(13, [(129, 1), (199, 1), (44, 1), (82, 1), (39, 1), (76, 1), (182, 1), (194, 1), (54, 1), (161, 1), (4, 1), (28, 1), (52, 1)])" +heuristic_minbudget,0.48520840000128374,200,0.1,"(9, [(194, 1), (76, 1), (52, 1), (4, 1), (28, 1), (161, 1), (147, 1), (48, 1), (44, 1), (17, 2), (107, 2), (57, 2), (129, 2), (122, 2), (81, 2), (108, 2), (121, 2), (2, 2)])" +spreading_minbudget,1.8839236000058008,200,0.1,"(5, [(48, 1), (91, 1), (42, 1), (136, 1), (106, 1)])" +heuristic_minbudget,0.398219099995913,200,0.1,"(3, [(136, 1), (106, 1), (48, 1), (157, 2), (128, 2), (120, 2)])" +spreading_minbudget,8.769554500002414,200,0.1,"(16, [(3, 1), (157, 1), (116, 1), (106, 1), (70, 1), (44, 1), (17, 1), (43, 1), (138, 1), (194, 1), (147, 1), (76, 1), (4, 1), (48, 1), (65, 1), (112, 1)])" +heuristic_minbudget,0.48429249999753665,200,0.1,"(10, [(48, 1), (147, 1), (194, 1), (76, 1), (106, 1), (44, 1), (65, 1), (112, 1), (4, 1), (52, 1), (142, 2), (16, 2), (107, 2), (69, 2), (42, 2), (12, 2), (143, 2), (87, 2), (6, 2), (177, 2)])" +spreading_minbudget,4.215613599997596,200,0.1,"(9, [(116, 1), (33, 1), (70, 1), (101, 1), (21, 1), (194, 1), (4, 1), (52, 1), (106, 1)])" +heuristic_minbudget,0.4958438000030583,200,0.1,"(6, [(52, 1), (106, 1), (4, 1), (147, 1), (194, 1), (76, 1), (59, 2), (81, 2), (2, 2), (129, 2), (61, 2), (16, 2)])" +spreading_minbudget,0.1568801999965217,200,0.5,"(1, [(10, 1)])" +heuristic_minbudget,3.0877527999982703,200,0.5,"(1, [(132, 1)])" +spreading_minbudget,2.236697499989532,200,0.5,"(6, [(99, 1), (168, 1), (175, 1), (31, 1), (149, 1), (177, 1)])" +heuristic_minbudget,3.3113985999953,200,0.5,"(5, [(149, 1), (168, 1), (177, 1), (31, 1), (175, 1)])" +spreading_minbudget,9.140447199999471,200,0.5,"(32, [(59, 1), (144, 1), (63, 1), (19, 1), (34, 1), (41, 1), (50, 1), (65, 1), (82, 1), (85, 1), (103, 1), (116, 1), (130, 1), (143, 1), (168, 1), (180, 1), (184, 1), (191, 1), (193, 1), (28, 1), (75, 1), (139, 1), (146, 1), (149, 1), (162, 1), (61, 1), (68, 1), (81, 1), (137, 1), (186, 1), (153, 1), (192, 1)])" +heuristic_minbudget,5.723877700002049,200,0.5,"(31, [(184, 1), (143, 1), (116, 1), (61, 1), (59, 1), (149, 1), (130, 1), (186, 1), (75, 1), (68, 1), (82, 1), (103, 1), (162, 1), (191, 1), (193, 1), (41, 1), (19, 1), (180, 1), (192, 1), (28, 1), (85, 1), (50, 1), (168, 1), (63, 1), (34, 1), (137, 1), (153, 1), (146, 1), (65, 1), (139, 1), (81, 1)])" +spreading_minbudget,2.4964694999944186,200,0.5,"(8, [(63, 1), (85, 1), (140, 1), (180, 1), (193, 1), (197, 1), (199, 1), (119, 1)])" +heuristic_minbudget,3.2830257000023266,200,0.5,"(7, [(180, 1), (140, 1), (193, 1), (119, 1), (199, 1), (85, 1), (197, 1)])" +spreading_minbudget,1.0909339999925578,200,0.5,"(2, [(4, 1), (192, 1)])" +heuristic_minbudget,3.0061140000034356,200,0.5,"(2, [(192, 1), (108, 1)])" +spreading_minbudget,2.8638310999958776,200,0.5,"(9, [(31, 1), (13, 1), (41, 1), (45, 1), (103, 1), (116, 1), (74, 1), (127, 1), (68, 1)])" +heuristic_minbudget,3.336111199998413,200,0.5,"(7, [(45, 1), (41, 1), (116, 1), (68, 1), (103, 1), (127, 1), (74, 1)])" +spreading_minbudget,6.566627099993639,200,0.5,"(19, [(1, 1), (76, 1), (34, 1), (112, 1), (160, 1), (193, 1), (197, 1), (55, 1), (69, 1), (86, 1), (122, 1), (139, 1), (141, 1), (159, 1), (196, 1), (137, 1), (16, 1), (153, 1), (93, 1)])" +heuristic_minbudget,4.1070819000015035,200,0.5,"(17, [(86, 1), (139, 1), (193, 1), (122, 1), (196, 1), (69, 1), (93, 1), (159, 1), (55, 1), (153, 1), (112, 1), (34, 1), (141, 1), (137, 1), (16, 1), (160, 1), (197, 1)])" +spreading_minbudget,11.145615999994334,200,0.5,"(35, [(99, 1), (138, 1), (48, 1), (32, 1), (44, 1), (52, 1), (56, 1), (85, 1), (103, 1), (107, 1), (120, 1), (130, 1), (140, 1), (160, 1), (175, 1), (180, 1), (191, 1), (8, 1), (25, 1), (55, 1), (67, 1), (69, 1), (74, 1), (86, 1), (132, 1), (139, 1), (141, 1), (159, 1), (68, 1), (98, 1), (104, 1), (186, 1), (177, 1), (119, 1), (21, 1)])" +heuristic_minbudget,6.92385840001225,200,0.5,"(33, [(103, 1), (67, 1), (68, 1), (130, 1), (132, 1), (48, 1), (186, 1), (177, 1), (69, 1), (21, 1), (191, 1), (98, 1), (104, 1), (107, 1), (119, 1), (180, 1), (32, 1), (140, 1), (159, 1), (85, 1), (120, 1), (86, 1), (175, 1), (52, 1), (8, 1), (55, 1), (25, 1), (139, 1), (160, 1), (56, 1), (44, 1), (141, 1), (74, 1)])" +spreading_minbudget,7.714225499992608,200,0.5,"(27, [(194, 1), (30, 1), (19, 1), (41, 1), (56, 1), (65, 1), (85, 1), (87, 1), (115, 1), (116, 1), (121, 1), (130, 1), (140, 1), (143, 1), (168, 1), (175, 1), (180, 1), (181, 1), (17, 1), (67, 1), (122, 1), (138, 1), (141, 1), (196, 1), (68, 1), (81, 1), (104, 1)])" +heuristic_minbudget,4.569759200006956,200,0.5,"(26, [(30, 1), (138, 1), (121, 1), (130, 1), (41, 1), (116, 1), (67, 1), (196, 1), (68, 1), (87, 1), (19, 1), (168, 1), (17, 1), (104, 1), (115, 1), (180, 1), (85, 1), (143, 1), (140, 1), (175, 1), (181, 1), (122, 1), (56, 1), (65, 1), (141, 1), (81, 1)])" +spreading_minbudget,5.409246000010171,200,0.5,"(21, [(184, 1), (34, 1), (45, 1), (52, 1), (80, 1), (103, 1), (112, 1), (120, 1), (130, 1), (143, 1), (168, 1), (175, 1), (193, 1), (199, 1), (8, 1), (28, 1), (109, 1), (135, 1), (198, 1), (61, 1), (119, 1)])" +heuristic_minbudget,4.488193300014245,200,0.5,"(21, [(184, 1), (45, 1), (193, 1), (61, 1), (130, 1), (119, 1), (103, 1), (199, 1), (80, 1), (52, 1), (28, 1), (120, 1), (143, 1), (175, 1), (34, 1), (135, 1), (168, 1), (8, 1), (109, 1), (112, 1), (198, 1)])" +spreading_minbudget,5.363142900008825,200,0.8,"(21, [(3, 1), (21, 1), (33, 1), (44, 1), (45, 1), (68, 1), (69, 1), (70, 1), (74, 1), (138, 1), (149, 1), (150, 1), (155, 1), (171, 1), (176, 1), (179, 1), (195, 1), (198, 1), (37, 1), (162, 1), (190, 1)])" +heuristic_minbudget,13.136786300005042,200,0.8,"(21, [(195, 1), (171, 1), (150, 1), (155, 1), (44, 1), (3, 1), (45, 1), (74, 1), (69, 1), (190, 1), (68, 1), (179, 1), (149, 1), (37, 1), (162, 1), (21, 1), (138, 1), (70, 1), (198, 1), (176, 1), (33, 1)])" +spreading_minbudget,13.20309090000228,200,0.8,"(63, [(17, 1), (6, 1), (13, 1), (16, 1), (21, 1), (22, 1), (23, 1), (25, 1), (26, 1), (28, 1), (33, 1), (35, 1), (36, 1), (38, 1), (39, 1), (43, 1), (53, 1), (58, 1), (60, 1), (61, 1), (65, 1), (68, 1), (70, 1), (71, 1), (73, 1), (77, 1), (78, 1), (88, 1), (90, 1), (99, 1), (108, 1), (109, 1), (113, 1), (124, 1), (129, 1), (131, 1), (134, 1), (136, 1), (140, 1), (142, 1), (148, 1), (150, 1), (155, 1), (163, 1), (175, 1), (176, 1), (178, 1), (179, 1), (184, 1), (192, 1), (195, 1), (196, 1), (198, 1), (199, 1), (5, 1), (8, 1), (15, 1), (29, 1), (63, 1), (95, 1), (123, 1), (133, 1), (146, 1)])" +heuristic_minbudget,18.206225700007053,200,0.8,"(63, [(53, 1), (26, 1), (88, 1), (5, 1), (23, 1), (38, 1), (150, 1), (155, 1), (178, 1), (39, 1), (108, 1), (134, 1), (13, 1), (36, 1), (163, 1), (17, 1), (109, 1), (175, 1), (195, 1), (63, 1), (113, 1), (8, 1), (77, 1), (71, 1), (124, 1), (136, 1), (140, 1), (21, 1), (148, 1), (22, 1), (43, 1), (60, 1), (123, 1), (142, 1), (65, 1), (6, 1), (35, 1), (196, 1), (68, 1), (95, 1), (176, 1), (179, 1), (28, 1), (146, 1), (29, 1), (58, 1), (70, 1), (61, 1), (25, 1), (73, 1), (78, 1), (199, 1), (133, 1), (33, 1), (99, 1), (131, 1), (90, 1), (184, 1), (198, 1), (15, 1), (129, 1), (16, 1), (192, 1)])" +spreading_minbudget,1.1575602000084473,200,0.8,"(5, [(80, 1), (28, 1), (86, 1), (134, 1), (195, 1)])" +heuristic_minbudget,9.099992300005397,200,0.8,"(5, [(80, 1), (134, 1), (28, 1), (195, 1), (86, 1)])" +spreading_minbudget,8.297417900001165,200,0.8,"(33, [(26, 1), (19, 1), (25, 1), (30, 1), (31, 1), (35, 1), (42, 1), (61, 1), (72, 1), (76, 1), (78, 1), (93, 1), (94, 1), (98, 1), (125, 1), (128, 1), (132, 1), (134, 1), (135, 1), (138, 1), (140, 1), (155, 1), (163, 1), (172, 1), (178, 1), (195, 1), (196, 1), (81, 1), (133, 1), (146, 1), (27, 1), (51, 1), (59, 1)])" +heuristic_minbudget,13.201126400002977,200,0.8,"(33, [(26, 1), (19, 1), (94, 1), (59, 1), (155, 1), (178, 1), (128, 1), (81, 1), (134, 1), (163, 1), (27, 1), (195, 1), (72, 1), (98, 1), (31, 1), (42, 1), (132, 1), (30, 1), (76, 1), (196, 1), (140, 1), (125, 1), (25, 1), (51, 1), (93, 1), (135, 1), (61, 1), (138, 1), (146, 1), (35, 1), (133, 1), (78, 1), (172, 1)])" +spreading_minbudget,12.984143499998027,200,0.8,"(63, [(89, 1), (3, 1), (13, 1), (14, 1), (16, 1), (17, 1), (23, 1), (32, 1), (33, 1), (38, 1), (40, 1), (41, 1), (42, 1), (45, 1), (47, 1), (56, 1), (58, 1), (64, 1), (65, 1), (67, 1), (68, 1), (75, 1), (76, 1), (80, 1), (86, 1), (90, 1), (92, 1), (93, 1), (98, 1), (99, 1), (100, 1), (106, 1), (112, 1), (117, 1), (121, 1), (131, 1), (132, 1), (134, 1), (136, 1), (142, 1), (150, 1), (151, 1), (158, 1), (164, 1), (171, 1), (174, 1), (175, 1), (183, 1), (187, 1), (188, 1), (196, 1), (197, 1), (198, 1), (199, 1), (5, 1), (8, 1), (52, 1), (95, 1), (96, 1), (102, 1), (116, 1), (123, 1), (87, 1)])" +heuristic_minbudget,17.87442839999858,200,0.8,"(63, [(175, 1), (5, 1), (171, 1), (89, 1), (23, 1), (102, 1), (40, 1), (38, 1), (150, 1), (47, 1), (151, 1), (197, 1), (13, 1), (52, 1), (17, 1), (41, 1), (75, 1), (96, 1), (76, 1), (65, 1), (56, 1), (80, 1), (116, 1), (132, 1), (134, 1), (8, 1), (98, 1), (67, 1), (136, 1), (42, 1), (58, 1), (174, 1), (86, 1), (32, 1), (121, 1), (164, 1), (3, 1), (196, 1), (95, 1), (112, 1), (68, 1), (64, 1), (131, 1), (100, 1), (123, 1), (142, 1), (187, 1), (117, 1), (188, 1), (14, 1), (45, 1), (199, 1), (198, 1), (16, 1), (106, 1), (33, 1), (87, 1), (158, 1), (92, 1), (99, 1), (90, 1), (93, 1), (183, 1)])" +spreading_minbudget,5.6764264999947045,200,0.8,"(27, [(66, 1), (6, 1), (16, 1), (25, 1), (31, 1), (38, 1), (41, 1), (57, 1), (65, 1), (76, 1), (89, 1), (92, 1), (106, 1), (126, 1), (140, 1), (158, 1), (160, 1), (167, 1), (174, 1), (182, 1), (185, 1), (192, 1), (196, 1), (52, 1), (95, 1), (102, 1), (181, 1)])" +heuristic_minbudget,13.88039399999252,200,0.8,"(27, [(76, 1), (185, 1), (66, 1), (89, 1), (102, 1), (38, 1), (174, 1), (65, 1), (6, 1), (52, 1), (182, 1), (167, 1), (41, 1), (196, 1), (25, 1), (126, 1), (140, 1), (95, 1), (31, 1), (181, 1), (16, 1), (92, 1), (158, 1), (57, 1), (160, 1), (106, 1), (192, 1)])" +spreading_minbudget,4.208028399996692,200,0.8,"(16, [(31, 1), (13, 1), (38, 1), (58, 1), (75, 1), (76, 1), (78, 1), (88, 1), (98, 1), (101, 1), (153, 1), (164, 1), (167, 1), (197, 1), (63, 1), (159, 1)])" diff --git a/networkz/algorithms/approximation/firefighter_problem/Firefighter_Problem.py b/networkz/algorithms/approximation/firefighter_problem/Firefighter_Problem.py new file mode 100644 index 0000000..4a3703b --- /dev/null +++ b/networkz/algorithms/approximation/firefighter_problem/Firefighter_Problem.py @@ -0,0 +1,524 @@ +""" +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import networkx as nx +import networkx.algorithms.connectivity as algo +import math +import logging +from networkz.algorithms.max_flow_with_node_capacity import min_cut_with_node_capacity +from networkz.algorithms.approximation.firefighter_problem.Utils import * + +def setup_logger(logger): + logger.setLevel(logging.INFO) + + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + console_handler.setFormatter(formatter) + + logger.addHandler(console_handler) + return logger + +logger = logging.getLogger('firefighter_problem_main') + + +def spreading_maxsave(Graph:nx.DiGraph, budget:int, source:int, targets:list, stop_condition=None) -> tuple[list, set]: + """ + Approximate the firefighter problem by maximizing the number of saved nodes. + + Parameters: + ---------- + Graph : nx.DiGraph + Directed graph representing the network. + budget : int + Number of nodes that can be vaccinated at each time step. + source : int + Source node where the infection starts. + targets : list + List of target nodes to be saved. + stop_condition : optional + If set, stops early if all targets are saved or if any target is infected. + + Returns: + ------- + tuple: + vaccination_strategy : list + List of tuples representing the vaccination strategy. + saved_target_nodes : set + Set of nodes that are saved from infection. + + Examples: + -------- + Example 1: + >>> G = nx.DiGraph() + >>> G.add_nodes_from([0,1,2], status="vulnerable") + >>> G.add_edges_from([(0,1),(0,2),(1,2)]) + >>> spreading_maxsave(G,1,0,[1,2]) + ([(1, 1)], {1}) + + Example 2: + >>> G1 = nx.DiGraph() + >>> G1.add_nodes_from([0,1,2,3], status="vulnerable") + >>> G1.add_edges_from([(0,1),(0,2),(1,2),(1,3),(2,3)]) + >>> spreading_maxsave(G1,1,0,[1,2,3]) + ([(1, 1)], {1, 3}) + + Example 3: + >>> G2 = nx.DiGraph() + >>> G2.add_nodes_from([0,1,2,3,4,5,6], status="vulnerable") + >>> G2.add_edges_from([(0,1),(0,2),(1,2),(1,4),(2,3),(2,6),(3,5)]) + >>> spreading_maxsave(G2,1,0,[1,2,3,4,5,6]) + ([(2, 1), (4, 2)], {2, 3, 4, 5, 6}) + + Example 4: + >>> G3 = nx.DiGraph() + >>> G3.add_nodes_from([0,1,2,3,4,5,6,7,8], status="vulnerable") + >>> G3.add_edges_from([(0,2),(0,4),(0,5),(2,1),(2,3),(4,1),(4,6),(5,3),(5,6),(5,7),(6,7),(6,8),(7,8)]) + >>> spreading_maxsave(G3,2,0,[1,2,3,4,5,6,7,8]) + ([(5, 1), (2, 1), (8, 2)], {1, 2, 3, 5, 6, 7, 8}) + """ + + if budget < 1: + logger.critical("Error: The budget must be at least 1") + raise ValueError("Error: The budget must be at least 1") + + validate_parameters(Graph, source, targets) + logger.info(f"Starting the spreading_maxsave function with source node {source}, budget {budget}, and targets: {targets}") + + clean_graph(Graph) + local_targets = targets.copy() + infected_nodes = [] + vaccinated_nodes = [] + vaccination_strategy = [] + saved_target_nodes = set() + can_spread = True + Graph.nodes[source]['status'] = Status.INFECTED.value + infected_nodes.append(source) + + logger.info("Calculating all possible direct vaccinations in each timestamp") + gamma, direct_vaccinations = calculate_gamma(Graph, source, targets) + + logger.info("Calculating direct vaccinations grouping by timestamp") + epsilon = calculate_epsilon(direct_vaccinations) + + time_step = 0 + while can_spread and time_step < len(epsilon): + spread_vaccination(Graph, vaccinated_nodes) + for i in range(budget): + logger.info(f"Calculating the best direct vaccination strategy for the current time step that saves more new nodes in targets (Current budget: {i+1} out of {budget})") + vaccination, nodes_saved = find_best_direct_vaccination(Graph, direct_vaccinations, epsilon[time_step], local_targets) + + if vaccination != (): + logger.info(f"Found {vaccination} as a solution for current timestamp. Appending to vaccination strategy and vaccinating the node") + vaccination_strategy.append(vaccination) + + chosen_node = vaccination[0] + vaccinate_node(Graph, chosen_node) + + vaccinated_nodes.append(chosen_node) + logger.info(f"Updated list of currently vaccinated nodes: {vaccinated_nodes}") + + if nodes_saved is not None: + saved_target_nodes.update(nodes_saved) + local_targets[:] = [element for element in local_targets if element not in nodes_saved] + logger.info(f"Updated list of targets: {local_targets}") + + else: + logger.info(f"All nodes are either vaccinated or infected") + break + + can_spread = spread_virus(Graph, infected_nodes) + + if stop_condition is not None: + if len(local_targets) == 0 or any(node in infected_nodes for node in local_targets): + logger.info(f"Returning vaccination strategy: {vaccination_strategy}. The strategy saved the nodes: {saved_target_nodes}") + return vaccination_strategy, saved_target_nodes + + time_step += 1 + + logger.info(f"Returning vaccination strategy: {vaccination_strategy}. The strategy saves the nodes: {saved_target_nodes}") + return vaccination_strategy, saved_target_nodes + + +def spreading_minbudget(Graph:nx.DiGraph, source:int, targets:list) -> tuple[int, list]: + """ + Approximate the firefighter problem by minimizing the budget required to save all target nodes. + + Parameters: + ---------- + Graph : nx.DiGraph + Directed graph representing the network. + source : int + Source node where the infection starts. + targets : list + List of target nodes to be saved. + + Returns: + ------- + tuple: + min_budget : int + Minimum budget required to save all target nodes. + best_strategy : list + List of tuples representing the vaccination strategy. + + Examples: + -------- + Example 1: + >>> G1 = nx.DiGraph() + >>> G1.add_nodes_from([0,1,2,3], status="vulnerable") + >>> G1.add_edges_from([(0,1),(0,2),(1,2),(1,3),(2,3)]) + >>> spreading_minbudget(G1,0,[1,2,3]) + (2, [(1, 1), (2, 1)]) + + Example 2: + >>> G1 = nx.DiGraph() + >>> G1.add_nodes_from([0,1,2,3], status="vulnerable") + >>> G1.add_edges_from([(0,1),(0,2),(1,2),(1,3),(2,3)]) + >>> spreading_minbudget(G1,0,[1,3]) + (1, [(1, 1)]) + + Example 3: + >>> G2 = nx.DiGraph() + >>> G2.add_nodes_from([0,1,2,3,4,5,6], status="vulnerable") + >>> G2.add_edges_from([(0,1),(0,2),(1,2),(1,4),(2,3),(2,6),(3,5)]) + >>> spreading_minbudget(G2,0,[1,2,3,4,5,6]) + (2, [(2, 1), (1, 1)]) + + Example 4: + >>> G3 = nx.DiGraph() + >>> G3.add_nodes_from([0,1,2,3,4,5,6,7,8], status="vulnerable") + >>> G3.add_edges_from([(0,2),(0,4),(0,5),(2,1),(2,3),(4,1),(4,6),(5,3),(5,6),(5,7),(6,7),(6,8),(7,8)]) + >>> spreading_minbudget(G3,0,[1,2,3,4,5,6,7,8]) + (3, [(5, 1), (2, 1), (4, 1)]) + """ + + validate_parameters(Graph, source, targets) + logger.info(f"Starting the spreading_minbudget function with source node {source} and targets: {targets}") + + min_value = 1 + max_value = len(targets) + min_budget = max_value + middle = math.floor((min_value + max_value) / 2) + + best_strategy = spreading_maxsave(Graph, min_budget, source, targets, True)[0] + + while min_value < max_value: + logger.info(f"Calling maxsave with parameters - Source: {source}, Targets: {targets}, Budget: {middle}") + strategy, nodes_saved = spreading_maxsave(Graph, middle, source, targets, True) + + common_elements = set(nodes_saved) & set(targets) + + if len(common_elements) == len(targets): + logger.info(f"The current budget {middle} has saved all the targets!") + max_value = middle + if middle < min_budget: + min_budget = middle + best_strategy = strategy + else: + logger.info(f"The current budget {middle} didn't save all the targets!") + min_value = middle + 1 + + middle = math.floor((min_value + max_value) / 2) + + logger.info(f"Returning minimum budget: {middle} and the vaccination strategy: {best_strategy}") + return min_budget, best_strategy + + +def non_spreading_minbudget(Graph:nx.DiGraph, source:int, targets:list) -> int: + """ + Calculate the minimum budget required to save all target nodes in a non-spreading scenario. + + Parameters: + ---------- + Graph : nx.DiGraph + Directed graph representing the network. + source : int + Source node where the infection starts. + targets : list + List of target nodes to be saved. + + Returns: + ------- + min_budget : int + Minimum budget required to save all target nodes. + + Examples: + -------- + Example 1: + >>> G1 = nx.DiGraph() + >>> G1.add_nodes_from([0,1,2,3], status="vulnerable") + >>> G1.add_edges_from([(0,1),(0,2),(1,2),(1,3),(2,3)]) + >>> non_spreading_minbudget(G1,0,[1,3]) + (2, [(1, 1), (3, 1)]) + + Example 2: + >>> G1 = nx.DiGraph() + >>> G1.add_nodes_from([0,1,2,3], status="vulnerable") + >>> G1.add_edges_from([(0,1),(0,2),(1,2),(1,3),(2,3)]) + >>> non_spreading_minbudget(G1,0,[1,2,3]) + (2, [(1, 1), (2, 1)]) + + Example 3: + >>> G2 = nx.DiGraph() + >>> G2.add_nodes_from([0,1,2,3,4,5,6], status="vulnerable") + >>> G2.add_edges_from([(0,1),(0,2),(1,2),(1,4),(2,3),(2,6),(3,5)]) + >>> non_spreading_minbudget(G2,0,[1,2,3,4,5,6]) + (2, [(1, 1), (2, 1)]) + + Example 4: + >>> G3 = nx.DiGraph() + >>> G3.add_nodes_from([0,1,2,3,4,5,6,7,8], status="vulnerable") + >>> G3.add_edges_from([(0,2),(0,4),(0,5),(2,1),(2,3),(4,1),(4,6),(5,3),(5,6),(5,7),(6,7),(6,8),(7,8)]) + >>> non_spreading_minbudget(G3,0,[2,6,1,8]) + (3, [(2, 1), (4, 1), (5, 1)]) + """ + validate_parameters(Graph, source, targets) + logger.info(f"Starting the non_spreading_minbudget function with source node {source} and targets: {targets}") + + G = create_st_graph(Graph, targets, 't') + min_cut = algo.minimum_st_node_cut(G, source, 't') + logger.info(f"Minimum s-t node cut: {min_cut}") + min_budget = len(min_cut) + strategy = [(item, 1) for item in min_cut] + + logger.info(f"Returning minimum budget: {min_budget}") + return min_budget, strategy + +def non_spreading_dirlaynet_minbudget(Graph:nx.DiGraph, source:int, targets:list) -> tuple[int, list]: + """ + Calculate the minimum budget required to save all target nodes in a non-spreading directed layer network. + + Parameters: + ---------- + Graph : nx.DiGraph + Directed graph representing the network. + source : int + Source node where the infection starts. + targets : list + List of target nodes to be saved. + + Returns: + ------- + tuple: + min_budget : int + Minimum budget required to save all target nodes. + best_strategy : list + List of tuples representing the vaccination strategy. + + Examples: + -------- + Example 1: + >>> G4 = nx.DiGraph() + >>> G4.add_nodes_from([0,1,2,3,4,5], status="vulnerable") + >>> G4.add_edges_from([(0,1),(0,2),(1,3),(1,4),(1,5),(2,3),(2,4),(2,5),(3,5),(4,5)]) + >>> non_spreading_dirlaynet_minbudget(G4,0,[1,2,3,4,5]) + (2, [(1, 1), (2, 1)]) + """ + + validate_parameters(Graph, source, targets) + if not is_dag(Graph): + logger.error("The graph is not a DAG graph, thus cannot run the algorithm") + return + + #display_graph(Graph) + logger.info(f"Starting the non_spreading_dirlaynet_minbudget function with source node {source} and targets: {targets}") + + layers = adjust_nodes_capacity(Graph, source) + G = create_st_graph(Graph, targets, 't') + #display_graph(G) + G_reduction_min_cut = min_cut_with_node_capacity(G, source=source, target='t') + N_groups = min_cut_N_groups(G_reduction_min_cut,layers) + vacc_matrix = calculate_vaccine_matrix(layers, N_groups) + integer_matrix = matrix_to_integers_values(vacc_matrix) + min_budget = min_budget_calculation(vacc_matrix) + strategy = dirlay_vaccination_strategy(integer_matrix, N_groups) + + logger.info(f"Returning minimum budget: {min_budget} and the vaccination strategy: {strategy}") + return min_budget, strategy + +def heuristic_maxsave(Graph:nx.DiGraph, budget:int, source:int, targets:list, spreading=True, stop_condition=None) -> tuple[list, set]: + """ + Approximate the firefighter problem by maximizing the number of saved nodes in our heuristic apprach. + The heuristic approach is based on the local search problem. + + Parameters + ---------- + Graph : nx.DiGraph + Directed graph representing the network. + budget : int + Number of nodes that can be vaccinated at each time step. + source : int + Source node where the infection starts. + targets : list + List of target nodes to be saved. + spreading : bool + If True, vaccination spreads to neighboring nodes. + stop_condition : optional + If set, stops early if all targets are saved or if any target is infected. + + Returns + ------- + tuple: + vaccination_strategy : list + List of tuples representing the vaccination strategy. + saved_target_nodes : set + Set of saved target nodes. + + Examples + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([0, 1, 2, 3], status="vulnerable") + >>> G.add_edges_from([(0, 1), (0, 2), (1, 2), (1, 3)]) + >>> heuristic_maxsave(G, 1, 0, [1, 2, 3]) + ([(1, 1)], {1, 3}) + """ + + if budget < 1: + logger.critical("Error: The budget must be at least 1") + raise ValueError("Error: The budget must be at least 1") + + validate_parameters(Graph, source, targets) + logger.info(f"Starting the heuristic_maxsave function with source node {source}, budget {budget}, targets: {targets}, and spreading: {spreading}") + + clean_graph(Graph) + #display_graph(Graph) + local_targets = targets.copy() + infected_nodes = [] + vaccinated_nodes = [] + vaccination_strategy = [] + saved_target_nodes = set() + can_spread = True + Graph.nodes[source]['status'] = Status.INFECTED.value + infected_nodes.append(source) + #display_graph(Graph) + time_step = 1 + + while can_spread: + if spreading: + spread_vaccination(Graph, vaccinated_nodes) + for i in range(budget): + logger.info(f"Calculating the best direct vaccination strategy for the current time step that saves more new node in targets (Current budget: {budget})") + node_to_vaccinate, nodes_saved = find_best_neighbor(Graph, infected_nodes, local_targets, targets) + if node_to_vaccinate is not None: + logger.info(f"Found {node_to_vaccinate} as a solution for current timestamp, appending to vaccination strategy and vaccinating the node") + vaccination_strategy.append((node_to_vaccinate, time_step)) + vaccinate_node(Graph, node_to_vaccinate) + vaccinated_nodes.append(node_to_vaccinate) + logger.info(f"Updated list of currently vaccinated nodes: {vaccinated_nodes}") + + if nodes_saved is not None: + local_targets[:] = [element for element in local_targets if element not in nodes_saved] + logger.info(f"Updated list of targets: {local_targets}") + + else: + logger.info(f"All nodes are either vaccinated or infected") + break + + can_spread = spread_virus(Graph, infected_nodes) + + if stop_condition is not None: + if len(local_targets) == 0 or any(node in infected_nodes for node in local_targets): + for node in targets: + node_status = Graph.nodes[node]['status'] + if node_status != Status.INFECTED.value: + saved_target_nodes.add(node) + logger.info(f"Returning vaccination strategy: {vaccination_strategy}. The strategy saved the nodes: {saved_target_nodes}") + return vaccination_strategy, saved_target_nodes + + time_step += 1 + + for node in targets: + node_status = Graph.nodes[node]['status'] + if node_status != Status.INFECTED.value: + saved_target_nodes.add(node) + + logger.info(f"Returning vaccination strategy: {vaccination_strategy}. The strategy saves the nodes: {saved_target_nodes}") + return vaccination_strategy, saved_target_nodes + +def heuristic_minbudget(Graph:nx.DiGraph, source:int, targets:list, spreading:bool) -> tuple[int, list]: + """ + Calculate the minimum budget required to save all target nodes in our heuristic approach. + + Parameters + ---------- + Graph : nx.DiGraph + Directed graph representing the network. + source : int + Source node where the infection starts. + targets : list + List of target nodes to be saved. + spreading : bool + If True, vaccination spreads to neighboring nodes. + + Returns + ------- + tuple: + min_budget : int + Minimum budget required to save all target nodes. + best_strategy : list + List of tuples representing the vaccination strategy. + + Examples + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([0, 1, 2, 3], status="vulnerable") + >>> G.add_edges_from([(0, 1), (0, 2), (1, 2), (1, 3)]) + >>> heuristic_minbudget(G, 0, [1, 2, 3], True) + (2, [(1, 1), (2, 1)]) + """ + + validate_parameters(Graph, source, targets) + logger.info(f"Starting the heuristic_minbudget function with source node {source}, targets: {targets}, and spreading: {spreading}") + + min_value = 1 + max_value = len(list(Graph.successors(source))) + min_budget = max_value + middle = math.floor((min_value + max_value) / 2) + + best_strategy = heuristic_maxsave(Graph, min_budget, source, targets, spreading, True)[0] + + while min_value < max_value: + logger.info(f"Calling heuristic_maxsave with parameters - Source: {source}, Targets: {targets}, Budget: {middle}") + strategy, nodes_saved = heuristic_maxsave(Graph, middle, source, targets, spreading, True) + + common_elements = set(nodes_saved) & set(targets) + + if len(common_elements) == len(targets): + logger.info(f"The current budget {middle} has saved all the targets!") + max_value = middle + if middle < min_budget: + min_budget = middle + best_strategy = strategy + else: + logger.info(f"The current budget {middle} didn't save all the targets!") + min_value = middle + 1 + + middle = math.floor((min_value + max_value) / 2) + + logger.info(f"Returning minimum budget: {middle} and the vaccination strategy: {best_strategy}") + + return min_budget, best_strategy + +if __name__ == "__main__": + + import doctest + result = doctest.testmod(verbose=False) + print(f"Doctest results: {result}") \ No newline at end of file diff --git a/networkz/algorithms/approximation/firefighter_problem/Random_Graph_Generator.py b/networkz/algorithms/approximation/firefighter_problem/Random_Graph_Generator.py new file mode 100644 index 0000000..309614f --- /dev/null +++ b/networkz/algorithms/approximation/firefighter_problem/Random_Graph_Generator.py @@ -0,0 +1,105 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import logging +import random +import networkx as nx + +logger = logging.getLogger(__name__) + +def generate_random_DiGraph( + num_nodes: int = 100, + edge_probability: float = 0.1, + seed: int = None + ) -> nx.DiGraph: + + if seed is None: + seed = random.randint(0, 2**32 - 1) + logger.debug(f"Random generated seed: {seed}") + else: + logger.debug(f"Using provided seed: {seed}") + + random.seed(seed) + + G = nx.DiGraph() + G.add_nodes_from(range(num_nodes), status="target") + + edges = [ + (source, target) + for source in range(num_nodes) + for target in range(num_nodes) + if source != target and random.random() < edge_probability + ] + + G.add_edges_from(edges) + + return G + + +#TODO : make this to receive paramaters +def generate_random_layered_network(): + """ + Generates a directed layered network with a random number of layers and random nodes per layer. + + Returns: + G (networkx.DiGraph): Directed graph representing the layered network. + """ + # Randomly decide the number of layers (between 2 and 3 for this example) + num_layers = random.randint(5, 10) + + # Randomly decide the number of nodes per layer (between 1 and 4 for this example) + nodes_per_layer = [random.randint(5, 30) for _ in range(num_layers)] + + G = nx.DiGraph() + node_id = 1 # Start node_id from 1 because 0 is the source + + # Initialize layer 0 with the source node + layers = [[0]] + G.add_node(0) + + # Create nodes layer by layer + for i in range(num_layers): + layer = [node_id + j for j in range(nodes_per_layer[i])] + layers.append(layer) + G.add_nodes_from(layer) + node_id += nodes_per_layer[i] + + print("LAYERS->", layers) + + # Connect source node (0) to all nodes in layer 1 + for node in layers[1]: + G.add_edge(0, node) + + # Create edges ensuring connectivity between consecutive layers + for i in range(1, num_layers): + for node in layers[i]: + # Connect each node in this layer to at least one node in the next layer + connected_nodes = random.sample(layers[i + 1], k=random.randint(1, len(layers[i + 1]))) + for target in connected_nodes: + if target != node: # Ensure no self-loop + G.add_edge(node, target) + + for target in layers[i + 1]: + # Ensure each node in the next layer is connected to from at least one node in this layer + if not any(G.has_edge(source, target) for source in layers[i]): + G.add_edge(random.choice(layers[i]), target) + + return G diff --git a/networkz/algorithms/approximation/firefighter_problem/Utils.py b/networkz/algorithms/approximation/firefighter_problem/Utils.py new file mode 100644 index 0000000..c62ce68 --- /dev/null +++ b/networkz/algorithms/approximation/firefighter_problem/Utils.py @@ -0,0 +1,893 @@ +""" +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi +""" + +import networkx as nx +import networkx.algorithms.connectivity as algo +import matplotlib.pyplot as plt +import numpy as np +from enum import Enum +import copy +import logging +import heapq + +class Status(Enum): + VULNERABLE = "vulnerable" + INFECTED = "infected" + VACCINATED = "vaccinated" + DIRECTLY_VACCINATED = "directly vaccinated" + + +node_colors = { + 'vulnerable': 'gray', + 'infected': 'red', + 'vaccinated': 'blue', + 'directly vaccinated': 'green', + 'default' : "#00FFD0" +} +logger = logging.getLogger(__name__) + +# ============================ Validation Functions ============================ + +def validate_parameters(graph:nx.DiGraph, source:int, targets:list) -> None: + """ + Validate the source and target nodes in the graph. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph. + source : int + Source node. + targets : list + List of target nodes to save. + + Raises: + ------- + ValueError + If the source node is not in the graph. + If the source node is in the targets list. + If any target node is not in the graph. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([1, 2, 3, 4]) + >>> validate_parameters(G, 1, [2, 3]) + >>> validate_parameters(G, 5, [2, 3]) + Traceback (most recent call last): + ... + ValueError: Error: The source node isn't on the graph + >>> validate_parameters(G, 1, [1, 3]) + Traceback (most recent call last): + ... + ValueError: Error: The source node can't be a part of the targets list, since the virus is spreading from the source + >>> validate_parameters(G, 1, [2, 5]) + Traceback (most recent call last): + ... + ValueError: Error: Not all nodes in the targets list are on the graph. + """ + graph_nodes = list(graph.nodes()) + if source not in graph_nodes: + logger.critical("Error: The source node isn't on the graph") + raise ValueError("Error: The source node isn't on the graph") + + if source in targets: + logger.critical("Error: The source node can't be a part of the targets list, since the virus is spreading from the source") + raise ValueError("Error: The source node can't be a part of the targets list, since the virus is spreading from the source") + + if not all(node in graph_nodes for node in targets): + logger.critical("Error: Not all nodes in the targets list are on the graph.") + raise ValueError("Error: Not all nodes in the targets list are on the graph.") + +def is_st_layered_dag(graph: nx.DiGraph, s: any, t: any) -> bool: #TODO: make this work and incorporate into code + """ + Validates if a given graph is an s-t directed layered network. + + In an s-t directed l-layered network, the vertex set consists of + V = (L0 := {s}) U L1 U ... U Ll U {t}, and all arcs except those + entering t are from a vertex in some layer Li to a vertex in Li+1; + arcs entering t may originate from any vertex other than t. + + Parameters + ---------- + graph : nx.DiGraph + Directed graph. + s : any + Source vertex. + t : any + Target vertex. + + Returns + ------- + bool + True if the graph is an s-t directed l-layered network, False otherwise. + + Examples + -------- + Example 1: + >>> G = nx.DiGraph() + >>> G.add_edges_from([(0, 1), (1, 2), (2, 3)]) + >>> is_st_layered_dag(G, 0, 3) + True + + Example 2: + >>> G = nx.DiGraph() + >>> G.add_edges_from([(0, 1), (1, 2), (2, 1), (2, 3)]) + >>> is_st_layered_dag(G, 0, 3) + False + """ + logger.info(f'Validating {graph} is an s-t directed layered network') + if not nx.is_directed_acyclic_graph(graph): + logger.error(f'{graph} is not DAG and therefore cannot be an s-t directed layered network!') + return False + + topo_sort = list(nx.topological_sort(graph)) + logger.debug(f'Performing topological sort to determine an ordering of vertices\n Sorted:{topo_sort}') + + if topo_sort[0] != s or topo_sort[-1] != t: + logger.error(f'First node in topological sort is not "t" or last node is not "s"') + return False + + # Assign layer indices based on topological sort + node_layers = {node: index for index, node in enumerate(topo_sort)} + + # Check if all edges (except those entering t) go from a lower layer to the next higher layer + for u, v in graph.edges(): + if v != t and node_layers[u] + 1 != node_layers[v]: + logger.error(f'The edge {u},{v} is an edge that does not enter "t" but goes from a higher to a lower layer - violating the required property') + return False + + return True + +def is_dag(graph:nx.DiGraph) -> bool: + """ + Validates if a given graph is a Directed Acyclic Graph (DAG) using NetworkX. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph. + + Returns: + ------- + bool + True if the graph is a DAG, False otherwise. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_edges_from([(1, 2), (2, 3)]) + >>> is_dag(G) + True + >>> G.add_edge(3, 1) + >>> is_dag(G) + False + """ + return nx.is_directed_acyclic_graph(graph) + +# ============================ End Validation Functions ============================ + +# ============================ Spreading Max-Save ============================ +def calculate_gamma(graph:nx.DiGraph, source:int, targets:list) -> dict: + """ + Calculate Gamma and S(u,t) based on the calculation in the article. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph. + source : int + Source node. + targets : list + List of target nodes to save. + + Returns: + ------- + gamma : dict + Dictionary of vaccination options. + direct_vaccination : dict + Dictionary of direct vaccination strategies - S(u,t). + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_edges_from([(1, 2), (2, 3), (1, 3)]) + >>> G.nodes[1]['capacity'] = 10 + >>> G.nodes[2]['capacity'] = 15 + >>> G.nodes[3]['capacity'] = 20 + >>> gamma, direct_vaccination = calculate_gamma(G, 1, [3]) + >>> gamma + {2: [(2, 1)], 3: [(3, 1)]} + >>> direct_vaccination + {(2, 1): [], (3, 1): [3]} + """ + + gamma = {} + direct_vaccination = {} + unreachable_nodes = [] + path_length = dict(nx.all_pairs_shortest_path_length(graph)) + for key in graph.nodes: + vaccination_options = [] + for node in graph.nodes: + if path_length[source].get(key) is not None and path_length[node].get(key) is not None: + s_to_v = path_length[source].get(key) + u_to_v = path_length[node].get(key) + max_time = s_to_v - u_to_v + if max_time > 0: + for i in range(1,max_time+1): + option = (node,i) + vaccination_options.append(option) + if option not in direct_vaccination: + direct_vaccination[option] = [] + if key in targets: + direct_vaccination[option].append(key) + + if not vaccination_options: + unreachable_nodes.append(key) + if key != source: + gamma[key] = vaccination_options + + for strategy in direct_vaccination: + for node in unreachable_nodes: + if node in targets: + direct_vaccination[strategy].append(node) + + logger.info("Gamma is: " + str(gamma)) + logger.info("S(u,t) is: " + str(direct_vaccination)) + return gamma, direct_vaccination + +def calculate_epsilon(direct_vaccinations:dict) -> list: + """ + Calculate Epsilon based on the calculation in the article. + + Parameters: + ---------- + direct_vaccinations : dict + Dictionary of direct vaccination strategies. + + Returns: + ------- + epsilon : list + List of direct vaccination groups by time step. + + Examples: + -------- + >>> direct_vaccinations = {(1, 1): [3], (2, 2): [4], (3, 1): [5]} + >>> calculate_epsilon(direct_vaccinations) + [[(1, 1), (3, 1)], [(2, 2)]] + """ + from itertools import groupby + from operator import itemgetter + + sorted_dict = sorted(direct_vaccinations, key=itemgetter(1)) + epsilon = [list(group) for _, group in groupby(sorted_dict, key=itemgetter(1))] + + logger.info("Epsilon is: " + str(epsilon)) + return epsilon + +def find_best_direct_vaccination(graph:nx.DiGraph, direct_vaccinations:dict, current_time_options:list, targets:list) -> tuple: + """ + Find the best direct vaccination strategy for the current time step that saves more new nodes in targets. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph representing the network. + direct_vaccinations : dict + Dictionary of direct vaccination strategies. + current_time_options : list + List of current time step vaccination options. + targets : list + List of target nodes. + + Returns: + ------- + tuple + best_vaccination : tuple + Best direct vaccination option for the current time stamp. + nodes_saved : list + List of the nodes who's been saved by this option. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([(1, {"status": 'vulnerable'}), (2, {"status": 'vulnerable'}), (3, {"status": 'vulnerable'})]) + >>> direct_vaccinations = {(1, 1): [1], (2, 2): [2]} + >>> current_time_options = [(1, 1), (2, 2)] + >>> targets = [2] + >>> find_best_direct_vaccination(G, direct_vaccinations, current_time_options, targets) + ((2, 2), {2}) + """ + best_vaccination = () + nodes_saved = [] + common_elements = None + max_number = -1 + for option in current_time_options: + if(graph.nodes[option[0]]['status'] == Status.VULNERABLE.value): + nodes_list = direct_vaccinations.get(option) + common_elements = set(nodes_list) & set(targets) + logger.debug(f"Direct vaccination: {option}, Nodes saved: {common_elements} (if set(), then it's empty)") + if len(common_elements) > max_number: + best_vaccination = option + nodes_saved = common_elements + max_number = len(common_elements) + + if best_vaccination != (): + logger.info("The best direct vaccination is: " + str(best_vaccination) + " and it saves nodes: " + str(nodes_saved)) + return best_vaccination, nodes_saved + +def spread_virus(graph:nx.DiGraph, infected_nodes:list) -> bool: + """ + Spread the virus from infected nodes to their neighbors. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph representing the network. + infected_nodes : list + List of currently infected nodes. + + Returns: + ------- + bool + True if there are new infections, False otherwise. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([(1, {"status": 'infected'}), (2, {"status": 'vulnerable'}), (3, {"status": 'vulnerable'})]) + >>> G.add_edges_from([(1, 2), (2, 3)]) + >>> infected_nodes = [1] + >>> spread_virus(G, infected_nodes) + True + >>> G.nodes(data=True) + NodeDataView({1: {'status': 'infected'}, 2: {'status': 'infected'}, 3: {'status': 'vulnerable'}}) + """ + new_infected_nodes = [] + for node in infected_nodes: + for neighbor in graph.neighbors(node): + if graph.nodes[neighbor]['status'] == Status.VULNERABLE.value: + graph.nodes[neighbor]['status'] = Status.INFECTED.value + new_infected_nodes.append(neighbor) + logger.debug("SPREAD VIRUS: Node " + f'{neighbor}' + " has been infected from node " + f'{node}') + + infected_nodes.clear() + #display_graph(graph) + for node in new_infected_nodes: + infected_nodes.append(node) + return bool(infected_nodes) + + +def spread_vaccination(graph:nx.DiGraph, vaccinated_nodes:list) -> None: + """ + Spread the vaccination from vaccinated nodes to their neighbors. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph representing the network. + vaccinated_nodes : list + List of currently vaccinated nodes. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([(1, {"status": 'directly_vaccinated'}), (2, {"status": 'vulnerable'}), (3, {"status": 'vulnerable'})]) + >>> G.add_edges_from([(1, 2), (2, 3)]) + >>> vaccinated_nodes = [1] + >>> spread_vaccination(G, vaccinated_nodes) + >>> G.nodes(data=True) + NodeDataView({1: {'status': 'directly_vaccinated'}, 2: {'status': 'vaccinated'}, 3: {'status': 'vulnerable'}}) + """ + new_vaccinated_nodes = [] + for node in vaccinated_nodes: + for neighbor in graph.neighbors(node): + if graph.nodes[neighbor]['status'] == Status.VULNERABLE.value: + graph.nodes[neighbor]['status'] = Status.VACCINATED.value + new_vaccinated_nodes.append(neighbor) + logger.debug("SPREAD VACCINATION: Node " + f'{neighbor}' + " has been vaccinated from node " + f'{node}') + + vaccinated_nodes.clear() + #display_graph(graph) + for node in new_vaccinated_nodes: + vaccinated_nodes.append(node) + return + +def vaccinate_node(graph:nx.DiGraph, node:int) -> None: + """ + Directly vaccinate a specific node in the graph. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph representing the network. + node : int + Node to be vaccinated. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_node(1, status=0) + >>> vaccinate_node(G, 1) + >>> G.nodes(data=True) + NodeDataView({1: {'status': 'directly vaccinated'}}) + """ + graph.nodes[node]['status'] = Status.DIRECTLY_VACCINATED.value + logger.info("Node " + f'{node}' + " has been directly vaccinated") + #display_graph(graph) + return + +def clean_graph(graph:nx.DiGraph) -> None: + """ + Reset the graph to its base state where all nodes are targets. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph representing the network. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_nodes_from([(1, {"status": 1}), (2, {"status": 2}), (3, {"status": 0})]) + >>> clean_graph(G) + >>> G.nodes(data=True) + NodeDataView({1: {'status': 'vulnerable'}, 2: {'status': 'vulnerable'}, 3: {'status': 'vulnerable'}}) + """ + + for node in graph.nodes: + graph.nodes[node]['status'] = Status.VULNERABLE.value + return + +# ============================ End Spreading Max-Save ============================ + +# =========================== Non-Spreading Min-Budget-Dirlay ============================ +def adjust_nodes_capacity(graph:nx.DiGraph, source:int) -> list: + """ + Adjust the capacity of nodes based on the layer they belong to. + The capacity is based on the formula in the article at the DirLayNet algorithm section. + + Parameters: + ---------- + graph : nx.DiGraph + Directed graph representing the network. + source : int + Source node. + + Returns: + ------- + layers: list + List of nodes grouped by layers. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_edges_from([(1, 2), (2, 3), (3, 4)]) + >>> layers = adjust_nodes_capacity(G, 1) + >>> layers + [[1], [2], [3], [4]] + >>> G.nodes(data=True) + NodeDataView({1: {}, 2: {'capacity': 0.5454545454545455}, 3: {'capacity': 0.27272727272727276}, 4: {'capacity': 0.18181818181818182}}) + """ + logger.debug(f"Starting to adjust node capacity for dirlay graph nodes...") + + layers = (list(nx.bfs_layers(graph,source))) + harmonic_sum = 0.0 + for i in range(1,len(layers)): + harmonic_sum = harmonic_sum + 1/i + for index in range(1,len(layers)): + for node in layers[index]: + graph.nodes[node]['capacity'] = 1/(index*harmonic_sum) + logger.info(f"Added Capacity {1/(index*harmonic_sum)} for node: {node}") + + logger.info(f"Done with adding capacity for nodes, with Layers: {layers}") + + return layers + +def create_st_graph(graph:nx.DiGraph, targets:list, new_target:str) -> nx.DiGraph: + """ + Create an s-t graph from the original graph for use in connectivity algorithms. + + Parameters: + ---------- + graph : nx.DiGraph + Original directed graph. + targets : list + List of target nodes. + + Returns: + ------- + G : nx.DiGraph + s-t graph. + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_edges_from([(1, 2), (2, 3), (3, 4)]) + >>> targets = [2, 3] + >>> G_st = create_st_graph(G, targets, 't') + >>> 't' in G_st.nodes + True + >>> list(G_st.successors(2)) + [3, 't'] + >>> list(G_st.successors(3)) + [4, 't'] + """ + logger.info(f"Creating a s-t graph to connect nodes to save") + + G = copy.deepcopy(graph) + G.add_node(new_target, status = Status.VULNERABLE.value) + for node in targets: + G.add_edge(node, new_target) + #display_graph(G) + + logger.info(f"Done creating a s-t graph") + return G + +def min_cut_N_groups(min_cut_nodes: set, layers: list) -> dict: + """ + Using the minimum cut group nodes accordingly. + + Parameters: + ---------- + graph : nx.DiGraph + Graph after flow reduction. + source : int + Source node. + layers : list + List of lists, where each sublist contains nodes belonging to that layer. + + Returns: + ------- + groups : dict + Dictionary with layers as keys and lists of nodes in the minimum cut as values. + + Examples: + -------- + + """ + + logger.info(f"Finding the correct nodes from each layer according to the min-cut nodes") + + # Initialize the groups dictionary with empty lists for each layer index + groups = {i+1: [] for i in range(len(layers)-1)} + + # Populate the groups dictionary + for item in min_cut_nodes: + node , suffix = item.split('_') + node = int(node) + for i, layer_nodes in enumerate(layers): + if node in layer_nodes: + groups[i].append(node) + break + + logger.info(f"Ni groups: {groups}") + return groups + + +def calculate_vaccine_matrix(layers:list, min_cut_nodes_grouped:dict) -> np.matrix: + """ + Calculate the vaccine matrix based on the calculation in the article at the DirLayNet algorithm section. + + Parameters: + ---------- + layers : list + List of nodes grouped by layers. + min_cut_nodes_grouped : dict + List of nodes in the minimum cut grouped into layers. + + Returns: + ------- + matrix : np.matrix + Vaccine matrix. + + Examples: + -------- + + """ + logger.info(f"Calculating the Vaccine Matrix...") + + matrix_length = max(min_cut_nodes_grouped.keys()) + matrix = np.zeros((matrix_length, matrix_length)) + for j in range(matrix_length): + for i in range(j+1): + N_j = len(min_cut_nodes_grouped[j+1]) + value = N_j / (j + 1) + matrix[i][j] = value + + logger.info(f"Vaccination Matrix Before roundups:\n{matrix}") + return matrix + +def matrix_to_integers_values(matrix: np.matrix) -> np.matrix: + """ + Convert a matrix with fractional entries to an integral matrix such that + the row and column sums are either the floor or ceiling of the original sums. + The solution is provided with a construction of a flow graph and then applying a max-flow algorithm on it. + + Parameters: + ---------- + matrix : np.matrix + The input matrix with fractional entries. + + Returns: + ------- + np.matrix + The converted integral matrix. + + Examples: + -------- + + """ + # dimensions of the matrix + logger.info(f"Applying max-flow to transfer the Vaccine Matrix for integers...") + rows, cols = matrix.shape + + row_sums = np.array(matrix.sum(axis=1)).flatten() + col_sums = np.array(matrix.sum(axis=0)).flatten() + + # logger.info(f"Row sums: {row_sums}") + # logger.info(f"Column sums: {col_sums}") + + G = nx.DiGraph() + + # add source and sink nodes + source = 's' + sink = 't' + G.add_node(source) + G.add_node(sink) + + # add nodes for rows and columns + row_nodes = ['r{}'.format(i) for i in range(rows)] + col_nodes = ['c{}'.format(j) for j in range(cols)] + G.add_nodes_from(row_nodes) + G.add_nodes_from(col_nodes) + + # add edges from source to row nodes with capacities as the ceiling of row sums + for i in range(rows): + G.add_edge(source, row_nodes[i], capacity=np.ceil(row_sums[i])) + + # add edges from column nodes to sink with capacities as the ceiling of column sums + for j in range(cols): + G.add_edge(col_nodes[j], sink, capacity=np.ceil(col_sums[j])) + + # add edges from row nodes to column nodes with capacity 1 + for i in range(rows): + for j in range(cols): + G.add_edge(row_nodes[i], col_nodes[j], capacity=1) + + # computes the maximum flow + flow_value, flow_dict = nx.maximum_flow(G, source, sink) + + # builds the integral matrix + integral_matrix = np.zeros_like(matrix, dtype=int) + for i in range(rows): + for j in range(cols): + if flow_dict[row_nodes[i]][col_nodes[j]] > 0: + integral_matrix[i, j] = np.ceil(matrix[i, j]) + else: + integral_matrix[i, j] = np.floor(matrix[i, j]) + + logger.info(f"Integral and final Matrix:\n{integral_matrix}") + + return np.matrix(integral_matrix) + + +def min_budget_calculation(matrix: np.matrix) -> int: + """ + Calculate the minimum budget from the matrix. + + Parameters: + ---------- + matrix : np.matrix + Input matrix. + + Returns: + ------- + min_budget : int + Minimum budget. + + Examples: + -------- + >>> matrix = np.matrix([[0.5, 1.5], [1.2, 0.8]]) + >>> min_budget_calculation(matrix) + 3 + """ + integral_matrix = matrix_to_integers_values(matrix) + rows_sum = integral_matrix.sum(axis=1) # we get column sum as we want to -> on time step i, vaccinate Mij nodes from layer j , for all i ≤ j ≤ . + min_budget = int(rows_sum.max()) + logger.info(f"Min budget needed to save the target nodes: {min_budget}") + return min_budget + +def dirlay_vaccination_strategy(vacc_matrix: np.matrix, ni_groups: dict) -> list: + """ + Determines a feasible vaccination strategy given the vaccine matrix and the nodes from each layer. + + Parameters: + ---------- + vacc_matrix: np.matrix + A matrix where rows represent time steps and columns represent layers, + with each element indicating the number of nodes to vaccinate. + ni_groups: dict + A dict of layers, where each layer contains nodes to be saved. + + Returns: + ---------- + strategy : list + A list of tuples where each tuple represents a node to vaccinate and the corresponding time step index. + """ + logger.info("Calculating the strategy") + + num_steps, num_layers = vacc_matrix.shape + strategy = [] + for i in range(num_steps): + for j in range(num_layers): + num_nodes_to_vaccinate = int(vacc_matrix[i, j]) + + logger.debug(f"On time step {i+1} needs to vaccinate: {num_nodes_to_vaccinate} nodes") + + if num_nodes_to_vaccinate > 0: + # Extract the nodes to vaccinate + selected_nodes = ni_groups[j+1][:num_nodes_to_vaccinate] + + logger.debug(f"The selected nodes to vaccinate {selected_nodes}") + + # Create tuples (node, i) and add them directly to strategy + strategy.extend((node, i+1) for node in selected_nodes) + + # sort the strategy by time stamp. + strategy.sort(key=lambda x: (x[1], x[0])) + return strategy + +# =========================== End Non-Spreading Max-Save ============================ + +# =========================== Heuristic Utilities =================================== +def find_best_neighbor(graph: nx.DiGraph, infected_nodes: list, remaining_targets: list, overall_targets: list) -> tuple[int, set]: + """ + Find the best node from the infected nodes' successors that saves the most new nodes in targets. + + Parameters + ---------- + graph : nx.DiGraph + Directed graph. + infected_nodes : list + List of all infected nodes that threaten to infect additional nodes. + remaining_targets : list + List of remaining target nodes to be saved. + overall_targets : list + List of all target nodes. + + Returns + ------- + best_node : int + Best node option to vaccinate. + nodes_saved : set + Set of nodes that would be saved by vaccinating the best node. + + Examples + -------- + Example 1: + >>> G = nx.DiGraph() + >>> G.add_nodes_from([0, 1, 2, 3, 4], status='vulnerable') + >>> G.add_edges_from([(0, 1), (0, 2), (1, 3), (1, 4)]) + >>> find_best_neighbor(G, [0], [1, 2, 3, 4], [1, 2, 3, 4]) + (1, {1, 3, 4}) + """ + optional_nodes = set() + priority_queue = [] + + # Go through the infected_nodes list and collect all their neighbors + for node in infected_nodes: + optional_nodes.update(graph.neighbors(node)) + + for node in optional_nodes: + is_target = False + if graph.nodes[node]['status'] == Status.VULNERABLE.value: + # For each node that is target, we will add only its neighbors that are target as well + neighbors_list = list(graph.neighbors(node)) + vulnerable_neighbors = set() + for neighbor in neighbors_list: + if graph.nodes[neighbor]['status'] == Status.VULNERABLE.value: + vulnerable_neighbors.add(neighbor) + if node in overall_targets: + is_target = True + vulnerable_neighbors.add(node) + common_elements = set(vulnerable_neighbors) & set(remaining_targets) + logger.info("node " + f'{node}' + " is saving the nodes " + str(common_elements)) + + # Define the priority tuple + node_info = (not is_target, -len(common_elements), -len(vulnerable_neighbors), node, common_elements) + heapq.heappush(priority_queue, node_info) + + if priority_queue: + best_node_info = heapq.heappop(priority_queue) + best_node = best_node_info[3] + nodes_saved = best_node_info[4] + logger.info("The best node is: " + f'{best_node}' + " and it's saving nodes: " + str(nodes_saved)) + return best_node, nodes_saved + + return None, [] + +# =========================== End Heuristic Utilities ================================ + +# =========================== General Utilities ====================================== +def display_graph(graph:nx.DiGraph) -> None: + """ + Display the graph using Matplotlib. + + Parameters + ---------- + graph : nx.DiGraph + Directed graph. + """ + pos = nx.shell_layout(graph) + colors = [node_colors.get(data.get('status', 'default'), 'default') for node, data in graph.nodes(data=True)] + nx.draw(graph, pos, node_color=colors, with_labels=True, font_weight='bold') + + if nx.get_edge_attributes(graph, 'weight'): + edge_labels = nx.get_edge_attributes(graph, 'weight') + nx.draw_networkx_edge_labels(graph, pos, edge_labels=edge_labels) + plt.show() + return + +def parse_json_to_networkx(json_data): + """ + Parse JSON data to create Networkx graphs. + + Parameters + ---------- + json_data : dict + JSON data containing graph information. + + Returns + ------- + graphs : dict + Dictionary of Networkx graphs. + + Raises + ------ + KeyError + If 'vertices' or 'edges' is not found or is not a non-empty list. + """ + graphs = {} + for graph_type, graph_data in json_data.items(): + for graph_name, graph_info in graph_data.items(): + graph_key = f"{graph_type}_{graph_name}" + + if "vertices" not in graph_info or not isinstance(graph_info["vertices"], list) or not graph_info["vertices"]: + logger.critical(f"Error parsing {graph_type}_{graph_name}: 'vertices' must be a non-empty list.") + raise KeyError(f"Error parsing {graph_type}_{graph_name}: 'vertices' must be a non-empty list.") + + if "edges" not in graph_info or not isinstance(graph_info["edges"], list) or not graph_info["edges"]: + logger.critical(f"Error parsing {graph_type}_{graph_name}: 'edges' must be a non-empty list.") + raise KeyError(f"Error parsing {graph_type}_{graph_name}: 'edges' must be a non-empty list.") + + vertices = graph_info["vertices"] + edges = [(edge[0], edge[1]) for edge in graph_info["edges"]] + G = nx.DiGraph() + G.add_nodes_from(vertices, status=Status.VULNERABLE.value) + G.add_edges_from(edges) + graphs[graph_key] = G + return graphs + +# =========================== End General Utilities ============================ + +if __name__ == "__main__": + import doctest + result = doctest.testmod(verbose=True) + logger.info(f"Doctest results: {result}") \ No newline at end of file diff --git a/networkz/algorithms/approximation/tests/test_coalition_formation.py b/networkz/algorithms/approximation/tests/test_coalition_formation.py index cf39fd1..01465aa 100644 --- a/networkz/algorithms/approximation/tests/test_coalition_formation.py +++ b/networkz/algorithms/approximation/tests/test_coalition_formation.py @@ -165,4 +165,4 @@ def test_disconnected_components_weighted_graph_with_k_5_returns_correct_partiti # Add random weights to the edges for u, v in G.edges(): G[u][v]["weight"] = random.randint(1, 205) - assert match_and_merge(G, k=5) == [[1, 2], [3, 4, 5, 6], [7, 8, 9]] + assert match_and_merge(G, k=5) == [[1, 2], [3, 4, 5, 6], [7, 8, 9]] \ No newline at end of file diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/__init__.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/graphs.json b/networkz/algorithms/approximation/tests/test_firefighter_problem/graphs.json new file mode 100644 index 0000000..bbeb176 --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/graphs.json @@ -0,0 +1,334 @@ +{ + "Dirlay": { + "Graph-1": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5 + ], + "edges": [ + [0, 1], + [0, 2], + [1, 3], + [3, 4], + [4, 5] + ] + }, + "Graph-2": { + "vertices": [ + 0, + 1, + 2, + 3, + 4 + ], + "edges": [ + [0, 1], + [0, 2], + [2, 3], + [1, 4] + ] + }, + "Graph-3": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "edges": [ + [0, 1], + [0, 2], + [0, 3], + [3, 4], + [1, 5], + [5, 6], + [4, 7] + ] + }, + "Graph-4": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 8 + ], + "edges": [ + [0, 1], + [0, 2], + [1, 3], + [1, 4], + [2, 3], + [3, 5], + [4, 5], + [5, 6], + [6, 8] + ] + }, + "Graph-5": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8 + ], + "edges": [ + [0, 2], + [0, 4], + [0, 5], + [2, 1], + [2, 3], + [4, 1], + [4, 6], + [5, 3], + [5, 6], + [5, 7], + [6, 7], + [6, 8], + [7, 8] + ] + } + }, + "RegularGraph": { + "Graph-1": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "edges": [ + [0, 1], + [0, 2], + [1, 3], + [1, 4], + [2, 3], + [2, 6], + [3, 5] + ] + }, + "Graph-2": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "edges": [ + [0, 5], + [0, 2], + [1, 7], + [2, 5], + [3, 7], + [4, 0], + [4, 7], + [6, 2], + [6, 3], + [6, 0], + [6, 1], + [7, 6], + [7, 4], + [7, 3], + [7, 0] + ] + }, + "Graph-3": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5 + ], + "edges": [ + [0, 1], + [0, 2], + [1, 3], + [1, 4], + [1, 5], + [2, 3], + [2, 4], + [2, 5], + [3, 5], + [4, 5] + ] + }, + "Graph-4": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "edges": [ + [0, 1], + [0, 6], + [1, 2], + [1, 5], + [1, 6], + [2, 3], + [3, 4], + [5, 2], + [5, 3], + [5, 4], + [6, 5], + [7, 6], + [7, 1] + ] + }, + "Graph-5": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ], + "edges": [ + [0, 1], + [0, 6], + [1, 2], + [1, 5], + [1, 6], + [2, 3], + [3, 4], + [5, 2], + [5, 3], + [5, 4], + [6, 5], + [7, 6], + [7, 1] + ] + }, + "Graph-6": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "edges": [ + [1, 2], + [2, 1], + [2, 3], + [2, 8], + [3, 7], + [3, 9], + [3, 0], + [4, 1], + [4, 7], + [6, 3], + [7, 0], + [7, 6], + [8, 1], + [9, 5], + [9, 2] + ] + }, + "Graph-7": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "edges": [ + [1, 5], + [1, 4], + [1, 3], + [2, 6], + [2, 3], + [3, 0], + [3, 4], + [5, 3], + [6, 4] + ] + }, + "Graph-8": { + "vertices": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14 + ], + "edges": [ + [0, 11], + [0, 3], + [0, 14], + [1, 13], + [1, 7], + [1, 6], + [1, 5], + [3, 14], + [5, 1], + [5, 0], + [6, 5], + [7, 4], + [7, 13], + [8, 5], + [9, 14], + [10, 12], + [11, 10], + [12, 10], + [12, 6], + [12, 2], + [13, 11], + [14, 13], + [14, 6], + [14, 11], + [14, 8] + ] + } + } +} diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_heuristic_maxsave.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_heuristic_maxsave.py new file mode 100644 index 0000000..6e79cb2 --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_heuristic_maxsave.py @@ -0,0 +1,177 @@ +""" +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi +""" + +import pytest +import networkx as nx +import json +import random +import logging +import os +import time + +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import heuristic_maxsave, spreading_maxsave +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx, Status + +def setup_logger(): + logger = logging.getLogger('firefighter_problem_tests') + logger.setLevel(logging.INFO) + + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + console_handler.setFormatter(formatter) + + logger.addHandler(console_handler) + return logger + +logger = setup_logger() + +path_to_graphs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'graphs.json') +if os.path.exists(path_to_graphs): + with open(path_to_graphs, "r") as file: + json_data = json.load(file) +else: + raise FileNotFoundError(f"{path_to_graphs} does not exist.") +graphs = parse_json_to_networkx(json_data) + + +@pytest.mark.parametrize("graph_key, budget, source, targets", [ + ("RegularGraph_Graph-1", 1, -2, [1, 2, 3, 4, 5, 6]), + ("RegularGraph_Graph-4", 1, 8, [1, 2, 4, 6, 7]), + ("RegularGraph_Graph-6", 1, 10, [0, 2, 3, 5, 6, 7, 8, 9]), + ("RegularGraph_Graph-8", 1, 17, [1, 7, 12, 14, 8, 3, 11, 2]), + ("RegularGraph_Graph-3", 1, 6, [1, 3, 5]), +]) +def test_source_not_in_graph(graph_key, budget, source, targets): + with pytest.raises(ValueError): + heuristic_maxsave(graphs[graph_key], budget, source, targets) + +@pytest.mark.parametrize("graph_key, budget, source, targets", [ + ("RegularGraph_Graph-2", 1, 0, [1, 2, 3, 9, 5, 16]), + ("RegularGraph_Graph-3", 1, 4, [1, 2, 3, 6, 7]), + ("RegularGraph_Graph-6", 1, 3, [0, 2, 5, 6, 7, 8, 10]), + ("RegularGraph_Graph-8", 1, 11, [1, 3, 12, 19, 8, 10, 4, 2]), + ("RegularGraph_Graph-7", 1, 2, [1, 3, -1, 5]), +]) +def test_target_not_in_graph(graph_key, budget, source, targets): + with pytest.raises(ValueError): + heuristic_maxsave(graphs[graph_key], budget, source, targets) + +@pytest.mark.parametrize("graph_key, budget, source, targets", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 0, 4, 5, 6]), + ("RegularGraph_Graph-3", 1, 1, [5, 1, 4]), + ("RegularGraph_Graph-4", 1, 4, [1, 2, 3, 4, 5, 6, 7]), + ("RegularGraph_Graph-6", 1, 0, [0, 3, 5, 6, 7, 8, 9]), + ("RegularGraph_Graph-8", 1, 0, [13, 10, 8, 6, 5, 4, 3, 0, 1, 2]), +]) +def test_source_is_target(graph_key, budget, source, targets): + with pytest.raises(ValueError): + heuristic_maxsave(graphs[graph_key], budget, source, targets) + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_length", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 4, 5, 6], 2), + ("Dirlay_Graph-5", 2, 0, [1, 2, 3, 4, 5, 6, 7, 8], 3), +]) +def test_strategy_length(graph_key, budget, source, targets, expected_length): + logger.info(f"Testing strategy length for {graph_key}") + graph = graphs[graph_key] + calculated_strategy = spreading_maxsave(graph, budget, source, targets)[0] + logger.info(f"Calculated strategy: {calculated_strategy}") + + assert len(calculated_strategy) == expected_length + logger.info(f"Strategy length test passed for {graph_key}") + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_strategy", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 4, 5, 6], [(1, 1), (6, 2)]), + ("Dirlay_Graph-5", 2, 0, [1, 2, 3, 4, 5, 6, 7, 8], [(5, 1), (2, 1)]), +]) +def test_save_all_vertices(graph_key, budget, source, targets, expected_strategy): + logger.info(f"Testing save all vertices for {graph_key}") + graph = graphs[graph_key] + calculated_strategy = heuristic_maxsave(graph, budget, source, targets)[0] + logger.info(f"Calculated strategy: {calculated_strategy}") + + assert calculated_strategy == expected_strategy + logger.info(f"Save all vertices test passed for {graph_key}") + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_save_amount", [ + ("RegularGraph_Graph-6", 2, 1, [3, 9, 0, 5, 6], 5), + ("RegularGraph_Graph-4", 1, 0, [2, 6, 4], 3), +]) +def test_save_subgroup_vertices(graph_key, budget, source, targets, expected_save_amount): + logger.info(f"Testing save subgroup vertices for {graph_key}") + graph = graphs[graph_key] + calculated_strategy = len(heuristic_maxsave(graph, budget, source, targets)[1]) + logger.info(f"Calculated strategy: {calculated_strategy}") + + assert calculated_strategy >= expected_save_amount + logger.info(f"Save subgroup vertices test passed for {graph_key}") + + +def test_random_graph_comparison(): + logger.info("Starting test_random_graph_comparison:") + try: + for i in range(2): + num_nodes = random.randint(5, 50) + nodes = list(range(num_nodes + 1)) + num_edges = 100 + save_amount = random.randint(5, num_nodes) + targets = [] + G = nx.DiGraph() + + G.add_nodes_from(nodes, status=Status.VULNERABLE.value) + for _ in range(num_edges): + source = random.randint(0, num_nodes - 1) + target = random.randint(0, num_nodes - 1) + if source != target: # Ensure no self-loops + G.add_edge(source, target) + for node in range(save_amount): + probability = random.random() + if probability < 0.9 and node != 0: + targets.append(node) + + logger.info(f"Random Graph {i+1} - Targets: {targets}") + + start_time = time.time() + spreading = spreading_maxsave(G, 1, 0, targets) + spreading_answer = spreading_maxsave(G, 1, 0, targets)[1] + spreading_time = time.time() - start_time + + start_time = time.time() + heuristic = heuristic_maxsave(G, 1, 0, targets) + heuristic_answer = heuristic_maxsave(G, 1, 0, targets)[1] + + heuristic_time = time.time() - start_time + + logger.info(f"Random Graph {i+1} - Spreading Result: {spreading}, Heuristic Result: {heuristic}") + logger.info(f"Random Graph {i+1} - Spreading Time: {spreading_time:.6f}s, Heuristic Time: {heuristic_time:.6f}s") + + if len(spreading_answer) > len(heuristic_answer): + warning_message = f"Warning: Heuristic result ({len(heuristic_answer)}) is less than spreading result ({len(spreading_answer)}) for Random Graph {i+1}" + logger.warning(warning_message) + + finally: + logger.info("Finished test_random_graph_comparison.") + logger.info("-" * 100) + + +if __name__ == "__main__": + pytest.main(["-v",__file__]) + diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_heuristic_minbudget.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_heuristic_minbudget.py new file mode 100644 index 0000000..353f27e --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_heuristic_minbudget.py @@ -0,0 +1,144 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" +import pytest +import random +import time +import logging +import os +import json + +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import spreading_minbudget, heuristic_minbudget +from networkz.algorithms.approximation.firefighter_problem.Random_Graph_Generator import generate_random_DiGraph +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx + + +def setup_logger(): + logger = logging.getLogger('firefighter_problem_tests') + logger.setLevel(logging.INFO) + + console_handler = logging.StreamHandler() + console_handler.setLevel(logging.INFO) + + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + console_handler.setFormatter(formatter) + + logger.addHandler(console_handler) + return logger + +logger = setup_logger() + + +@pytest.fixture +def sample_json_data(): + return { + "Dirlay": { + "Graph-1": { + "vertices": [0, 1, 2, 3, 4, 5], + "edges": [[0, 1], [0, 2]] + }, + }, + "RegularGraph": { + "Graph-1": { + "vertices": [0, 1, 2], + "edges": [[0, 1], [1, 2]] + }, + } + } + +def get_graphs(): + path_to_graphs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'graphs.json') + if os.path.exists(path_to_graphs): + with open(path_to_graphs, "r") as file: + json_data = json.load(file) + else: + raise FileNotFoundError(f"{path_to_graphs} does not exist.") + + graphs = parse_json_to_networkx(json_data) + return graphs + +graphs = get_graphs() + +@pytest.mark.parametrize("G, source, targets, directed", [ + (graphs["RegularGraph_Graph-1"], -3, [1, 0, 4, 5, 2, 6], True), + (graphs["RegularGraph_Graph-4"], 10, [1, 3, 5, 6, 7], False), + (graphs["RegularGraph_Graph-6"], 12, [9, 2, 3, 4, 6, 7], True), + (graphs["RegularGraph_Graph-8"], -1, [7, 10, 4, 9, 3, 11, 2], False), + (graphs["RegularGraph_Graph-3"], 8, [1, 4, 2], True) +]) +def test_source_not_in_graph(G, source, targets, directed): + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + heuristic_minbudget(G, source, targets, directed) + +@pytest.mark.parametrize("G, source, targets, directed", [ + (graphs["RegularGraph_Graph-2"], 2, [0, 4, 5, 11, 6], True), + (graphs["RegularGraph_Graph-3"], 3, [0, 4, 5, -1, 1, 2], False), + (graphs["RegularGraph_Graph-6"], 7, [9, 2, 4, 5, 8, 11], True), + (graphs["RegularGraph_Graph-8"], 10, [0, 2, 4, 5, 8, 11, 12, 3, 15], False), + (graphs["RegularGraph_Graph-7"], 1, [3, 5, 4, 0, 13], True) +]) +def test_target_not_in_graph(G, source, targets, directed): + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + heuristic_minbudget(G, source, targets, directed) + +@pytest.mark.parametrize("G, source, targets, directed", [ + (graphs["RegularGraph_Graph-1"], 0, [1, 2, 3, 0, 4, 5, 6], True), + (graphs["RegularGraph_Graph-3"], 1, [5, 1, 4], False), + (graphs["RegularGraph_Graph-4"], 4, [1, 2, 3, 4, 5, 6, 7], True), + (graphs["RegularGraph_Graph-6"], 0, [0, 3, 5, 6, 7, 8, 9], False), + (graphs["RegularGraph_Graph-8"], 0, [13, 10, 8, 6, 5, 4, 3, 0, 1, 2], True) +]) +def test_source_is_target(G, source, targets, directed): + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + heuristic_minbudget(G, source, targets, directed) + + +@pytest.mark.parametrize("i", range(10)) +def test_random_graph_comparison(i): + logger.info(f"Starting test_random_graph_comparison for Random Graph {i+1}:") + try: + G = generate_random_DiGraph(num_nodes=100, edge_probability=0.5) + + num_targets = random.randint(1, int(len(G.nodes) / 2) + 1) + nodes_to_sample = list(G.nodes) + nodes_to_sample.remove(0) + targets = random.sample(list(nodes_to_sample), num_targets) + + start_time = time.time() + spreading_answer = spreading_minbudget(G, 0, targets)[0] + spreading_time = time.time() - start_time + + start_time = time.time() + heuristic_answer = heuristic_minbudget(G, 0, targets, True)[0] + heuristic_time = time.time() - start_time + + logger.info(f"Random Graph {i+1} - Spreading Result: {spreading_answer}, Heuristic Result: {heuristic_answer}") + logger.info(f"Random Graph {i+1} - Spreading Time: {spreading_time:.6f}s, Heuristic Time: {heuristic_time:.6f}s") + + if heuristic_answer > spreading_answer: + warning_message = f"Warning: Heuristic result ({heuristic_answer}) is greater than spreading result ({spreading_answer}) for Random Graph {i+1}" + logger.warning(warning_message) + + finally: + logger.info(f"Finished test_random_graph_comparison for Random Graph {i+1}.") + logger.info("-" * 100) + +if __name__ == "__main__": + pytest.main(["-v", __file__]) \ No newline at end of file diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_non_spreading_dirlaynet_minbudget.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_non_spreading_dirlaynet_minbudget.py new file mode 100644 index 0000000..15a2347 --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_non_spreading_dirlaynet_minbudget.py @@ -0,0 +1,385 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import pytest +import json +import numpy as np +import math +import random +import os + +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import non_spreading_dirlaynet_minbudget +from networkz.algorithms.approximation.firefighter_problem.Utils import adjust_nodes_capacity +from networkz.algorithms.approximation.firefighter_problem.Utils import create_st_graph +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx +from networkz.algorithms.max_flow_with_node_capacity import min_cut_with_node_capacity +from networkz.algorithms.approximation.firefighter_problem.Utils import calculate_vaccine_matrix +from networkz.algorithms.approximation.firefighter_problem.Utils import min_cut_N_groups +from networkz.algorithms.approximation.firefighter_problem.Utils import matrix_to_integers_values +from networkz.algorithms.approximation.firefighter_problem.Utils import min_budget_calculation +from networkz.algorithms.approximation.firefighter_problem.Random_Graph_Generator import generate_random_layered_network + +path_to_graphs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'graphs.json') +if os.path.exists(path_to_graphs): + with open(path_to_graphs, "r") as file: + json_data = json.load(file) +else: + raise FileNotFoundError(f"{path_to_graphs} does not exist.") + +graphs = parse_json_to_networkx(json_data) + +@pytest.mark.parametrize("graph_key, source, targets", [ + ("Dirlay_Graph-1", -3, [0, 5]), + ("Dirlay_Graph-2", 13, [0, 1, 4]), + ("Dirlay_Graph-3", 15, [0, 6, 7]), + ("Dirlay_Graph-4", -1, [1, 3, 5, 7]), +]) +def test_source_not_in_graph(graph_key, source, targets): + with pytest.raises(ValueError): + non_spreading_dirlaynet_minbudget(graphs[graph_key], source, targets) + +@pytest.mark.parametrize("graph_key, source, targets", [ + ("Dirlay_Graph-1", 0, [1, 5, 7]), + ("Dirlay_Graph-2", 1, [0, 2, -1, 9]), + ("Dirlay_Graph-3", 4, [0, 1, 2, 11, 12, 13, 14]), + ("Dirlay_Graph-4", 0, [1, 3, 5, 7, 15, 20]), +]) +def test_target_not_in_graph(graph_key, source, targets): + with pytest.raises(ValueError): + non_spreading_dirlaynet_minbudget(graphs[graph_key], source, targets) + +@pytest.mark.parametrize("graph_key, source, targets", [ + ("Dirlay_Graph-1", 0, [0, 5]), + ("Dirlay_Graph-2", 1, [0, 1, 4]), + ("Dirlay_Graph-3", 6, [0, 6, 7]), + ("Dirlay_Graph-4", 3, [1, 3, 5, 7]), +]) +def test_source_is_target(graph_key, source, targets): + with pytest.raises(ValueError): + non_spreading_dirlaynet_minbudget(graphs[graph_key], source, targets) + + +# Test 1 +# graph building +graph_1 = graphs["Dirlay_Graph-1"] +layers_1 = adjust_nodes_capacity(graph_1, 0) # src is 0 +targets_1 = [1, 2, 3] # saving 1,2,3 +G1 = create_st_graph(graph_1, targets_1,'t') +reduction_G1_min_cut = min_cut_with_node_capacity(G1, 0) +N_1_groups = min_cut_N_groups(reduction_G1_min_cut,layers_1) +matrix_1 = calculate_vaccine_matrix(layers_1, N_1_groups) +integer_matrix_1 = matrix_to_integers_values(matrix_1) +min_budget_1 = min_budget_calculation(integer_matrix_1) + +# Test 2 +# graph building +graph_2 = graphs["Dirlay_Graph-2"] +layers_2 = adjust_nodes_capacity(graph_2, 0) # src is 0 +targets_2 = [2, 4] # saving 2,4 +G2 = create_st_graph(graph_2, targets_2,'t') +reduction_G2_min_cut = min_cut_with_node_capacity(G2, 0) +N_2_groups = min_cut_N_groups(reduction_G2_min_cut, layers_2) +matrix_2 = calculate_vaccine_matrix(layers_2, N_2_groups) +integer_matrix_2 = matrix_to_integers_values(matrix_2) +min_budget_2 = min_budget_calculation(integer_matrix_2) + +# Test 3 +# graph building +graph_3 = graphs["Dirlay_Graph-3"] +layers_3 = adjust_nodes_capacity(graph_3, 0) # src is 0 +targets_3 = [1, 5, 7] # saving 1,5,7 +G3 = create_st_graph(graph_3, targets_3,'t') +reduction_G3_min_cut = min_cut_with_node_capacity(G3, 0) +N_3_groups = min_cut_N_groups(reduction_G3_min_cut, layers_3) +matrix_3 = calculate_vaccine_matrix(layers_3, N_3_groups) +integer_matrix_3 = matrix_to_integers_values(matrix_3) +min_budget_3 = min_budget_calculation(integer_matrix_3) + +# Test 4 +# graph building +graph_4 = graphs["Dirlay_Graph-4"] +layers_4 = adjust_nodes_capacity(graph_4, 0) # src is 0 +targets_4 = [4, 5, 6, 8] # saving 4,5,6,8 +G4 = create_st_graph(graph_4, targets_4,'t') +reduction_G4_min_cut = min_cut_with_node_capacity(G4, 0) +N_4_groups = min_cut_N_groups(reduction_G4_min_cut, layers_4) +matrix_4 = calculate_vaccine_matrix(layers_4, N_4_groups) +integer_matrix_4 = matrix_to_integers_values(matrix_4) +min_budget_4 = min_budget_calculation(integer_matrix_4) + +def test_adjust_nodes_capacity(): + """ + This test checks if the node capacity and layers are correct. + """ + # Tolerance for floating point comparisons, this is simply to not inturrpt in the after point shenanings. + tolerance = 1e-6 + + # Test 1 + layers_1_check = [[0], [1, 2], [3], [4], [5]] + assert adjust_nodes_capacity(graph_1, 0) == layers_1_check + assert math.isclose(graph_1.nodes[1]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3 + 1/4)), rel_tol=tolerance) + assert math.isclose(graph_1.nodes[2]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3 + 1/4)), rel_tol=tolerance) + assert math.isclose(graph_1.nodes[3]['capacity'], 1 / (2 * (1/1 + 1/2 + 1/3 + 1/4)), rel_tol=tolerance) + assert math.isclose(graph_1.nodes[4]['capacity'], 1 / (3 * (1/1 + 1/2 + 1/3 + 1/4)), rel_tol=tolerance) + assert math.isclose(graph_1.nodes[5]['capacity'], 1 / (4 * (1/1 + 1/2 + 1/3 + 1/4)), rel_tol=tolerance) + + # Test 2 + layers_2_check = [[0], [1, 2], [4, 3]] + assert adjust_nodes_capacity(graph_2, 0) == layers_2_check + assert math.isclose(graph_2.nodes[1]['capacity'], 1 / (1 * (1/1 + 1/2)), rel_tol=tolerance) + assert math.isclose(graph_2.nodes[2]['capacity'], 1 / (1 * (1/1 + 1/2)), rel_tol=tolerance) + assert math.isclose(graph_2.nodes[3]['capacity'], 1 / (2 * (1/1 + 1/2)), rel_tol=tolerance) + assert math.isclose(graph_2.nodes[4]['capacity'], 1 / (2 * (1/1 + 1/2)), rel_tol=tolerance) + + # Test 3 + layers_3_check = [[0], [1, 2, 3], [5, 4], [6, 7]] + assert adjust_nodes_capacity(graph_3, 0) == layers_3_check + assert math.isclose(graph_3.nodes[1]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + assert math.isclose(graph_3.nodes[2]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + assert math.isclose(graph_3.nodes[3]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + assert math.isclose(graph_3.nodes[4]['capacity'], 1 / (2 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + assert math.isclose(graph_3.nodes[5]['capacity'], 1 / (2 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + assert math.isclose(graph_3.nodes[6]['capacity'], 1 / (3 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + assert math.isclose(graph_3.nodes[7]['capacity'], 1 / (3 * (1/1 + 1/2 + 1/3)), rel_tol=tolerance) + + # Test 4 + layers_4_check = [[0], [1, 2], [3, 4], [5], [6], [8]] + assert adjust_nodes_capacity(graph_4, 0) == layers_4_check + assert math.isclose(graph_4.nodes[1]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + assert math.isclose(graph_4.nodes[2]['capacity'], 1 / (1 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + assert math.isclose(graph_4.nodes[3]['capacity'], 1 / (2 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + assert math.isclose(graph_4.nodes[4]['capacity'], 1 / (2 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + assert math.isclose(graph_4.nodes[5]['capacity'], 1 / (3 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + assert math.isclose(graph_4.nodes[6]['capacity'], 1 / (4 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + assert math.isclose(graph_4.nodes[8]['capacity'], 1 / (5 * (1/1 + 1/2 + 1/3 + 1/4 + 1/5)), rel_tol=tolerance) + + + +def test_create_st_graph() : + """ + Creates the s-t graph and connects the nodes we want to save. + """ + # Test1 + # edges check + assert "t" in G1 + assert G1.has_edge(1, "t") + assert G1.has_edge(2, "t") + assert G1.has_edge(3, "t") + + # Test2 + # edges check + assert "t" in G2 + assert G2.has_edge(2, "t") + assert G2.has_edge(4, "t") + + # Test3 + # edges check + assert "t" in G3 + assert G3.has_edge(1, "t") + assert G3.has_edge(5, "t") + assert G3.has_edge(7, "t") + + # Test4 + # edges check + assert "t" in G4 + assert G4.has_edge(4, "t") + assert G4.has_edge(5, "t") + assert G4.has_edge(6, "t") + assert G4.has_edge(8, "t") + +def test_min_cut_N_groups(): + """ + This test validates the nodes taken from the min-cut create the right groups (N_1...N_l). + """ + def sort_dict_values(d): #| this is for sorting purposes , cases where [1,2] or [2,1] it does not really matters as we need to vaccinate them. + return {k: sorted(v) for k, v in d.items()} + + # Test 1 + # checking equality + N1_groups_check = {1: [1, 2], 2: [], 3: [], 4: []} + result_1 = min_cut_N_groups(reduction_G1_min_cut, layers_1) + assert sort_dict_values(result_1) == sort_dict_values(N1_groups_check) + + # Test 2 + # checking equality + N2_groups_check = {1: [2], 2: [4]} + result_2 = min_cut_N_groups(reduction_G2_min_cut, layers_2) + assert sort_dict_values(result_2) == sort_dict_values(N2_groups_check) + + # Test 3 + # checking equality + N3_groups_check = {1: [1], 2: [], 3: [7]} + result_3 = min_cut_N_groups(reduction_G3_min_cut, layers_3) + assert sort_dict_values(result_3) == sort_dict_values(N3_groups_check) + + # Test 4 + # checking equality + N4_groups_check = {1: [], 2: [4], 3: [5], 4: [], 5: []} + result_4 = min_cut_N_groups(reduction_G4_min_cut, layers_4) + assert sort_dict_values(result_4) == sort_dict_values(N4_groups_check) + +def test_calculate_vaccine_matrix(): + """ + This test checks that the calculations made to create the triangular matrix from the min-cut nodes are correct. + A matrix is valid if, for any column j, the column sum is exactly |Nj|. + """ + # Test 1 + # checking equality + matrix_1_check = np.array([[2, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]]) + np.testing.assert_array_equal(calculate_vaccine_matrix(layers_1, N_1_groups), matrix_1_check) + + # Test 2 + + """ + Applying the formula: Mij ': = Nj j , 1≤i≤j≤2 (l=2) + N2_groups_check = {1: [2], 2: [4]} + N1 : = {2} |N1| = 1 + N2 : = {4} |N2| = 1 + + 1. M11 : i = 1, j = 1 + |N1|/1 = 1/1 = 1 + 2. M12 : i = 1, j = 2 + |N2|/2 = 1/2 + 3. M22 : i = 2, j = 2 + |N2|/2 = 1/2 + """ + + # checking equality + matrix_2_check = np.array([[1, 0.5], + [0, 0.5]]) + np.testing.assert_array_equal(calculate_vaccine_matrix(layers_2, N_2_groups), matrix_2_check) + + # Test 3 + """ + Applying the formula: Mij ': = Nj j , 1≤i≤j≤2 (l=2) + N3_groups_check = {1: [1], 2: [], 3: [7]} + N1 : = {1} |N1| = 1 + N2 : = {0} |N2| = 0 + N3 := {7} |N3| = 1 + + 1. M11 : i = 1, j = 1 + |N1|/1 = 1/1 = 1 + 2. M12 : i = 1, j = 2 + |N2|/2 = 0/2 = 0 + 3. M13 : i = 1, j = 3 + |N3|/3 = 1/3 + 4. M22 : i = 2, j = 2 + |N2|/2 = 0/2 = 0 + 5. M23 : i = 2 j = 3 + |N3|/3 = 1/3 + 5. M33 : i = 2 j = 3 + |N3|/3 = 1/3 + """ + # checking equality + matrix_3_check = np.array([[1, 0, 1/3], + [0, 0, 1/3], + [0, 0, 1/3]]) + np.testing.assert_array_equal(calculate_vaccine_matrix(layers_3, N_3_groups), matrix_3_check) + + # Test 4 + # checking equality + matrix_4_check = np.array([[0, 0.5, 1/3, 0, 0], + [0, 0.5, 1/3, 0, 0], + [0, 0, 1/3, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]]) + np.testing.assert_array_equal(calculate_vaccine_matrix(layers_4, N_4_groups), matrix_4_check) + +def test_matrix_to_integers_values(): + """ + Test the matrix to integers values function. + """ + # Test 1 + # checking equality + matrix_1_check = np.array([[2, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]]) + + expected_matrix_1 = np.array([[2, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]]) + np.testing.assert_array_equal(matrix_to_integers_values(matrix_1_check), expected_matrix_1) + + # Test 2 + # checking equality + matrix_2_check = np.array([[1, 0.5], + [0, 0.5]]) + + expected_matrix_2 = np.array([[1, 1], + [0, 0]]) + np.testing.assert_array_equal(matrix_to_integers_values(matrix_2_check), expected_matrix_2) + + # Test 3 + # checking equality + matrix_3_check = np.array([[1, 0, 1/3], + [0, 0, 1/3], + [0, 0, 1/3]]) + + expected_matrix_3 = np.array([[1, 0, 1], + [0, 0, 0], + [0, 0, 0]]) + np.testing.assert_array_equal(matrix_to_integers_values(matrix_3_check), expected_matrix_3) + + +def test_min_budget_calculation(): + """ + This test validates that the minimum budget is accurate. + """ + # Test 1 + # checking equality + matrix_1_check = np.array([[2, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]]) + assert min_budget_calculation(matrix_1_check) == 2 + + # Test 2 + # checking equality + matrix_2_check = np.array([[1, 1], #on time i = 1, vaccinate M11(1) nodes from layer 1. , on time i = 2, vaccinante M12(1) nodes from layer 2 + [0, 0]]) + assert min_budget_calculation(matrix_2_check) == 2 + + # Test 3 + # checking equality + matrix_3_check = np.array([[1, 0, 1], + [0, 0, 0], + [0, 0, 0]]) + assert min_budget_calculation(matrix_3_check) == 2 + + +def test_non_spreading_dirlaynet_minbudget(): + G = generate_random_layered_network() + source = 0 + + nodes = list(G.nodes()) + num_targets = random.randint(1, len(nodes) - 1) # Ensure at least one target node + targets = random.sample(nodes[1:], num_targets) # Randomly choose nodes to save, excluding the source node + + min_budget = non_spreading_dirlaynet_minbudget(G, source, targets)[0] + assert min_budget > 0, "Minimum budget should be non-negative" + +if __name__ == "__main__": + pytest.main(["-v", __file__]) diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_non_spreading_minbudget.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_non_spreading_minbudget.py new file mode 100644 index 0000000..16c230a --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_non_spreading_minbudget.py @@ -0,0 +1,129 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import pytest +import json +import os + +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import non_spreading_minbudget +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx + +@pytest.fixture +def sample_json_data(): + return { + "Dirlay": { + "Graph-1": { + "vertices": [0, 1, 2, 3, 4, 5], + "edges": [[0, 1], [0, 2]] + }, + }, + "RegularGraph": { + "Graph-1": { + "vertices": [0, 1, 2], + "edges": [[0, 1], [1, 2]] + }, + } + } + +def get_graphs(): + path_to_graphs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'graphs.json') + if os.path.exists(path_to_graphs): + with open(path_to_graphs, "r") as file: + json_data = json.load(file) + else: + raise FileNotFoundError(f"{path_to_graphs} does not exist.") + + graphs = parse_json_to_networkx(json_data) + return graphs + +graphs = get_graphs() + +def test_source_not_in_graph(): + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + non_spreading_minbudget(graphs["RegularGraph_Graph-1"], -2, [1,2,3,4,5,6]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + non_spreading_minbudget(graphs["RegularGraph_Graph-4"], 8, [1,2,4,6,7]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + non_spreading_minbudget(graphs["RegularGraph_Graph-6"], 10, [0,2,3,5,6,7,8,9]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + non_spreading_minbudget(graphs["RegularGraph_Graph-8"], 17, [1,7,12,14,8,3,11,2]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + non_spreading_minbudget(graphs["RegularGraph_Graph-3"], 6, [1,3,5]) + + +def test_target_not_in_graph(): + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + non_spreading_minbudget(graphs["RegularGraph_Graph-2"], 0, [1,2,3,9,5,16]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + non_spreading_minbudget(graphs["RegularGraph_Graph-3"], 4, [1,2,3,6,7]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + non_spreading_minbudget(graphs["RegularGraph_Graph-6"], 3, [0,2,5,6,7,8,10]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + non_spreading_minbudget(graphs["RegularGraph_Graph-8"], 11, [1,3,12,19,8,10,4,2]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + non_spreading_minbudget(graphs["RegularGraph_Graph-7"], 2, [1,3,-1,5]) + + +def test_source_is_target(): + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + non_spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,2,3,0,4,5,6]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + non_spreading_minbudget(graphs["RegularGraph_Graph-3"], 1, [5,1,4]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + non_spreading_minbudget(graphs["RegularGraph_Graph-4"], 4, [1,2,3,4,5,6,7]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + non_spreading_minbudget(graphs["RegularGraph_Graph-6"], 0, [0,3,5,6,7,8,9]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + non_spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [13,10,8,6,5,4,3,0,1,2]) + +def test_save_all_vertices(): + assert 2 == non_spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,2,3,4,5,6])[0] #answer is 2 + assert 2 == non_spreading_minbudget(graphs["RegularGraph_Graph-2"], 0, [1,2,3,4,5,6,7])[0] #answer is 2 + assert 3 != non_spreading_minbudget(graphs["RegularGraph_Graph-3"], 0, [1,2,3,4,5])[0] #answer is 2 + assert 3 > non_spreading_minbudget(graphs["RegularGraph_Graph-4"], 0, [1,2,3,4,5,6,7])[0] #answer is 2 + assert 1 == non_spreading_minbudget(graphs["RegularGraph_Graph-6"], 1, [0,2,3,4,5,6,7,8,9])[0] #answer is 1 + assert 3 == non_spreading_minbudget(graphs["RegularGraph_Graph-7"], 1, [0,2,3,4,5,6])[0] #answer is 3 + assert 2 != non_spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [1,2,3,4,5,6,7,8,9,10,11,12,13,14])[0] #answer is 3 + +def test_save_subgroup_vertices(): + assert 1 != non_spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,5,6])[0] #answer is 2 + assert 1 == non_spreading_minbudget(graphs["RegularGraph_Graph-2"], 0, [1,3,4,5,6])[0] #answer is 1 + assert 3 > non_spreading_minbudget(graphs["RegularGraph_Graph-3"], 0, [1,2])[0] #answer is 2 + assert 1 < non_spreading_minbudget(graphs["RegularGraph_Graph-4"], 0, [2,3,5,7])[0] #answer is 2 + assert 4 > non_spreading_minbudget(graphs["RegularGraph_Graph-6"], 1, [0,3,5,6,8,9])[0] #answer is 1 + assert 2 == non_spreading_minbudget(graphs["RegularGraph_Graph-7"], 1, [0,2,5,6])[0] #answer is 2 + assert 3 == non_spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [1,3,4,5,6,9,10,12,14])[0] #answer is 3 + + +if __name__ == "__main__": + pytest.main(["-v", __file__]) \ No newline at end of file diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_parsing.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_parsing.py new file mode 100644 index 0000000..03066b8 --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_parsing.py @@ -0,0 +1,139 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import pytest +import networkx as nx + +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx, Status + +@pytest.fixture +def sample_json_data(): + return { + "Dirlay": { + "Graph-1": { + "vertices": [0, 1, 2, 3, 4, 5], + "edges": [[0, 1], [0, 2]] + }, + }, + "RegularGraph": { + "Graph-1": { + "vertices": [0, 1, 2], + "edges": [[0, 1], [1, 2]] + }, + } + } + +@pytest.fixture +def missing_vertices_json(): + return { + "InvalidGraph": { + "Graph-1": { + "edges": [[0, 1], [1, 2]] + } + } + } + +@pytest.fixture +def missing_edges_json(): + return { + "InvalidGraph": { + "Graph-2": { + "vertices": [0, 1, 2] + } + } + } + +@pytest.fixture +def empty_json(): + return { + "InvalidGraph": { + "Graph-3": { + "vertices": [], + "edges": [] + } + } + } + + +def test_parsing_dirlay_graph(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + dirlay_graph = graphs["Dirlay_Graph-1"] + assert isinstance(dirlay_graph, nx.DiGraph) + +def test_parsing_dirlay_graph_nodes(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + dirlay_graph = graphs["Dirlay_Graph-1"] + assert set(dirlay_graph.nodes()) == {0, 1, 2, 3, 4, 5} + +def test_parsing_dirlay_graph_edges(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + dirlay_graph = graphs["Dirlay_Graph-1"] + assert set(dirlay_graph.edges()) == {(0, 1), (0, 2)} + +def test_parsing_regular_graph(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + regular_graph = graphs["RegularGraph_Graph-1"] + assert isinstance(regular_graph, nx.Graph) + +def test_parsing_regular_graph_nodes(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + regular_graph = graphs["RegularGraph_Graph-1"] + assert set(regular_graph.nodes()) == {0, 1, 2} + +def test_parsing_regular_graph_edges(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + regular_graph = graphs["RegularGraph_Graph-1"] + assert set(regular_graph.edges()) == {(0, 1), (1, 2)} + +def test_parse_exceptions_missing_vertices(missing_vertices_json): + with pytest.raises(KeyError): + parse_json_to_networkx(missing_vertices_json) + +def test_parse_exceptions_missing_edges(missing_edges_json): + with pytest.raises(KeyError): + parse_json_to_networkx(missing_edges_json) + +def test_parse_exceptions_empty_json(empty_json): + with pytest.raises(KeyError): + parse_json_to_networkx(empty_json) + +def test_parsing_dirlay_graph_status(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + dirlay_graph = graphs["Dirlay_Graph-1"] + for node in dirlay_graph.nodes(data=True): + assert node[1]["status"] == Status.VULNERABLE.value + +def test_parsing_regular_graph_status(sample_json_data): + graphs = parse_json_to_networkx(sample_json_data) + + regular_graph = graphs["RegularGraph_Graph-1"] + for node in regular_graph.nodes(data=True): + assert node[1]["status"] == Status.VULNERABLE.value + +if __name__ == "__main__": + pytest.main(["-v", __file__]) \ No newline at end of file diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_spreading_maxsave.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_spreading_maxsave.py new file mode 100644 index 0000000..15b7873 --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_spreading_maxsave.py @@ -0,0 +1,299 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import pytest +import networkx as nx +import json +import random +import os + +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import spreading_maxsave +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx, calculate_gamma, calculate_epsilon, find_best_direct_vaccination + +path_to_graphs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'graphs.json') +if os.path.exists(path_to_graphs): + with open(path_to_graphs, "r") as file: + json_data = json.load(file) +else: + raise FileNotFoundError(f"{path_to_graphs} does not exist.") +graphs = parse_json_to_networkx(json_data) + +@pytest.mark.parametrize("graph_key, budget, source, targets", [ + ("RegularGraph_Graph-1", 1, -2, [1, 2, 3, 4, 5, 6]), + ("RegularGraph_Graph-4", 1, 8, [1, 2, 4, 6, 7]), + ("RegularGraph_Graph-6", 1, 10, [0, 2, 3, 5, 6, 7, 8, 9]), + ("RegularGraph_Graph-8", 1, 17, [1, 7, 12, 14, 8, 3, 11, 2]), + ("RegularGraph_Graph-3", 1, 6, [1, 3, 5]), +]) +def test_source_not_in_graph(graph_key, budget, source, targets): + with pytest.raises(ValueError): + spreading_maxsave(graphs[graph_key], budget, source, targets) + +@pytest.mark.parametrize("graph_key, budget, source, targets", [ + ("RegularGraph_Graph-2", 1, 0, [1, 2, 3, 9, 5, 16]), + ("RegularGraph_Graph-3", 1, 4, [1, 2, 3, 6, 7]), + ("RegularGraph_Graph-6", 1, 3, [0, 2, 5, 6, 7, 8, 10]), + ("RegularGraph_Graph-8", 1, 11, [1, 3, 12, 19, 8, 10, 4, 2]), + ("RegularGraph_Graph-7", 1, 2, [1, 3, -1, 5]), +]) +def test_target_not_in_graph(graph_key, budget, source, targets): + with pytest.raises(ValueError): + spreading_maxsave(graphs[graph_key], budget, source, targets) + +@pytest.mark.parametrize("graph_key, budget, source, targets", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 0, 4, 5, 6]), + ("RegularGraph_Graph-3", 1, 1, [5, 1, 4]), + ("RegularGraph_Graph-4", 1, 4, [1, 2, 3, 4, 5, 6, 7]), + ("RegularGraph_Graph-6", 1, 0, [0, 3, 5, 6, 7, 8, 9]), + ("RegularGraph_Graph-8", 1, 0, [13, 10, 8, 6, 5, 4, 3, 0, 1, 2]), +]) +def test_source_is_target(graph_key, budget, source, targets): + with pytest.raises(ValueError): + spreading_maxsave(graphs[graph_key], budget, source, targets) + +@pytest.mark.parametrize("graph_key, source, targets, expected_gamma, expected_direct_vaccination", [ + ("Dirlay_Graph-5", 0, [1, 2, 3, 4, 5 ,6 ,7 ,8], { + 1: [(2, 1), (4, 1), (1, 1), (1, 2)], + 2: [(2, 1)], + 3: [(2, 1), (5, 1), (3, 1), (3, 2)], + 4: [(4, 1)], + 5: [(5, 1)], + 6: [(4, 1), (5, 1), (6, 1), (6, 2)], + 7: [(5, 1), (6, 1), (7, 1), (7, 2)], + 8: [(4, 1), (5, 1), (6, 1), (6, 2), (7, 1), (7, 2), (8, 1), (8, 2), (8, 3)], + }, { + (1, 1): [1], + (1, 2): [1], + (2, 1): [1, 2, 3], + (3, 1): [3], + (3, 2): [3], + (4, 1): [1, 4, 6, 8], + (5, 1): [3, 5, 6, 7, 8], + (6, 1): [6, 7, 8], + (6, 2): [6, 8], + (7, 1): [7, 8], + (7, 2): [7, 8], + (8, 1): [8], + (8, 2): [8], + (8, 3): [8] + }), + ("RegularGraph_Graph-1", 0, [1, 3, 4, 5], { + 1: [(1, 1)], + 2: [(2, 1)], + 3: [(1, 1), (2, 1), (3, 1), (3, 2)], + 4: [(1, 1), (4, 1), (4, 2)], + 5: [(1, 1), (2, 1), (3, 1), (3, 2), (5, 1), (5, 2), (5, 3)], + 6: [(2, 1), (6, 1), (6, 2)], + }, { + (1, 1): [1, 3, 4, 5], + (2, 1): [3, 5], + (3, 1): [3, 5], + (3, 2): [3, 5], + (4, 1): [4], + (4, 2): [4], + (5, 1): [5], + (5, 2): [5], + (5, 3): [5], + (6, 1): [], + (6, 2): [], + }) +]) +def test_calculate_gamma(graph_key, source, targets, expected_gamma, expected_direct_vaccination): + print(calculate_gamma(graphs[graph_key], source, targets)) + calculated_gamma, calculated_direct_vaccination = calculate_gamma(graphs[graph_key], source, targets) + + for key in expected_gamma: + assert key in calculated_gamma, f"Expected key {key} to be in {calculated_gamma}" + assert calculated_direct_vaccination == expected_direct_vaccination + +@pytest.mark.parametrize("direct_vaccinations, expected_epsilon", [ + ({ + (1, 1): [1, 3, 4, 5], + (2, 1): [2, 3, 5, 6], + (3, 1): [3, 5], + (3, 2): [3, 5], + (4, 1): [4], + (4, 2): [4], + (5, 1): [5], + (5, 2): [5], + (5, 3): [5], + (6, 1): [6], + (6, 2): [6], + }, [ + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)], + [(3, 2), (4, 2), (5, 2), (6, 2)], + [(5, 3)] + ]), + ({ + (1, 1): [1], + (1, 2): [1], + (2, 1): [1, 2, 3], + (3, 1): [3], + (3, 2): [3], + (4, 1): [1, 4, 6, 8], + (5, 1): [3, 5, 6, 7, 8], + (6, 1): [4, 6, 8], + (6, 2): [6, 8], + (7, 1): [7, 8], + (7, 2): [7, 8], + (8, 1): [8], + (8, 2): [8], + (8, 3): [8], + }, [ + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1)], + [(1, 2), (3, 2), (6, 2), (7, 2), (8, 2)], + [(8, 3)] + ]), +]) +def test_calculate_epsilon(direct_vaccinations, expected_epsilon): + calculated_epsilon = calculate_epsilon(direct_vaccinations) + + assert calculated_epsilon == expected_epsilon + +@pytest.mark.parametrize("graph_key, direct_vaccinations, current_epsilon, targets, expected_best_direct_vaccination", [ + ("RegularGraph_Graph-1", + { + (1, 1): [1, 2, 3, 4, 5, 7], + (2, 1): [2, 3, 4, 7], + (2, 2): [2, 3, 7], + (3, 1): [3, 4, 7], + (3, 2): [3, 4, 7], + (3, 3): [3, 7], + (4, 1): [4, 7], + (4, 2): [4, 7], + (4, 3): [4, 7], + (5, 1): [2, 3, 4, 5, 7], + (5, 2): [3, 4, 5, 7], + (6, 1): [3, 4, 5, 6, 7], + }, + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)], + [1, 3, 4, 5, 6], + (1, 1)), + ("Dirlay_Graph-5", + { + (1, 1): [1], + (1, 2): [1], + (2, 1): [1, 2, 3], + (3, 1): [3], + (3, 2): [3], + (4, 1): [1, 4, 6, 8], + (5, 1): [3, 5, 6, 7, 8], + (6, 1): [4, 6, 8], + (6, 2): [6, 8], + (7, 1): [7, 8], + (7, 2): [7, 8], + (8, 1): [8], + (8, 2): [8], + (8, 3): [8], + }, + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1)], + [1, 2, 3, 4, 5, 6, 7, 8], + (5, 1)) +]) + +def test_find_best_direct_vaccination(graph_key, direct_vaccinations, current_epsilon, targets, expected_best_direct_vaccination): + calculated_best_direct_vaccination = find_best_direct_vaccination(graphs[graph_key],direct_vaccinations,current_epsilon,targets)[0] + + assert calculated_best_direct_vaccination == expected_best_direct_vaccination + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_length", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 4, 5, 6], 2), + ("Dirlay_Graph-5", 2, 0, [1, 2, 3, 4, 5, 6, 7, 8], 3), +]) +def test_strategy_length(graph_key, budget, source, targets, expected_length): + graph = graphs[graph_key] + calculated_strategy = spreading_maxsave(graph, budget, source, targets)[0] + + assert len(calculated_strategy) == expected_length + + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_strategy", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 4, 5, 6], [(1, 1), (6, 2)]), + ("Dirlay_Graph-5", 2, 0, [1, 2, 3, 4, 5, 6, 7, 8], [(5, 1), (2, 1), (8, 2)]), +]) +def test_save_all_vertices(graph_key, budget, source, targets, expected_strategy): + graph = graphs[graph_key] + calculated_strategy = spreading_maxsave(graph, budget, source, targets)[0] + + assert calculated_strategy == expected_strategy + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_strategy", [ + ("RegularGraph_Graph-6", 2, 1, [3, 9, 0, 5, 6], [(2, 1), (0, 1)]), + ("RegularGraph_Graph-4", 1, 0, [2, 6, 4], [(1, 1), (3, 2)]), +]) +def test_save_subgroup_vertices(graph_key, budget, source, targets, expected_strategy): + graph = graphs[graph_key] + calculated_strategy = spreading_maxsave(graph, budget, source, targets)[0] + + assert calculated_strategy == expected_strategy + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_nodes_saved_list", [ + ("RegularGraph_Graph-1", 1, 0, [1, 2, 3, 4, 5, 6], {1, 3, 4, 5, 6}), + ("Dirlay_Graph-5", 2, 0, [1, 2, 3, 4, 5, 6, 7, 8], {1, 2, 3, 5, 6, 7, 8}), +]) +def test_save_all_vertices_nodes_list(graph_key, budget, source, targets, expected_nodes_saved_list): + graph = graphs[graph_key] + calculated_nodes_saved_list = spreading_maxsave(graph, budget, source, targets)[1] + print(calculated_nodes_saved_list) + + assert calculated_nodes_saved_list == expected_nodes_saved_list + +@pytest.mark.parametrize("graph_key, budget, source, targets, expected_nodes_saved_list", [ + ("RegularGraph_Graph-6", 2, 1, [3, 9, 0, 5, 6], {0, 3, 5, 6, 9}), + ("RegularGraph_Graph-4", 1, 0, [2, 6, 4], {2, 4}), +]) +def test_save_subgroup_vertices_nodes_list(graph_key, budget, source, targets, expected_nodes_saved_list): + graph = graphs[graph_key] + calculated_nodes_saved_list = spreading_maxsave(graph, budget, source, targets)[1] + + assert calculated_nodes_saved_list == expected_nodes_saved_list + +def test_random_graph(): + for i in range(10): + num_nodes = random.randint(2,100) + nodes = list(range(num_nodes+1)) + num_edges = 1000 + save_amount = random.randint(1,num_nodes) + targets = [] + G = nx.DiGraph() + + G.add_nodes_from(nodes, status="target") + for _ in range(num_edges): + source = random.randint(0, num_nodes - 1) + target = random.randint(0, num_nodes - 1) + if source != target: # Ensure no self-loops + G.add_edge(source, target) + for node in range(save_amount): + probability = random.random() + if probability < 0.75 and node!=0: + targets.append(node) + + ans = spreading_maxsave(G,1,0,targets)[0] + print(len(ans)) + print(len(G.nodes)) + + assert len(ans) <= len(G.nodes) + + print("All tests have passed!") + + +if __name__ == "__main__": + pytest.main(["-v", __file__]) \ No newline at end of file diff --git a/networkz/algorithms/approximation/tests/test_firefighter_problem/test_spreading_minbudget.py b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_spreading_minbudget.py new file mode 100644 index 0000000..29c9865 --- /dev/null +++ b/networkz/algorithms/approximation/tests/test_firefighter_problem/test_spreading_minbudget.py @@ -0,0 +1,291 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import pytest +import json +import random +import os + +from networkz.algorithms.approximation.firefighter_problem.Firefighter_Problem import spreading_minbudget +from networkz.algorithms.approximation.firefighter_problem.Utils import parse_json_to_networkx, calculate_gamma, calculate_epsilon, find_best_direct_vaccination +from networkz.algorithms.approximation.firefighter_problem.Random_Graph_Generator import generate_random_DiGraph + + +@pytest.fixture +def sample_json_data(): + return { + "Dirlay": { + "Graph-1": { + "vertices": [0, 1, 2, 3, 4, 5], + "edges": [[0, 1], [0, 2]] + }, + }, + "RegularGraph": { + "Graph-1": { + "vertices": [0, 1, 2], + "edges": [[0, 1], [1, 2]] + }, + } + } + +def get_graphs(): + path_to_graphs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'graphs.json') + if os.path.exists(path_to_graphs): + with open(path_to_graphs, "r") as file: + json_data = json.load(file) + else: + raise FileNotFoundError(f"{path_to_graphs} does not exist.") + + graphs = parse_json_to_networkx(json_data) + return graphs + +graphs = get_graphs() + +def test_source_not_in_graph(): + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + spreading_minbudget(graphs["RegularGraph_Graph-1"], -3, [1,0,4,5,2,6]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + spreading_minbudget(graphs["RegularGraph_Graph-4"], 10, [1,3,5,6,7]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + spreading_minbudget(graphs["RegularGraph_Graph-6"], 12, [9,2,3,4,6,7]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + spreading_minbudget(graphs["RegularGraph_Graph-8"], -1, [7,10,4,9,3,11,2]) + + with pytest.raises(ValueError, match="Error: The source node isn't on the graph"): + spreading_minbudget(graphs["RegularGraph_Graph-3"], 8, [1,4,2]) + + +def test_target_not_in_graph(): + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + spreading_minbudget(graphs["RegularGraph_Graph-2"], 2, [0,4,5,11,6]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + spreading_minbudget(graphs["RegularGraph_Graph-3"], 3, [0,4,5,-1,1,2]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + spreading_minbudget(graphs["RegularGraph_Graph-6"], 7, [9,2,4,5,8,11]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + spreading_minbudget(graphs["RegularGraph_Graph-8"], 10, [0,2,4,5,8,11,12,3,15]) + + with pytest.raises(ValueError, match="Error: Not all nodes in the targets list are on the graph."): + spreading_minbudget(graphs["RegularGraph_Graph-7"], 1, [3,5,4,0,13]) + + +def test_source_is_target(): + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,2,3,0,4,5,6]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + spreading_minbudget(graphs["RegularGraph_Graph-3"], 1, [5,1,4]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + spreading_minbudget(graphs["RegularGraph_Graph-4"], 4, [1,2,3,4,5,6,7]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + spreading_minbudget(graphs["RegularGraph_Graph-6"], 0, [0,3,5,6,7,8,9]) + + with pytest.raises(ValueError, match="Error: The source node can't be a part of the targets list, since the virus is spreading from the source"): + spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [13,10,8,6,5,4,3,0,1,2]) + +@pytest.mark.parametrize("graph_key, source, targets, expected_gamma, expected_direct_vaccination", [ + ("RegularGraph_Graph-4", 0, [1, 2, 3, 4, 5 ,6 ,7], { + 1: [(1, 1)], + 2: [(1, 1), (2, 1), (2, 2), (5, 1)], + 3: [(1, 1), (2, 1), (2, 2), (3, 1), (3, 2), (3, 3), (5, 1), (5, 2), (6, 1)], + 4: [(1, 1), (2, 1), (3, 1), (3, 2), (4, 1), (4, 2), (4, 3), (5, 1), (5, 2), (6, 1)], + 5: [(1, 1), (5, 1), (5, 2), (6, 1)], + 6: [(6, 1)], + 7: [], + }, { + (1, 1): [1, 2, 3, 4, 5, 7], + (2, 1): [2, 3, 4, 7], + (2, 2): [2, 3, 7], + (3, 1): [3, 4, 7], + (3, 2): [3, 4, 7], + (3, 3): [3, 7], + (4, 1): [4, 7], + (4, 2): [4, 7], + (4, 3): [4, 7], + (5, 1): [2, 3, 4, 5, 7], + (5, 2): [3, 4, 5, 7], + (6, 1): [3, 4, 5, 6, 7] + }), + ("RegularGraph_Graph-1", 0, [1, 3, 4, 5], { + 1: [(1, 1)], + 2: [(2, 1)], + 3: [(1, 1), (2, 1), (3, 1), (3, 2)], + 4: [(1, 1), (4, 1), (4, 2)], + 5: [(1, 1), (2, 1), (3, 1), (3, 2), (5, 1), (5, 2), (5, 3)], + 6: [(2, 1), (6, 1), (6, 2)], + }, { + (1, 1): [1, 3, 4, 5], + (2, 1): [3, 5], + (3, 1): [3, 5], + (3, 2): [3, 5], + (4, 1): [4], + (4, 2): [4], + (5, 1): [5], + (5, 2): [5], + (5, 3): [5], + (6, 1): [], + (6, 2): [], + }) +]) +def test_calculate_gamma(graph_key, source, targets, expected_gamma, expected_direct_vaccination): + calculated_gamma, calculated_direct_vaccination = calculate_gamma(graphs[graph_key], source, targets) + + assert calculated_gamma == expected_gamma + assert calculated_direct_vaccination == expected_direct_vaccination + + +@pytest.mark.parametrize("direct_vaccinations, expected_epsilon", [ + ({ + (1, 1): [1, 2, 3, 4, 5, 7], + (2, 1): [2, 3, 4, 7], + (2, 2): [2, 3, 7], + (3, 1): [3, 4, 7], + (3, 2): [3, 4, 7], + (3, 3): [3, 7], + (4, 1): [4, 7], + (4, 2): [4, 7], + (4, 3): [4, 7], + (5, 1): [2, 3, 4, 5, 7], + (5, 2): [3, 4, 5, 7], + (6, 1): [3, 4, 5, 6, 7], + }, [ + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)], + [(2, 2), (3, 2), (4, 2), (5, 2)], + [(3, 3), (4, 3)] + ]), + ({ + (1, 1): [1], + (1, 2): [1], + (2, 1): [1, 2, 3], + (3, 1): [3], + (3, 2): [3], + (4, 1): [1, 4, 6, 8], + (5, 1): [3, 5, 6, 7, 8], + (6, 1): [4, 6, 8], + (6, 2): [6, 8], + (7, 1): [7, 8], + (7, 2): [7, 8], + (8, 1): [8], + (8, 2): [8], + (8, 3): [8], + }, [ + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1)], + [(1, 2), (3, 2), (6, 2), (7, 2), (8, 2)], + [(8, 3)] + ]), +]) +def test_calculate_epsilon(direct_vaccinations, expected_epsilon): + calculated_epsilon = calculate_epsilon(direct_vaccinations) + + assert calculated_epsilon == expected_epsilon + +@pytest.mark.parametrize("graph_key, direct_vaccinations, current_epsilon, targets, expected_best_direct_vaccination", [ + ("RegularGraph_Graph-1", + { + (1, 1): [1, 2, 3, 4, 5, 7], + (2, 1): [2, 3, 4, 7], + (2, 2): [2, 3, 7], + (3, 1): [3, 4, 7], + (3, 2): [3, 4, 7], + (3, 3): [3, 7], + (4, 1): [4, 7], + (4, 2): [4, 7], + (4, 3): [4, 7], + (5, 1): [2, 3, 4, 5, 7], + (5, 2): [3, 4, 5, 7], + (6, 1): [3, 4, 5, 6, 7], + }, + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)], + [1, 3, 4, 5, 6], + (1, 1)), + ("Dirlay_Graph-5", + { + (1, 1): [1], + (1, 2): [1], + (2, 1): [1, 2, 3], + (3, 1): [3], + (3, 2): [3], + (4, 1): [1, 4, 6, 8], + (5, 1): [3, 5, 6, 7, 8], + (6, 1): [4, 6, 8], + (6, 2): [6, 8], + (7, 1): [7, 8], + (7, 2): [7, 8], + (8, 1): [8], + (8, 2): [8], + (8, 3): [8], + }, + [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1), (8, 1)], + [1, 2, 3, 4, 5, 6, 7, 8], + (5, 1)) +]) + +def test_find_best_direct_vaccination(graph_key, direct_vaccinations, current_epsilon, targets, expected_best_direct_vaccination): + calculated_best_direct_vaccination = find_best_direct_vaccination(graphs[graph_key],direct_vaccinations,current_epsilon,targets)[0] + + assert calculated_best_direct_vaccination == expected_best_direct_vaccination + +def test_save_all_vertices(): + assert 2 == spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,2,3,4,5,6])[0] # answer is 2 + assert 2 == spreading_minbudget(graphs["RegularGraph_Graph-2"], 0, [1,2,3,4,5,6,7])[0] # answer is 2 + assert 3 != spreading_minbudget(graphs["RegularGraph_Graph-3"], 0, [1,2,3,4,5])[0] # answer is 2 + assert spreading_minbudget(graphs["RegularGraph_Graph-2"], 0, [1,2,3,4,5,6,7])[0] >= spreading_minbudget(graphs["RegularGraph_Graph-4"], 0, [1,2,3,4,5,6,7])[0] # answer is 2 + assert spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,2,3,4,5,6])[0] > spreading_minbudget(graphs["RegularGraph_Graph-6"], 1, [0,2,3,4,5,6,7,8,9])[0] # answer is 1 + assert 3 == spreading_minbudget(graphs["RegularGraph_Graph-7"], 1, [0,2,3,4,5,6])[0] # answer is 3 + assert 2 != spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [1,2,3,4,5,6,7,8,9,10,11,12,13,14])[0] # answer is 4 + + +def test_save_subgroup_vertices(): + assert spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,2,3,4,5,6])[0] != spreading_minbudget(graphs["RegularGraph_Graph-1"], 0, [1,5,6])[0] # answer is 1 + assert 1 == spreading_minbudget(graphs["RegularGraph_Graph-2"], 0, [1,3,4,5,6])[0] #answer is 1 + assert spreading_minbudget(graphs["RegularGraph_Graph-3"], 0, [1,2,3,4,5])[0] > spreading_minbudget(graphs["RegularGraph_Graph-3"], 0, [1,3,5])[0] #answer is 1 + assert 2 > spreading_minbudget(graphs["RegularGraph_Graph-4"], 0, [2,3,5,7])[0] # anser is 1 + assert 4 > spreading_minbudget(graphs["RegularGraph_Graph-6"], 1, [0,3,5,6,8,9])[0] #answer is 1 + assert 2 == spreading_minbudget(graphs["RegularGraph_Graph-7"], 1, [4,2,5,6])[0] #answer is 2 + assert spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [1,2,3,4,5,6,7,8,9,10,11,12,13,14])[0] != spreading_minbudget(graphs["RegularGraph_Graph-8"], 0, [1,3,4,5,6,9,10,12,14])[0] #answer is 3 + + +def test_random_graph(): + for i in range(10): + G = generate_random_DiGraph(num_nodes=100, edge_probability=0.5) + + num_targets = random.randint(1, int(len(G.nodes) / 2) + 1) + nodes_to_sample = list(G.nodes) + nodes_to_sample.remove(0) + targets = random.sample(nodes_to_sample, num_targets) + + target_length = len(targets) + ans = spreading_minbudget(G,0,targets)[0] + + assert ans <= target_length + + print("All tests have passed!") + +if __name__ == "__main__": + pytest.main(["-v", __file__]) \ No newline at end of file diff --git a/networkz/algorithms/max_flow_with_node_capacity.py b/networkz/algorithms/max_flow_with_node_capacity.py new file mode 100644 index 0000000..89997a1 --- /dev/null +++ b/networkz/algorithms/max_flow_with_node_capacity.py @@ -0,0 +1,113 @@ +""" + +The Paper - +Approximability of the Firefighter Problem Computing Cuts over Time + +Paper Link - +https://www.math.uwaterloo.ca/~cswamy/papers/firefighter-journ.pdf + +Authors - +Elliot Anshelevich +Deeparnab Chakrabarty +Ameya Hate +Chaitanya Swamy + +Developers - +Yuval Bubnovsky +Almog David +Shaked Levi + +""" + +import networkx as nx +import networkx.algorithms.connectivity as algo +from networkz.algorithms.approximation.firefighter_problem.Utils import * +import logging + + +logger = logging.getLogger(__name__) + +def min_cut_with_node_capacity(graph: nx.DiGraph, source: int = None, target: int = None) -> set: + """ + Computes a minimum cut in the given graph, where each node has a capacity + + Parameters: + ---------- + graph : nx.DiGraph + The original directed graph. Each node should have a 'capacity' attribute. + source (Optional) : int + The source node in the graph. This node will have an infinite capacity + between its "in" and "out" nodes. + target (Optional) : int + The target node in the graph. This node will have an infinite capacity + between its "in" and "out" nodes + + Returns: + ------- + set + The minimum cut nodes + + Notes: + ----- + This function transforms a given directed graph into a new graph where each node + is split into two nodes (an "in" node and an "out" node) connected by an edge + with a capacity (weight). The transformation is used for flow problems where + nodes have capacities instead of edges - allowing to run algorithms which + were originally designed to be used for edge-flow problems. + - If a node does not have a 'capacity' attribute, a default capacity of 1 + is used. + - There is infinite capacity between two different edge_out & edge_in + + Examples: + -------- + >>> G = nx.DiGraph() + >>> G.add_node(1, capacity=0.6) + >>> G.add_node(2, capacity=0.6) + >>> G.add_node(3, capacity=0.3) + >>> G.add_node(4, capacity=0.3) + >>> G.add_edge(0, 1) + >>> G.add_edge(0, 2) + >>> G.add_edge(2, 3) + >>> G.add_edge(1, 4) + >>> s_t_G = create_st_graph(G, [2,4], 't') + >>> min_cut_nodes = min_cut_with_node_capacity(s_t_G, 0, 4) + >>> sorted(min_cut_nodes) + ['2_out', '4_out'] + """ + logger.info("Starting graph flow reduction") + H = nx.DiGraph() + + logger.debug("Adding nodes and internal edges") + for node in graph.nodes: + in_node, out_node = f'{node}_in', f'{node}_out' + H.add_nodes_from([in_node, out_node]) + if node == source: + H.add_edge(in_node, out_node, weight=float('inf')) + logger.debug(f"Added infinite capacity edge for source node: {node}") + elif node == target: + H.add_edge(in_node, out_node, weight=float('inf')) + logger.debug(f"Added infinite capacity edge for target node: {node}") + else: + capacity = graph.nodes[node].get('capacity', 1) + H.add_edge(in_node, out_node, weight=capacity) + logger.debug(f"Added edge with capacity {capacity} for node: {node}") + + logger.debug("Adding edges between nodes") + for edge in graph.edges: + u_out, v_in = f'{edge[0]}_out', f'{edge[1]}_in' + H.add_edge(u_out, v_in, weight=float('inf')) + logger.debug(f"Added infinite capacity edge from {u_out} to {v_in}") + + logger.info("Graph flow reduction finished") + + # Compute the minimum cut + logger.info(f"Finding the minimum cut on the graph after reduction") + min_cut_nodes = algo.minimum_st_node_cut(H, f'{source}_out', 't_in') + + logger.info(f"Minimum Cut is: {min_cut_nodes}") + return min_cut_nodes + +if __name__ == "__main__": + import doctest + result = doctest.testmod(verbose=False) + print(f"Doctest results: {result}") diff --git a/pyproject.toml b/pyproject.toml index 4c057b2..a310b1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,3 +95,7 @@ select = [ [tool.mypy] ignore_missing_imports = true exclude = 'subgraphviews|reportviews' + +[tool.pytest.ini_options] +minversion = "6.0" +addopts = " --doctest-modules --durations=10 --ignore=experiments"