From 22415ff7f8ad587526753361085869256e77fd8a Mon Sep 17 00:00:00 2001 From: 21105419 Date: Sat, 3 Feb 2024 15:48:03 +0100 Subject: [PATCH] =?UTF-8?q?API=20d'=C3=A9criture=20d'attaques?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/Attack.py | 62 ++++++++++++++ scripts/Attaques.py | 33 -------- scripts/CityGraph.py | 49 ++++++++--- scripts/Strategies.py | 37 +++++++++ test_attack.txt | 183 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 318 insertions(+), 46 deletions(-) create mode 100644 scripts/Attack.py delete mode 100644 scripts/Attaques.py create mode 100644 scripts/Strategies.py create mode 100644 test_attack.txt diff --git a/scripts/Attack.py b/scripts/Attack.py new file mode 100644 index 00000000..8c8bc8e4 --- /dev/null +++ b/scripts/Attack.py @@ -0,0 +1,62 @@ +import osmnx as ox +import networkx as nx +import random + +from CityGraph import CityGraph + +# Juste pour test pour l'instant +ville="Saints" + +class Attack : + """ + Represents an attack on a graph + --- Attributes --- + graph : the graph to attack (READ-ONLY) + attacks : the attacks to perform + """ + + graph : CityGraph + attacks : list[int] # Format : [time, edge_idx] + + def __init__(self, graph : CityGraph) : + self.graph = graph + self.attacks = [] + + def add_attack(self, time : int, edge_idx : int) -> None : + """Adds an attack to the list""" + self.attacks.append((time, edge_idx)) + + def write_to_file(self, file_path : str) -> None : + """Writes the attacks to a file""" + + # Conversion + edges_deleted : dict[int, set[int]] = {} + for time, edge_idx in self.attacks : + node0 = self.graph.get_node_index(self.graph.get_edge_index(edge_idx)[0]) + node1 = self.graph.get_node_index(self.graph.get_edge_index(edge_idx)[1]) + if (node0, node1) in edges_deleted : + edges_deleted[(node0, node1)].add(time) + else : + edges_deleted[(node0, node1)] = {time} + + # Sorting for easier parsing in the future + for edge in edges_deleted : + edges_deleted[edge] = list(edges_deleted[edge]) + edges_deleted[edge].sort() + + edges_deleted : list[tuple[tuple[int, int], list[int]]] = [((edge[0], edge[1]), edges_deleted[edge]) for edge in edges_deleted] + edges_deleted.sort(key = lambda x : (x[0][0], x[0][1])) + + # Writing + with open(file_path, "w") as file : + file.write(f"{len(edges_deleted)}\n") + for edge, times in edges_deleted : + file.write(f"{edge[0]} {edge[1]} {len(times)} {' '.join(map(str, times))}\n") + + print(f"Attacks have been written to {file_path}") + +def print_suppression_edge(graph : CityGraph, edge_idx : int, time : int): + edge = graph.get_edge_index(edge_idx) + noeud0 = graph.get_node_index(edge[0]) + noeud1 = graph.get_node_index(edge[1]) + print(f"T={time}, suppression de l'arete {edge_idx} entre les noeuds {noeud0} et {noeud1}") \ No newline at end of file diff --git a/scripts/Attaques.py b/scripts/Attaques.py deleted file mode 100644 index f4b19def..00000000 --- a/scripts/Attaques.py +++ /dev/null @@ -1,33 +0,0 @@ -import osmnx as ox -import networkx as nx -import random - -from CityGraph import CityGraph - -# Juste pour test pour l'instant -ville="Saints" - -def format_suppression_edge(graph : CityGraph, edge_idx : int, time : int) -> str : - edge = graph.get_edge_index(edge_idx) - noeud0 = graph.get_node_index(edge[0]) - noeud1 = graph.get_node_index(edge[1]) - return f"T={time}, suppression de l'arete {edge_idx} entre les noeuds {noeud0} et {noeud1}" - -def random_attack(graph : CityGraph, nbTemps : int, budget : int, output_file : str) -> None : - """A chaque temps, on supprime budget liens choisis aleatoirement""" - - assert budget <= graph.size() - - # TODO : ecriture dans le fichier - edges = list(graph.edges()) - for i in range(nbTemps) : - for j in range(budget) : - edge_idx = random.randint(0, len(edges)-1) - print(format_suppression_edge(graph, edge_idx, i)) - - -graph = CityGraph(ville) -graph.print_stats() -graph.show() - -random_attack(graph, 10, 5, "test.txt") \ No newline at end of file diff --git a/scripts/CityGraph.py b/scripts/CityGraph.py index 9bbf9dcb..d4a141f6 100644 --- a/scripts/CityGraph.py +++ b/scripts/CityGraph.py @@ -5,47 +5,70 @@ class CityGraph : """ Represents a graph of a city, with some useful methods --- Attributes --- - city : name of the city + city_name : name of the city graph : the graph itself - nodes : a dict that maps a node to its index in the graph + nodes_idx_map : a dict that maps a node to its index in the graph projected_graph : the graph projected on a plane """ - city : str + city_name : str graph : nx.Graph - nodes : dict[int, int] + nodes_idx_map : dict[int, int] projected_graph : nx.Graph = None - def __init__(self, city : str, network_type : str = "drive") : + def __init__(self, city_name : str, network_type : str = "drive") : """Loads a graph from OSmnx through its name""" - self.city = city - self.graph = ox.graph_from_place(city, network_type=network_type) - self.nodes = { edge : i for i, edge in enumerate(self.graph.nodes())} + ox.settings.osm_xml_way_tags=["highway", "lanes"] + self.city_name = city_name + self.graph = ox.graph_from_place(city_name, network_type=network_type) + #Load the graph with the number of lanes too + self.graph = ox.graph_from_place(city_name, network_type=network_type) - def get_node_index(self, node : int) : - return self.nodes[node] + self.nodes_idx_map = { edge : i for i, edge in enumerate(self.graph.nodes())} - def get_node(self, index : int) : - return self.nodes[index] + def get_node_index(self, node : int) : + """Returns the index in the matrix of the node through it's OSmnx numero""" + return self.nodes_idx_map[node] def show(self) : + """Opens an image of the graph""" ox.plot_graph(self.graph) def print_stats(self) : + """Prints some stats about the graph""" print(ox.basic_stats(self.graph)) def get_projected_graph(self) : + """Returns the projected graph""" if self.projected_graph is None : self.projected_graph = ox.project_graph(self.graph) return self.projected_graph def edges(self) : + """Returns the edges of the graph""" return self.graph.edges() - def size(self) : + def nb_nodes(self) : + """Returns the number of nodes in the graph""" return self.graph.size() + def nb_edges(self) : + """Returns the number of edges in the graph""" + return self.graph.number_of_edges() + def get_edge_index(self, edge_idx : int) : + """Accesses an edge through its index""" return list(self.graph.edges())[edge_idx] + + # TODO : ca marche pas + def get_nb_lanes_of_edge(self, edge_idx : int) -> int: + """Returns the number of lanes of an edge""" + #edges = ox.graph_to_gdfs(self.graph, nodes=False, edges=True) + #print(edges.columns) + #lanes = edges["lanes"] + #for (u, v, d) in self.graph.edges(data=True): + #print(d) + #print(lanes) + return self.graph.get_edge_data(*self.get_edge_index(edge_idx), key="lanes") @staticmethod def read_from_file(file_path : str) : diff --git a/scripts/Strategies.py b/scripts/Strategies.py new file mode 100644 index 00000000..2cd862f3 --- /dev/null +++ b/scripts/Strategies.py @@ -0,0 +1,37 @@ +import osmnx as ox +import networkx as nx +import random + +from CityGraph import CityGraph +from Attack import Attack, print_suppression_edge + +# Juste pour test pour l'instant +ville="Saints" + +def random_attack(graph : CityGraph, nbTemps : int, budget : int) -> Attack : + """A chaque temps, on supprime budget liens choisis aleatoirement""" + + attacks = Attack(graph) + edges = list(graph.edges()) + + for i in range(nbTemps) : + edges_t = edges.copy() + budget_used : int = 0 + nb_retires : int = 0 + while budget_used < budget : + edge_idx = random.randint(0, graph.nb_edges() - 1 - nb_retires) + # print_suppression_edge(graph, edge_idx, i) + attacks.add_attack(i, edge_idx) + edges_t.pop(edge_idx) + nb_retires += 1 + budget_used += 1 #graph.get_nb_lanes_of_edge(edge_idx) + + return attacks + + +graph = CityGraph(ville) +graph.print_stats() +graph.show() + +a = random_attack(graph, 50, 50) +a.write_to_file("test_attack.txt") \ No newline at end of file diff --git a/test_attack.txt b/test_attack.txt new file mode 100644 index 00000000..47053334 --- /dev/null +++ b/test_attack.txt @@ -0,0 +1,183 @@ +182 +0 1 11 2 4 18 20 25 28 34 38 39 42 44 +0 5 15 1 2 4 7 11 14 21 22 24 28 30 33 39 45 48 +1 20 18 3 9 10 13 15 18 19 21 22 25 33 34 36 39 41 44 45 48 +2 3 15 3 4 8 11 12 15 16 21 25 26 33 37 43 45 48 +2 7 12 9 11 22 28 37 41 42 43 44 45 47 48 +3 4 7 11 14 15 41 46 47 49 +5 1 16 6 9 13 15 24 25 27 33 34 37 39 40 43 45 47 48 +5 30 18 0 5 7 8 10 11 13 14 18 19 22 23 33 34 37 40 41 49 +6 63 20 0 1 2 5 6 14 16 20 24 25 27 28 29 32 34 36 40 42 45 47 +7 3 12 1 11 12 14 23 29 33 37 39 41 47 48 +8 15 12 1 7 15 17 22 23 28 30 31 33 47 49 +8 26 9 2 4 7 8 20 21 29 45 48 +8 31 11 4 5 8 10 13 23 24 32 35 40 41 +9 26 19 0 1 9 10 13 15 16 18 20 22 23 24 27 28 32 35 38 47 48 +9 60 10 0 2 6 9 13 16 24 35 44 49 +9 61 13 1 3 6 15 16 17 19 20 29 30 35 39 48 +10 23 13 9 12 16 18 23 31 32 33 34 35 36 42 47 +10 33 14 1 3 4 5 8 14 17 19 24 26 32 37 38 44 +10 42 15 0 2 6 8 9 13 16 17 26 27 31 32 35 36 40 +11 12 12 0 4 9 14 16 27 30 37 38 41 44 47 +11 50 8 0 13 15 21 30 37 38 42 +12 11 9 11 20 21 26 32 38 39 42 48 +12 13 14 5 7 10 11 14 15 18 27 28 33 35 39 42 46 +12 55 11 1 4 9 16 22 29 35 37 41 46 49 +13 12 21 0 2 6 8 9 10 12 17 18 19 20 22 24 27 28 30 33 36 39 46 49 +13 14 17 2 3 4 8 10 17 18 20 21 25 27 31 38 41 44 46 49 +13 55 18 4 6 10 11 12 13 15 18 19 24 26 27 34 40 43 45 47 49 +14 13 15 0 2 7 8 10 11 12 21 25 29 30 31 37 38 48 +14 51 14 1 2 4 5 14 17 22 25 26 27 37 38 39 44 +14 56 12 2 5 17 20 21 24 25 28 29 34 37 41 +15 8 6 5 24 31 36 39 48 +15 16 14 3 4 9 11 13 18 23 26 30 32 40 41 45 46 +15 82 13 0 2 3 6 10 14 22 23 28 30 35 36 38 +16 15 13 1 2 7 10 17 21 26 29 30 32 34 40 43 +16 17 9 1 6 7 11 19 21 27 34 35 +16 57 13 0 4 5 6 15 24 28 29 40 41 44 46 47 +17 16 15 2 3 4 8 10 25 27 28 29 36 40 42 46 48 49 +17 26 14 5 6 12 13 16 19 23 33 34 35 41 44 46 49 +17 61 5 0 22 26 37 43 +18 19 16 0 5 10 11 14 15 18 19 20 23 31 35 36 40 43 48 +18 36 12 1 8 10 22 27 34 35 39 40 42 45 47 +19 18 17 1 4 5 7 11 14 27 29 30 31 32 33 35 36 42 43 48 +19 75 10 16 21 25 29 32 35 43 46 47 49 +20 19 14 0 1 6 8 10 11 12 18 20 24 30 31 33 45 +20 75 14 2 5 6 7 17 22 26 27 28 29 32 34 42 47 +21 48 16 0 6 11 12 14 22 25 28 30 31 37 40 41 42 44 46 +21 50 9 2 3 11 19 25 29 30 39 44 +22 23 12 5 12 15 18 21 24 26 27 31 38 40 41 +22 39 12 0 2 10 12 13 18 20 23 32 35 40 41 +22 45 15 1 4 5 8 15 18 22 24 25 30 31 40 42 44 47 +23 10 12 0 4 8 12 16 17 29 36 44 46 48 49 +23 22 12 2 3 7 17 19 25 26 31 32 37 45 48 +23 60 12 0 4 10 15 21 23 24 27 28 31 37 39 +24 25 16 6 10 15 16 19 20 21 25 30 34 36 38 42 43 44 46 +24 40 17 0 2 6 7 8 12 16 19 23 29 36 38 41 42 43 44 47 +25 24 16 5 8 9 13 15 18 22 24 25 26 28 31 32 35 42 46 +25 37 9 7 8 17 19 20 32 39 48 49 +25 81 10 10 11 12 21 27 34 36 37 39 45 +26 8 18 2 5 7 11 16 18 20 22 24 25 30 33 35 36 37 43 44 49 +26 9 13 3 6 18 19 24 27 32 33 34 36 43 46 49 +26 17 12 1 2 6 11 12 17 18 38 39 43 46 47 +27 28 13 2 7 8 11 19 22 23 24 26 30 33 42 47 +27 67 8 16 27 32 37 42 43 45 47 +28 27 11 13 19 20 21 23 24 26 28 29 30 45 +28 29 14 2 9 10 11 13 14 16 19 27 28 31 39 42 45 +28 73 13 1 5 7 14 15 29 30 31 32 41 43 44 47 +29 28 17 1 2 3 4 7 8 14 15 25 26 27 28 33 38 39 41 49 +29 30 13 2 3 10 19 24 25 27 28 31 32 38 39 44 +30 5 17 1 2 5 7 8 12 13 21 33 37 38 39 41 43 44 45 48 +30 29 16 2 5 8 9 14 17 21 22 23 25 26 36 42 43 44 48 +30 63 14 1 7 8 9 11 21 23 25 26 33 35 37 45 47 +31 8 13 1 5 6 13 15 17 23 26 31 34 41 48 49 +31 32 14 0 1 17 18 20 21 23 24 32 33 39 41 43 46 +31 37 11 6 7 13 16 18 28 30 32 35 45 49 +32 31 15 11 12 13 14 15 18 21 22 26 34 37 38 39 44 45 +32 34 13 1 4 13 21 23 26 30 35 40 41 43 44 46 +32 62 9 3 18 21 23 25 37 43 48 49 +33 10 17 0 3 7 17 19 23 25 27 28 32 38 40 42 43 45 47 49 +33 41 15 7 9 10 16 24 27 30 31 33 35 36 43 44 46 48 +34 32 13 1 2 12 15 19 21 23 24 26 30 40 41 49 +34 35 14 0 7 8 10 15 20 24 30 32 37 39 41 43 46 +35 34 13 11 15 16 19 26 28 30 33 40 42 45 47 49 +35 36 14 0 2 3 8 13 16 17 20 26 28 33 34 36 40 +35 65 17 7 11 12 17 20 21 22 25 27 29 30 31 34 39 42 45 49 +36 18 12 3 4 8 11 18 20 23 24 28 32 37 44 +36 35 14 1 3 6 10 14 17 23 24 25 31 34 35 39 43 +36 70 14 8 10 13 19 20 21 22 25 28 30 32 35 37 46 +37 25 11 3 10 11 17 21 31 34 41 43 44 49 +37 31 17 1 4 8 16 18 19 20 24 25 28 30 31 32 35 37 38 47 +38 39 12 6 10 22 23 29 30 32 33 34 36 42 48 +38 43 7 19 20 24 30 33 35 39 +38 47 18 0 1 4 6 15 16 20 22 24 30 33 34 36 39 42 44 45 48 +39 22 12 0 3 6 8 10 27 33 35 36 38 39 40 +39 38 13 3 4 8 11 13 19 29 32 42 44 45 46 48 +39 76 15 4 5 7 14 17 19 24 25 26 29 33 34 37 40 46 +40 24 8 0 1 3 19 26 31 33 40 +41 33 17 0 1 6 8 13 21 22 26 29 31 32 35 36 41 43 45 48 +42 10 14 3 4 5 8 14 17 20 22 31 40 43 45 48 49 +42 42 22 5 6 8 10 12 13 16 19 22 25 27 28 29 30 34 36 37 39 42 43 44 49 +43 38 15 12 13 19 20 21 22 25 26 29 38 39 40 41 45 46 +44 46 16 2 3 5 9 13 14 20 22 27 28 29 30 32 39 43 48 +44 48 15 0 10 16 17 19 22 25 29 31 35 38 40 42 46 49 +44 56 14 8 10 13 18 19 21 22 23 26 29 38 40 43 48 +45 22 15 2 4 7 12 13 18 21 24 27 30 31 33 35 43 47 +45 46 11 1 4 9 10 13 23 24 38 45 47 49 +45 53 12 12 17 18 21 23 26 31 33 34 37 40 48 +46 44 15 2 3 5 6 9 18 27 28 30 37 38 40 45 46 47 +46 45 19 2 3 6 8 10 12 14 15 16 18 19 26 27 35 37 40 43 45 46 +46 53 9 5 6 7 11 14 21 31 32 42 +47 38 14 2 7 13 14 16 17 18 20 29 33 34 39 40 44 +48 21 10 1 25 27 29 31 36 41 44 45 48 +48 44 9 6 7 9 15 17 29 31 36 43 +48 51 9 1 5 8 12 14 24 31 42 45 +49 51 11 18 23 25 28 29 38 39 42 46 47 49 +50 11 18 0 1 3 4 7 9 12 14 20 26 27 34 38 40 41 43 47 49 +50 21 22 1 2 3 8 11 14 16 20 24 27 28 29 31 36 37 39 41 42 43 45 48 49 +50 55 15 2 7 12 15 17 22 25 26 29 30 33 34 40 44 46 +51 14 11 0 18 20 22 24 25 28 37 42 44 47 +51 48 13 0 1 4 10 12 15 25 29 34 41 42 43 46 +51 49 11 7 11 13 15 16 21 29 38 44 45 46 +51 52 16 1 6 8 9 14 20 23 25 26 27 30 32 38 41 42 47 +52 51 14 3 5 9 15 18 22 23 27 35 37 41 42 47 49 +53 45 19 0 1 4 7 8 9 12 16 17 22 27 31 32 34 36 37 43 46 48 +53 46 13 4 9 10 22 23 26 28 32 35 36 40 42 44 +53 54 16 3 5 7 10 12 22 28 29 33 34 36 41 43 44 45 49 +54 53 11 0 5 12 24 29 33 36 39 46 48 49 +55 12 19 0 3 4 6 9 14 15 19 20 22 23 26 27 34 35 36 41 44 45 +55 13 12 1 11 13 15 16 17 19 20 37 39 41 46 +55 50 12 0 9 10 18 20 23 25 28 29 30 41 44 +56 14 14 5 6 14 16 22 23 26 27 28 29 36 37 46 48 +56 44 13 0 1 5 17 18 22 23 26 32 33 46 47 49 +56 80 13 1 3 6 8 13 17 19 21 23 24 38 39 42 +57 16 16 3 5 9 15 16 17 18 20 21 30 33 35 42 43 45 47 +57 59 16 4 7 9 11 13 18 19 30 32 36 38 40 45 46 47 48 +57 68 12 2 3 4 5 9 14 15 17 19 30 45 49 +58 59 14 4 10 16 17 18 20 23 24 35 37 44 45 47 49 +59 57 11 5 7 9 11 13 19 22 26 34 35 37 +59 58 14 0 1 3 11 12 19 20 26 28 30 31 32 39 43 +59 60 16 8 9 10 11 12 14 20 22 24 25 28 35 37 42 46 48 +60 9 12 4 15 17 24 25 38 41 42 44 45 46 47 +60 23 10 9 11 27 29 31 33 35 39 44 46 +60 59 15 0 2 9 14 21 22 25 26 31 34 36 38 39 44 48 +61 9 9 4 7 15 17 20 25 30 31 32 +61 17 15 3 9 10 11 12 13 16 18 20 31 33 40 47 48 49 +61 69 9 8 14 18 19 27 32 35 47 49 +62 32 18 0 1 3 5 11 12 17 28 31 32 34 36 40 43 45 46 47 49 +63 6 8 0 7 20 21 22 31 33 37 +63 30 5 2 12 37 41 48 +63 71 9 3 10 13 25 26 29 36 37 39 +64 65 15 0 6 7 13 14 16 21 25 27 34 36 37 38 44 49 +65 35 12 1 9 10 13 15 17 18 26 30 32 35 38 +65 64 12 3 6 7 14 15 19 23 25 31 39 40 46 +65 66 8 4 5 12 21 23 38 44 49 +66 65 11 8 11 13 15 16 17 18 21 27 36 46 +67 27 7 7 9 13 15 29 32 40 +68 57 7 3 10 14 16 40 42 43 +69 61 5 3 11 39 42 45 +70 36 11 0 5 11 12 16 19 23 24 30 39 41 +71 63 9 5 8 12 15 33 34 36 38 48 +71 72 3 14 24 49 +71 73 9 0 3 4 5 9 14 19 37 43 +72 71 5 3 28 35 38 40 +72 73 3 14 24 38 +72 74 5 7 14 30 36 48 +73 28 3 18 33 47 +73 71 4 9 13 38 43 +73 72 3 0 4 8 +74 72 4 1 4 37 38 +75 2 4 14 17 19 38 +76 39 5 12 14 20 27 39 +76 77 2 17 34 +77 76 5 1 4 17 34 45 +77 78 4 4 10 25 36 +77 79 1 42 +78 77 2 23 35 +79 77 2 2 35 +80 56 2 5 10 +80 82 1 17 +81 25 1 24 +81 80 1 1 +82 15 1 36 +82 81 1 19