Skip to content

Commit

Permalink
new strategy : sorted by a criteria
Browse files Browse the repository at this point in the history
  • Loading branch information
Fur0rem committed Feb 4, 2024
1 parent 84377e8 commit 57dcfef
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 197 deletions.
6 changes: 3 additions & 3 deletions scripts/Attack.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ def write_to_file(self, file_path : str) -> None :
# 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])
node0 = self.graph.get_node_index(self.graph.get_edge_at(edge_idx)[0])
node1 = self.graph.get_node_index(self.graph.get_edge_at(edge_idx)[1])
if (node0, node1) in edges_deleted :
edges_deleted[(node0, node1)].add(time)
else :
Expand All @@ -56,7 +56,7 @@ def write_to_file(self, file_path : str) -> None :
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)
edge = graph.get_edge_at(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}")
20 changes: 19 additions & 1 deletion scripts/CityGraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class CityGraph :
nodes_idx_map : dict[int, int]
projected_graph : nx.Graph = None
lanes_data : list[int] = None
betweenness_centralities : list[float] = None

def __init__(self, city_name : str, network_type : str = "drive") :
"""Loads a graph from OSmnx through its name"""
Expand Down Expand Up @@ -49,6 +50,12 @@ def get_lanes_data(self) :
self.lanes_data = lanes_data

return self.lanes_data

def get_betweenness_centralities(self) :
"""Returns the betweenness centralities of each edge"""
if self.betweenness_centralities is None :
self.betweenness_centralities = nx.edge_betweenness_centrality(self.get_projected_graph())
return self.betweenness_centralities

def get_projected_graph(self) :
"""Returns the projected graph"""
Expand All @@ -68,14 +75,25 @@ 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) :
def get_edge_at(self, edge_idx : int) :
"""Accesses an edge through its index"""
return list(self.graph.edges())[edge_idx]

def get_nb_lanes_of_edge(self, edge_idx : int) -> int:
"""Returns the number of lanes of an edge"""
edges = self.get_lanes_data()
return edges[edge_idx]

def get_edge_betweenness_centrality(self, edge_idx : int) -> float:
"""Returns the betweenness centrality of an edge"""
edges = self.get_betweenness_centralities()
edge = self.get_edge_at(edge_idx)
edge = (edge[0], edge[1], 0) # keys are tuples with a third 0 for some reason
return edges[edge]

def find_edge_index(self, node0 : int, node1 : int) -> int:
"""Returns the index of an edge through its nodes"""
return list(self.graph.edges()).index((node0, node1))

@staticmethod
def read_from_file(file_path : str) :
Expand Down
66 changes: 54 additions & 12 deletions scripts/Strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,71 @@
ville="Saints"

def random_attack(graph : CityGraph, nbTemps : int, budget : int) -> Attack :
"""A chaque temps, on supprime budget liens choisis aleatoirement"""
"""Each time, it removes a random edge from the graph until the budget is reached or no more edges are available"""

attacks = Attack(graph)
edges = list(graph.edges())

for i in range(nbTemps) :
for time 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)
budget_used = 0
nb_retires = 0
while budget_used < budget and len(edges_t) > 0 :
edge_idx = random.randint(0, graph.nb_edges() - (nb_retires + 1))
cost = graph.get_nb_lanes_of_edge(edge_idx)
if cost <= budget - budget_used :
attacks.add_attack(time, edge_idx)
budget_used += cost
nb_retires += 1
edges_t.pop(edge_idx)
nb_retires += 1
budget_used += 1 + graph.get_nb_lanes_of_edge(edge_idx)

return attacks


def sorted_attack(graph : CityGraph, nbTemps : int, budget : int, sort_by : callable) -> Attack :
"""Each time, it removes the edge that is the most affected by the sort_by function until the budget is reached or no more edges are available"""

attacks = Attack(graph)
edges = list(graph.edges())
for i, edge in enumerate(edges) :
edges[i] = graph.find_edge_index(edge[0], edge[1])
edges.sort(key = sort_by, reverse = True)

