Skip to content

Commit 2315421

Browse files
committed
Reorganisation + function to generate graphs without cycles + division of modules in multiples files.
1 parent 307696f commit 2315421

10 files changed

Lines changed: 127 additions & 97 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Pierre BRUOT et Maxime BLANCHON
22
# Théorie des graphes
33

4-
### [TP1 : Implantation d'algorithmes en Python](tp1/TP1.md)
5-
### [TP2 : Algorithmes dans les graphes sans circuits](tp2/TP2.md)
4+
### [TP1 : Implantation d'algorithmes en Python](reports/TP1.md)
5+
### [TP2 : Algorithmes dans les graphes sans circuits](reports/TP2.md)
File renamed without changes.
File renamed without changes.

tp1/TP1.md renamed to reports/TP1.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,26 +183,26 @@ Fin génèreGraph
183183

184184
Cette fonction permet de tester les performances en exécutant n fois chaque algorithme avec des graphs aléatoires dont la taille augmente progressivement de a à b, b non compris.
185185

186-
Exemple ci-dessous, avec n = 1000, a = 1, b = 21 (la taille des graphs générés varie de 1 à 20)
186+
Exemple ci-dessous, avec n = 1000, a = 1, b = 101 (la taille des graphs générés varie de 1 à 100)
187187

188-
![Figure1](/tp1/figure1.png?raw=true)
188+
![Figure1](../figures/figure1.png?raw=true)
189189

190190
On peut voir sur le diagramme ci-dessous que l'algorithme le plus efficace est Roy-Warshall 2 (environ 2 fois plus efficace que Roy-Warshall 1).
191191
On remarque également que Roy-Warshall 1 Bis est l'implémentation la moins efficace.
192192

193193
Cependant, si on zoome dans le diagramme, on peut voir que Roy-Warshall 1 bis est très légèrement plus efficace que Roy-Warshall 1 pour des graphs avec des sommets allant de 1 à 7/8.
194194

195-
![Figure2](/tp1/figure2.png?raw=true)
195+
![Figure2](../figures/figure2.png?raw=true)
196196

197-
Le diagramme peut être visualisé en exécutant les commandes suivantes dans un terminal (sur Linux) :
197+
Le diagramme peut être visualisé en exécutant les commandes suivantes dans un terminal à l'intérieur du dossier racine (sur Linux) :
198198

199199
```bash
200200
python3 -m venv venv # création d'un environnement virtuel pour installer la bibliothèque matplotlib
201201
source venv/bin/activate # activation de l'environnement virtuel
202202
pip3 install matplotlib # installation de la bibliothèque Python matplotlib
203-
python3 tp1/src/graph.py # exécution du script Python qui génère les diagrammes
203+
python3 -m src.tp1 # exécution du script Python qui génère les diagrammes
204204
```
205-
Les paramètres d'exécution peuvent être modifiées au début du fichier `tp1/src/graph.py` :
205+
Les paramètres d'exécution peuvent être modifiées au début du fichier `src/tp1.py` :
206206

