def test_long_links_within_threshold(self): """ Test that long links are indeed within a certain threshold """ for dth in range(1, 4): threshold = 2**dth number_of_links = 1 factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold) graph_edges = factory.generate_random_power_law_graph_edges( number_of_links) count = 0 for edge in graph_edges: # Checking for non-neighboring nodes: if self.are_long_neighbours(edge[0], edge[1], factory.number_of_nodes): link_length = self.get_link_length(edge[0], edge[1], factory.number_of_nodes) self.assertTrue( 1 < link_length <= threshold, "The length of long links should be greater than one but smaller than or equal to" "the threshold value.") count += edge[2] number_of_edges = factory.number_of_nodes * number_of_links # We have checked all the edges self.assertEqual( count, number_of_edges, "There is a difference in the number of" " edges checked and the number of edges in the graph.")
def test_initial_knowledge_init(self): factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=2, number_of_nodes=32, max_distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() results = routing_algorithms.initial_knowledge_init( graph_edges, 50, link_prediction=False) self.assertEqual(4, len(results))
def test_dth16_long_links_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=16) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 17), [17, 1]) self.assertTrue( shortest_path.dijkstra(local_graph, 6, 18) != [18, 17, 1, 5, 6]) self.assertEqual(shortest_path.dijkstra(local_graph, 32, 18), [18, 17, 1, 32]) self.assertEqual(shortest_path.dijkstra(local_graph, 31, 18), [18, 17, 1, 31]) self.assertEqual(shortest_path.dijkstra(local_graph, 31, 18), [18, 17, 1, 31]) self.assertEqual(shortest_path.dijkstra(local_graph, 30, 18), [18, 17, 1, 29, 30]) self.assertEqual(shortest_path.dijkstra(local_graph, 29, 18), [18, 17, 1, 29]) self.assertEqual(shortest_path.dijkstra(local_graph, 28, 18), [18, 17, 1, 29, 28]) self.assertTrue( shortest_path.dijkstra(local_graph, 27, 18) != [18, 17, 1, 29, 27]) self.assertTrue( shortest_path.dijkstra(local_graph, 6, 18) != [18, 17, 1, 5, 6])
def test_number_of_paths_get_paths_for_all_pairs(self): """ Testing (a) the number of paths created (b) if all pairs are tested """ for dth in range(1, 5): # Creating the related graph object threshold = 2**dth factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold) deterministic_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(deterministic_edges) number_of_nodes = len(local_graph.Vertices) expected_number_of_pairs = number_of_nodes * (number_of_nodes - 1) # Generating the paths local_paths = local_graph.get_paths_for_all_pairs() self.assertEqual(len(local_paths), expected_number_of_pairs) list_of_pairs = [(path[-1:][0], path[:1][0]) for path in local_paths] # See if we really have the same source-destination pairs self.assertEqual( set(list_of_pairs), set([(x, y) for x in range(1, number_of_nodes + 1) for y in range(1, number_of_nodes + 1) if x != y]))
def test_initial_knowledge_step(self): factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=2, number_of_nodes=32, max_distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges, link_prediction=True) local_final_results = ([], [], [], []) local_time_window_size = 5 local_number_of_source_destination_pairs = 100 for x in range(1, local_number_of_source_destination_pairs + 1): self.assertEqual( None, routing_algorithms.initial_knowledge_step( local_graph, x, local_time_window_size, local_number_of_source_destination_pairs, local_final_results)) # See if we really have all the rounds computed [ self.assertEqual( math.ceil(local_number_of_source_destination_pairs / local_time_window_size) * local_time_window_size, len(x)) for x in local_final_results ]
def test_dth1(self): """ Testing (a) If the link is removed after the swap operation (b) If we get a latency of 1 for each neighbouring edge and no-link distance of 0 """ for dth in range(1, 5): threshold = 2**dth factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold, capacity=1) # Check for deterministic graph deterministic_edges = factory.generate_deterministic_graph_edges() main_graph = graph.Graph(deterministic_edges) # For each of the edge, we increment the latency, but not the number of no-links for (start, end, capacity) in deterministic_edges: for x in range(capacity): self.assertEqual(main_graph.get_edge_capacity(start, end), capacity - x) self.assertEqual( routing_algorithms.entanglement_swap( main_graph, start, end), (1, 0)) # The link was removed from the graph self.assertEqual(main_graph.get_edge_capacity(start, end), capacity - x - 1)
def test_dth4_simple_path(self): """ Test that it computes the paths according to the local data """ link_prediction = True factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges, link_prediction=link_prediction) # Shortest paths in the virtual graph self.assertEqual( shortest_path.dijkstra(local_graph, 1, 3, link_prediction=True), [3, 1]) self.assertEqual( shortest_path.dijkstra(local_graph, 1, 5, link_prediction=True), [5, 1]) self.assertEqual( shortest_path.dijkstra(local_graph, 1, 9, link_prediction=True), [9, 5, 1]) current_step = 1000 local_graph.update_stored_weights(current_step)\ # Still getting the same result, as 1 is equal to the source -> knows the availability of the 1-3 link self.assertEqual( shortest_path.dijkstra(local_graph, 1, 3, link_prediction=True), [3, 1]) self.assertEqual( shortest_path.dijkstra(local_graph, 1, 5, link_prediction=True), [5, 1]) # Link 5-9 is far away, so we move along the physical graph self.assertEqual( shortest_path.dijkstra(local_graph, 1, 9, link_prediction=True), [9, 8, 7, 6, 5, 1])
def test_neighbouring_link_is_unique(self): """ Test that neighbours only share one virtual link """ for dth in range(1, 3): factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=2**dth) graph_edges = factory.generate_deterministic_graph_edges() # Checking if neighbouring nodes only have exactly one link count = 0 for edge in graph_edges: # Checking for neighboring nodes: # (A) Either they have consequtive indices # (B) Or we are already at the end of the cycle and have the last edge if abs(edge[0] - edge[1]) == 1 or (edge[0] == factory.number_of_nodes and edge[1] == 1): self.assertEqual( edge[2], 1, "The should be only one edge between neighbouring nodes." ) count += 1 # We have checked all the nodes self.assertEqual( count, factory.number_of_nodes, "There is a difference in the number of nodes checked and " "the number of nodes in the graph.")
def test_dth2_long_links_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=2) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 15), [15, 13, 11, 9, 7, 5, 3, 1])
def test_dth2_complex_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=2) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 20), [20, 21, 23, 25, 27, 29, 31, 1])
def test_node_index_non_existent(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) self.assertRaises(KeyError, shortest_path.dijkstra, local_graph, 33, 35)
def test_dth4_simple_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 5), [5, 1])
def test_serve_demands(self): factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=2, number_of_nodes=32, max_distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) results = routing_algorithms.serve_demands(local_graph, deque([(1, 2)])) self.assertEqual(results, ([1], [55], [47]))
def test_initialize_paths(self): number_of_pairs = 100 factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=2) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) self.assertTrue( number_of_pairs, len( routing_algorithms.initialize_paths(local_graph, number_of_pairs)))
def test_same_source_destination(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) for x in range(1, factory.number_of_nodes + 1): self.assertEqual(shortest_path.dijkstra(local_graph, x, x), [x])
def test_shift_by_index(self): for number in range(1, 50): factory = graph_edge_factory.VirtualEdgeFactory( number_of_nodes=number) for x in range(0, 200): for y in range(0, 200): if (x + y) % factory.number_of_nodes == 0: self.assertEqual(factory.shift_by_index(x, y), factory.number_of_nodes) else: self.assertEqual(factory.shift_by_index(x, y), (x + y) % factory.number_of_nodes)
def test_on_demand_graph(self): factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=1, capacity=0) graph_edges = factory.generate_deterministic_graph_edges() main_graph = graph.Graph(graph_edges) # For each of the edge, we don't increase the latency, but increment the number of no-links for (start, end, capacity) in graph_edges: self.assertEqual(capacity, 0) self.assertEqual( routing_algorithms.entanglement_swap(main_graph, start, end), (0, 1))
def test_dth4_on_demand_long_links_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=4, capacity=0) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) # self.assertEqual(shortest_path.dijkstra(local_graph, 1, 17), [17, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 16), [16, 15, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 16, 1), [1, 5, 9, 13, 15, 16]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 15), [15, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 15, 1), [1, 5, 9, 13, 15]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 14), [14, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 14, 1), [1, 5, 9, 13, 14])
def test_dth8_on_demand_long_links_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=8, capacity=0) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) # self.assertEqual(shortest_path.dijkstra(local_graph, 1, 17), [17, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 19), [19, 21, 25, 1]) # Disclaimer: the following is longer than the expected shortest path, as we are in the on-demand model self.assertEqual(shortest_path.dijkstra(local_graph, 1, 18), [18, 19, 21, 25, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 16), [16, 15, 13, 9, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 15), [15, 13, 9, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 14), [14, 13, 9, 1])
def test_create_graph_(self): for dth in range(1, 5): threshold = 2**dth factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold) # Check for deterministic graph deterministic_edges = factory.generate_deterministic_graph_edges() local_knowledge_graph = routing_algorithms.create_graph_with_local_knowledge( deterministic_edges) main_graph = graph.Graph(deterministic_edges) for vertex in local_knowledge_graph.Vertices.values(): self.assertTrue( TestLocalKnowledge.does_node_have_correct_knowledge( vertex.local_knowledge, main_graph)) self.assertTrue( TestLocalKnowledge.does_node_have_correct_knowledge( main_graph, vertex.local_knowledge))
def test_generate_deterministic_graph_edges_generates_long_links(self): for max_dth in range(1, 5): for dth in range(1, max_dth + 1): threshold = 2**dth max_threshold = 2**max_dth factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold, max_distance_threshold=max_threshold) graph_edges = factory.generate_deterministic_graph_edges() graph_edges_without_capacities = [(x[0], x[1]) for x in graph_edges] for node in range(1, factory.number_of_nodes + 1): if node % max_threshold == 1: self.assertTrue( (node, factory.shift_by_index(node, threshold)) in graph_edges_without_capacities or (factory.shift_by_index(node, threshold), node) in graph_edges_without_capacities)
def test_on_demand_distribute_entanglement(self): factory = graph_edge_factory.VirtualEdgeFactory(capacity=0) deterministic_edges = factory.generate_deterministic_graph_edges() main_graph = graph.Graph(deterministic_edges) for x in range(3, factory.number_of_nodes + 1): path = [node for node in range(1, x)] local_settings = routing_simulation.Settings() unit_time_for_rebuild = (1 / local_settings.rebuild_probability) potential_latency = unit_time_for_rebuild**(len(path) - 1) if local_settings.time_threshold > potential_latency: self.assertEqual( routing_algorithms.distribute_entanglement( main_graph, path), potential_latency) else: self.assertEqual( routing_algorithms.distribute_entanglement( main_graph, path), unit_time_for_rebuild**main_graph.physical_distance( path[-1:][0], path[:1][0]))
def test_sum_of_edges_deterministic_graph(self): """ Test that it can sum a list of integers """ for dth in range(0, 5): threshold = 2**dth factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold, max_distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() # Checking if the number of edges is the same as expected sum_of_edges = sum([x[2] for x in graph_edges]) number_of_edges = sum([ int(factory.number_of_nodes / 2**x) for x in range( 0, int(math.log(factory.max_distance_threshold, 2)) + 1) ]) self.assertEqual(sum_of_edges, number_of_edges, "The number of edges is not the expected value.")
def test_dth4_long_links_path(self): """ Test that it can sum a list of integers """ factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=4, max_distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) # self.assertEqual(shortest_path.dijkstra(local_graph, 1, 17), [17, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 27), [27, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 26), [26, 27, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 25), [25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 24), [24, 25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 23), [23, 25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 22), [22, 23, 25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 21), [21, 25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 20), [20, 21, 25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 19), [19, 21, 25, 29, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 18), [18, 17, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 16, 1), [1, 29, 25, 21, 17, 16]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 17), [17, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 16), [16, 17, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 15), [15, 13, 9, 5, 1]) self.assertEqual(shortest_path.dijkstra(local_graph, 1, 14), [14, 13, 9, 5, 1])
def test_continuous_distribute_entanglement(self): factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=2, number_of_nodes=32, max_distance_threshold=4) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) # First consume links (which costs 1), then assert for the real cost 4 ** dist # 1-> 2 self.assertEqual( 1, routing_algorithms.distribute_entanglement(local_graph, [1, 2])) self.assertEqual( 4, routing_algorithms.distribute_entanglement(local_graph, [1, 2])) # 2-> 3 self.assertEqual( 1, routing_algorithms.distribute_entanglement(local_graph, [2, 3])) self.assertEqual( 4, routing_algorithms.distribute_entanglement(local_graph, [2, 3])) # 1-> 3 for x in range(local_graph.get_edge_capacity(1, 3)): self.assertEqual( 1, routing_algorithms.distribute_entanglement( local_graph, [1, 3])) self.assertEqual( 4**local_graph.physical_distance(1, 3), routing_algorithms.distribute_entanglement(local_graph, [1, 3])) # 1-> 5 for x in range(local_graph.get_edge_capacity(3, 5)): self.assertEqual( 4**local_graph.physical_distance(1, 3) + 1, routing_algorithms.distribute_entanglement( local_graph, [1, 3, 5])) self.assertEqual( 4**local_graph.physical_distance(1, 5), routing_algorithms.distribute_entanglement(local_graph, [1, 3, 5]))
def test_always_same_as_nx(self): factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=2, max_distance_threshold=16) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) nx_graph = nx.Graph() for x in graph_edges: nx_graph.add_edge(x[0], x[1]) for x in range(1, factory.number_of_nodes + 1): for y in range(1, factory.number_of_nodes + 1): if x != y: shortest_path1 = shortest_path.dijkstra(local_graph, x, y) shortest_path2 = nx.shortest_path(nx_graph, x, y) self.assertEqual(len(shortest_path1), len(shortest_path2)) self.assertTrue(shortest_path1[0] == y) self.assertTrue(shortest_path1[len(shortest_path1)-1] == x) index = 0 for node in shortest_path1: self.assertEqual(node, shortest_path1[index]) index += 1 if index == len(shortest_path1)-2: self.assertTrue(shortest_path1[index+1] in nx.neighbors(nx_graph, shortest_path1[index]))
def test_complex_graphs_get_edge_frequencies_in_graph(self): """ Testing the number of edges in the dictionary and in the paths generated """ for dth in range(0, 5): threshold = 2**dth # Creating on-demand graphs factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold, capacity=0) graph_edges = factory.generate_deterministic_graph_edges() # print(graph_edges) temp_graph = graph.Graph(graph_edges, link_prediction=True) number_of_edges = sum([ len(path) - 1 for path in temp_graph.get_paths_for_all_pairs() ]) local_frequencies = temp_graph.edge_frequencies # Check if we really have the right number of edges self.assertEqual(number_of_edges, sum(local_frequencies.values()))
def test_empty_dict_get_frequency_for_path(self): """ Testing (a) Clearing the edge frequencies after instantiation of the graph (b) Check if the return value is None """ path_length = 50 local_current_path_list = [x for x in range(path_length)] factory = graph_edge_factory.VirtualEdgeFactory(distance_threshold=1) graph_edges = factory.generate_deterministic_graph_edges() local_graph = graph.Graph(graph_edges) # Clear the edge_frequencies local_graph.edge_frequencies = {} self.assertEqual( local_graph.add_frequency_for_path(local_current_path_list), None) self.assertEqual(local_graph.edge_frequencies, {(x, x + 1): 1 for x in range(path_length - 1)})
def run_for_specific_source_destination_pair( number_of_source_destination_pairs: int, samples: int, algorithm=None, graph_edges: list = None, distance_threshold: int = None, propagation_radius: int = None, exponential_scale: bool = True, link_prediction: bool = False): results_for_source_destination = [] link_length_dictionary = {} for x in range(1, samples + 1): # If the edges of the graph were not specified, then a random graph was specified if graph_edges is None: factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=distance_threshold) graph_edges = factory.generate_random_power_law_graph_edges() # helper.add_dictionary_to_dictionary(link_length_dictionary, link_lengths) if algorithm == routing_algorithms.local_knowledge_algorithm and propagation_radius is not None: results: tuple = algorithm(graph_edges, number_of_source_destination_pairs, propagation_radius, exponential_scale=exponential_scale) elif algorithm == routing_algorithms.global_knowledge_init: results: tuple = algorithm(graph_edges, number_of_source_destination_pairs, exponential_scale=exponential_scale) else: results: tuple = algorithm(graph_edges, number_of_source_destination_pairs, link_prediction=link_prediction, exponential_scale=exponential_scale) results_for_source_destination.append(results) return results_for_source_destination, link_length_dictionary
def test_sum_of_edges(self): """ Test that it can sum a list of integers """ for x in range(100): max_power = 4 for dth in range(1, max_power + 1): threshold = 2**dth factory = graph_edge_factory.VirtualEdgeFactory( distance_threshold=threshold, max_distance_threshold=2**max_power) graph_edges = factory.generate_random_power_law_graph_edges() # Number of neighbours that are selected by each node k = 1 # Checking if the number of edges is the same as expected sum_of_edges = sum([x[2] for x in graph_edges]) number_of_edges = factory.number_of_nodes + factory.number_of_nodes * k self.assertEqual( sum_of_edges, number_of_edges, "The number of edges is not the expected value.")