for time in range(nbTemps) :
edges_t = edges.copy()
budget_used = 0
nb_retires = 0
while budget_used < budget and len(edges_t) > 0 :
edge_idx = edges_t.pop(0)
cost = graph.get_nb_lanes_of_edge(edge_idx)
if cost <= budget - budget_used :
attacks.add_attack(time, edge_idx)
budget_used += cost
nb_retires += 1
edges_t.pop(edge_idx)

return attacks

def min_lanes_attack(graph : CityGraph, nbTemps : int, budget : int) -> Attack :
"""Each time, it removes the edge with the least lanes until the budget is reached or no more edges are available"""
return sorted_attack(graph, nbTemps, budget, lambda x : -graph.get_nb_lanes_of_edge(x))

def max_lanes_attack(graph : CityGraph, nbTemps : int, budget : int) -> Attack :
"""Each time, it removes the edge with the most lanes until the budget is reached or no more edges are available"""
return sorted_attack(graph, nbTemps, budget, lambda x : graph.get_nb_lanes_of_edge(x))

def betweenness_centralities_attack(graph : CityGraph, nbTemps : int, budget : int) -> Attack :
"""Each time, it removes the edge with the highest betweenness centrality until the budget is reached or no more edges are available"""
return sorted_attack(graph, nbTemps, budget, lambda x : graph.get_edge_betweenness_centrality(x))

graph = CityGraph(ville)
graph.print_stats()
graph.show()

a = random_attack(graph, 50, 50)
a.write_to_file("test_attack.txt")
a.write_to_file("test_random_attack.txt")
a = min_lanes_attack(graph, 10, 10)
a.write_to_file("test_min_lanes_attack.txt")
a = max_lanes_attack(graph, 10, 10)
a.write_to_file("test_max_lanes_attack.txt")
a = betweenness_centralities_attack(graph, 10, 10)
a.write_to_file("test_betweenness_centralities_attack.txt")
181 changes: 0 additions & 181 deletions test_attack.txt

This file was deleted.

11 changes: 11 additions & 0 deletions test_betweenness_centralities_attack.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
10
1 20 10 0 1 2 3 4 5 6 7 8 9
5 1 10 0 1 2 3 4 5 6 7 8 9
18 36 10 0 1 2 3 4 5 6 7 8 9
19 18 10 0 1 2 3 4 5 6 7 8 9
20 19 10 0 1 2 3 4 5 6 7 8 9
31 8 10 0 1 2 3 4 5 6 7 8 9
32 31 10 0 1 2 3 4 5 6 7 8 9
34 32 10 0 1 2 3 4 5 6 7 8 9
35 34 10 0 1 2 3 4 5 6 7 8 9
36 35 10 0 1 2 3 4 5 6 7 8 9
6 changes: 6 additions & 0 deletions test_max_lanes_attack.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
5
11 50 10 0 1 2 3 4 5 6 7 8 9
21 48 10 0 1 2 3 4 5 6 7 8 9
21 50 10 0 1 2 3 4 5 6 7 8 9
22 39 10 0 1 2 3 4 5 6 7 8 9
22 45 10 0 1 2 3 4 5 6 7 8 9
11 changes: 11 additions & 0 deletions test_min_lanes_attack.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
10
0 5 10 0 1 2 3 4 5 6 7 8 9
1 20 10 0 1 2 3 4 5 6 7 8 9
2 3 10 0 1 2 3 4 5 6 7 8 9
2 7 10 0 1 2 3 4 5 6 7 8 9
5 1 10 0 1 2 3 4 5 6 7 8 9
5 30 10 0 1 2 3 4 5 6 7 8 9
7 3 10 0 1 2 3 4 5 6 7 8 9
8 15 10 0 1 2 3 4 5 6 7 8 9
8 31 10 0 1 2 3 4 5 6 7 8 9
9 26 10 0 1 2 3 4 5 6 7 8 9
Loading

0 comments on commit 57dcfef

Please sign in to comment.