207207
```python
208208
def main() -> None:
File renamed without changes.

src/__init__.py

Whitespace-only changes.

src/performance.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from statistics import mean
2+
from timeit import default_timer
3+
4+
from src.utils import generate_adjacency_list
5+
6+
7+
def get_exec_time(function, *args) -> float:
8+
start = default_timer()
9+
function(*args)
10+
return default_timer() - start
11+
12+
13+
def get_n_exec_time(algorithm, n, size) -> int:
14+
exec_times = []
15+
16+
for i in range(n):
17+
adjacency_list = generate_adjacency_list(size)
18+
exec_times.append(get_exec_time(algorithm, adjacency_list))
19+
20+
return mean(exec_times) * 10 ** 6 # Convert seconds to microseconds

tp1/src/graph.py renamed to src/tp1.py

Lines changed: 10 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import sys
2-
from timeit import default_timer
32
from typing import List, Tuple
4-
from random import randrange, sample
5-
from statistics import mean
3+
64
import matplotlib.pyplot as plt
75

6+
from src.performance import get_n_exec_time
7+
from src.utils import adjacency_list_to_adjacency_matrix
8+
89
""" ---------- Plot Roy Warshall exec times ---------- """
910

1011

@@ -43,35 +44,16 @@ def main() -> None:
4344
plt.show()
4445

4546

46-
""" ---------- Performance Tests ---------- """
47-
48-
49-
def get_exec_time(function, *args):
50-
start = default_timer()
51-
function(*args)
52-
return default_timer() - start
53-
54-
55-
def get_n_exec_time(algorithm, n, size):
56-
exec_times = []
57-
58-
for i in range(n):
59-
adjacency_list = generate_adjacency_list(size)
60-
exec_times.append(get_exec_time(algorithm, adjacency_list))
61-
62-
return mean(exec_times) * 10 ** 6 # Convert seconds to microseconds
63-
64-
6547
""" ---------- Roy Warshall Algorithm ---------- """
6648

6749

6850
def roy_warshall_1(adjacency_list: List[List[int]]) -> List[List[int]]:
6951
# here we convert the adjacency list to an adjacency matrix
7052
matrix = adjacency_list_to_adjacency_matrix(adjacency_list)
7153
vertices_number = len(adjacency_list)
72-
for k in range(0, vertices_number):
73-
for i in range(0, vertices_number):
74-
for j in range(0, vertices_number):
54+
for k in range(vertices_number):
55+
for i in range(vertices_number):
56+
for j in range(vertices_number):
7557
matrix[i][j] = matrix[i][j] or (matrix[i][k] and matrix[k][j])
7658

7759
return matrix
@@ -80,10 +62,10 @@ def roy_warshall_1(adjacency_list: List[List[int]]) -> List[List[int]]:
8062
# Another implementation of Roy Warshall's algorithm, more efficient than roy_warshall_1
8163
def roy_warshall_1_bis(adjacency_list: List[List[int]]) -> List[List[int]]:
8264
matrix = adjacency_list_to_adjacency_matrix(adjacency_list)
83-
for i in range(0, len(matrix)):
84-
for j in range(0, len(matrix[i])):
65+
for i in range(len(matrix)):
66+
for j in range(len(matrix[i])):
8567
if matrix[i][j] == 1:
86-
for x in range(0, len(matrix[j])):
68+
for x in range(len(matrix[j])):
8769
if matrix[j][x] == 1:
8870
matrix[i][x] = matrix[j][x]
8971
return matrix
@@ -154,64 +136,5 @@ def _depth_first_search(vertex: int, glob_index: int):
154136
return res_visit_stack, scc
155137

156138

157-
""" ---------- Utility functions ---------- """
158-
159-
160-
def generate_adjacency_list(vertices_number):
161-
adjacency_list = [[] for i in range(vertices_number)]
162-
163-
for i in range(vertices_number):
164-
# actual vertex can be linked to itself
165-
successors_number = randrange(vertices_number + 1)
166-
adjacency_list[i].extend(sample(range(vertices_number), successors_number))
167-
168-
return adjacency_list
169-
170-
171-
def adjacency_list_to_adjacency_matrix(adjacency_list: List[List[int]]) -> List[List[int]]:
172-
vertices_number = len(adjacency_list)
173-
matrix = [[0 for x in range(vertices_number)] for x in range(vertices_number)]
174-
175-
for i in range(0, len(adjacency_list)):
176-
for j in range(0, len(adjacency_list[i])):
177-
matrix[i][adjacency_list[i][j]] = 1
178-
179-
return matrix
180-
181-
182-
def transpose_adjacency_list(adjacency_list: List[List[int]]) -> List[List[int]]:
183-
vertices_number = len(adjacency_list)
184-
transposed_adjacency_list = [[] for i in range(vertices_number)]
185-
186-
for i in range(vertices_number):
187-
for j in range(len(adjacency_list[i])):
188-
transposed_adjacency_list[adjacency_list[i][j]].append(i)
189-
190-
return transposed_adjacency_list
191-
192-
193-
def print_matrix(matrix: List[List[int]]) -> None:
194-
print(' ', end='')
195-
for i in range(0, len(matrix)):
196-
print(i, end=' ')
197-
198-
print('\n', end='')
199-
print(' ', end='')
200-
201-
for i in range(0, len(matrix)):
202-
print('_', end=' ')
203-
204-
print('\n', end='')
205-
206-
i = 0
207-
for row in matrix:
208-
print('{} |'.format(i), end=' ')
209-
for val in row:
210-
print(val, end=' ')
211-
print('\n', end='')
212-
i += 1
213-
print('')
214-
215-
216139
if __name__ == "__main__":
217140
main()

tp2/src/main.py renamed to src/tp2.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
from operator import itemgetter
22
from typing import List
33

4+
from src.utils import print_adjacency_matrix_csv, adjacency_list_to_adjacency_matrix, \
5+
generate_adjacency_list_without_cycles
6+
47

58
def main():
69
# graph = [[1, 2], [2], [3], [4], []]
7-
graph = [[1, 2], [2], [3], [4, 5], [], [6], []]
8-
print(grundy(graph))
10+
# graph = [[1, 2], [2], [3], [4, 5], [], [6], []]
11+
# print(grundy(graph))
12+
13+
for i in range(1):
14+
print_adjacency_matrix_csv(adjacency_list_to_adjacency_matrix(generate_adjacency_list_without_cycles(8)))
15+
16+
# print(adjacency_list_to_adjacency_matrix(generate_adjacency_list_without_cycles(5)))
917

1018

1119
def leveling(adjacency_list: List[List[int]]) -> List[int]:

src/utils.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from random import randrange, sample
2+
from typing import List
3+
4+
5+
def generate_adjacency_list(vertices_number: int) -> List[List[int]]:
6+
adjacency_list = [[] for i in range(vertices_number)]
7+
8+
for i in range(vertices_number):
9+
# actual vertex can be linked to itself
10+
successors_number = randrange(vertices_number + 1)
11+
adjacency_list[i].extend(sample(range(vertices_number), successors_number))
12+
13+
return adjacency_list
14+
15+
16+
def generate_adjacency_list_without_cycles(vertices_number: int) -> List[List[int]]:
17+
adjacency_list = [[] for i in range(vertices_number)]
18+
19+
for i in range(vertices_number):
20+
successors_number = randrange(vertices_number - i)
21+
adjacency_list[i].extend(sample(range(i + 1, vertices_number), successors_number))
22+
23+
return adjacency_list
24+
25+
26+
def print_adjacency_matrix_csv(adjacency_matrix: List[List[int]]) -> None:
27+
vertices_number = len(adjacency_matrix)
28+
for i in range(vertices_number):
29+
for j in range(vertices_number):
30+
print(adjacency_matrix[i][j], end='')
31+
if j != (vertices_number - 1):
32+
print(', ', end='')
33+
print('\n', end='')
34+
print('\n', end='')
35+
36+
37+
def adjacency_list_to_adjacency_matrix(adjacency_list: List[List[int]]) -> List[List[int]]:
38+
vertices_number = len(adjacency_list)
39+
matrix = [[0 for x in range(vertices_number)] for x in range(vertices_number)]
40+
41+
for i in range(len(adjacency_list)):
42+
for j in range(len(adjacency_list[i])):
43+
matrix[i][adjacency_list[i][j]] = 1
44+
45+
return matrix
46+
47+
48+
def transpose_adjacency_list(adjacency_list: List[List[int]]) -> List[List[int]]:
49+
vertices_number = len(adjacency_list)
50+
transposed_adjacency_list = [[] for i in range(vertices_number)]
51+
52+
for i in range(vertices_number):
53+
for j in range(len(adjacency_list[i])):
54+
transposed_adjacency_list[adjacency_list[i][j]].append(i)
55+
56+
return transposed_adjacency_list
57+
58+
59+
def print_adjacency_matrix(adjacency_matrix: List[List[int]]) -> None:
60+
print(' ', end='')
61+
for i in range(len(adjacency_matrix)):
62+
print(i, end=' ')
63+
64+
print('\n', end='')
65+
print(' ', end='')
66+
67+
for i in range(len(adjacency_matrix)):
68+
print('_', end=' ')
69+
70+
print('\n', end='')
71+
72+
i = 0
73+
for row in adjacency_matrix:
74+
print('{} |'.format(i), end=' ')
75+
for val in row:
76+
print(val, end=' ')
77+
print('\n', end='')
78+
i += 1
79+
print('')

0 commit comments

Comments
 (0)