Skip to content
Extraits de code Groupes Projets
Valider ac377f4d rédigé par Louis Navarre's avatar Louis Navarre
Parcourir les fichiers

Code python clean

parent 21ccf795
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
import math import math
import argparse import argparse
import sys import sys
parser = argparse.ArgumentParser(
description="LEPL1503 - Détection et correction d'erreurs")
parser.add_argument(
"input_file", help="Nom du fichier contenant les données nécessaires")
parser.add_argument("-f", help="Chemin vers le fichier de sortie",
type=argparse.FileType("wb"), default=sys.stdout)
parser.add_argument(
"-v", help="\"verbose\" mode: si ajouté, affiche des informations sur l'exécution du programme", action="store_true")
args = parser.parse_args()
verbose = args.v
output_fd = args.f
nb_nodes = None
nb_edges = None
if verbose:
print(args, file=sys.stderr)
def get_file_infos(data): def get_file_infos(data):
"""
Récupère les informations basiques du graphe : le nombre de noeuds et de liens.
"""
nb_nodes = int.from_bytes(data[0:4], "big", signed=True) nb_nodes = int.from_bytes(data[0:4], "big", signed=True)
nb_edges = int.from_bytes(data[4:], "big", signed=True) nb_edges = int.from_bytes(data[4:], "big", signed=True)
return nb_nodes, nb_edges return nb_nodes, nb_edges
def bellman_ford(table, s): def bellman_ford(links, s, verbose):
dist = [math.inf]*nb_nodes """
dist[s] = 0 Exécute l'algorithme de Bellman-Ford avec comme noeud source `s`.
path = [-1]*nb_nodes Retourne un tableau de distances pour atteindre chaque noeud depuis `s`,
for _ in range(nb_nodes-1): ainsi que le chemin pour atteindre ces noeuds (tableau de précédence).
for j in range(len(table)): Si le noeud est isolé ou qu'un cycle négatif est trouvé, retourne une distance
a, b, cab = table[j][0], table[j][1], table[j][2] infinie pour chaque autre noeud, et une distance de 0 pour `s`.
if (dist[a] != math.inf and dist[b] > dist[a]+cab): """
dist[b] = dist[a]+cab dist = [math.inf] * nb_nodes
path[b] = a dist[s] = 0 # Le noeud source est à distance 0 de lui-meme.
for j in range(len(table)): path = [-1] * nb_nodes
a, b, cab = table[j][0], table[j][1], table[j][2] for _ in range(nb_nodes-1): # Iteration de Bellman-Ford.
if (dist[a] != math.inf and dist[b] > dist[a]+cab): for j in range(len(links)):
print("Cycle négatif détecté") node_from, node_to, cost = links[j][0], links[j][1], links[j][2]
if (dist[node_from] != math.inf and dist[node_to] > dist[node_from] + cost):
dist[node_to] = dist[node_from] + cost
path[node_to] = node_from
for j in range(len(links)):
node_from, node_to, cost = links[j][0], links[j][1], links[j][2]
if (dist[node_from] != math.inf and dist[node_to] > dist[node_from] + cost):
if verbose:
print("Cycle négatif détecté")
dist = [math.inf] * nb_nodes dist = [math.inf] * nb_nodes
dist[s] = 0 dist[s] = 0
path = [-1] * nb_nodes path = [-1] * nb_nodes
...@@ -50,75 +41,104 @@ def bellman_ford(table, s): ...@@ -50,75 +41,104 @@ def bellman_ford(table, s):
def get_path(dest, path, source): def get_path(dest, path, source):
"""
Retourne une liste contenant le chemin de `source` vers `dest`
en utilisant le tableau de précédence `path`.
"""
r = [dest] r = [dest]
i = dest i = dest
while (True): while i != source:
if (i == source):
break
r.insert(0, path[i]) r.insert(0, path[i])
i = path[i] i = path[i]
return r return r
def get_max(dist, s): def get_max(dist, s):
max = -math.inf """
n = s Retourne l'indice du noeud dont il existe un chemin de `s` vers ce noeud
for i in range(len(dist)): et le cout de ce chemin est le plus élevé parmis tous les noeuds ayant un chemin
if (i != s and dist[i] != math.inf and dist[i] >= max): depuis `s`.
max = dist[i] """
n = i max_cost = -math.inf
if (max == -math.inf): max_node = s
if (dist[s] != math.inf and dist[s] >= max): for node_idx in range(len(dist)):
max = dist[s] if node_idx != s and dist[node_idx] != math.inf and dist[node_idx] >= max_cost:
max_cost = dist[node_idx]
max_node = node_idx
if max_cost == -math.inf:
if dist[s] != math.inf and dist[s] >= max_cost:
max_cost = dist[s]
return max_cost, max_node
def read_graph(filename):
"""
Récupère le graphe représenté dans le fichier donné en argument.
Suit le format défini dans l'énoncé.
"""
with open(filename, "rb") as fd:
binary_data = fd.read()
nb_nodes, nb_edges = get_file_infos(binary_data[:8])
return max, n if verbose:
print("Nombre de noeuds :", nb_nodes,
", nombre de liens :", nb_edges)
binary_data = binary_data[8:]
links = []
for i in range(nb_edges):
from_node = int.from_bytes(binary_data[i * 12:i * 12 + 4], "big", signed=True)
to_node = int.from_bytes(binary_data[i * 12 + 4:i * 12 + 8], "big", signed=True)
cost = int.from_bytes(
binary_data[i * 12 + 8:i * 12 + 12], "big", signed=True)
l1 = [from_node, to_node, cost]
links.append(l1)
return links
if __name__ == "__main__": if __name__ == "__main__":
with open(args.input_file, "rb") as input_file: parser = argparse.ArgumentParser(
binary_data = input_file.read() description="LEPL1503 - Algorithme de plus court chemin")
nb_nodes, nb_edges = get_file_infos(binary_data[:8]) parser.add_argument(
if verbose: "input_file", help="chemin vers le fichier d'instance representant le graphe a traiter.")
print("Number of nodes :", nb_nodes, parser.add_argument("-f", help="chemin vers le fichier qui contiendra le resultat de programme, au format specifie dans l'enonce. Defaut : stdout.",
", number of links :", nb_edges) type=argparse.FileType("wb"), default=sys.stdout)
parser.add_argument(
"-v", help="autorise les messages de debug. Si ce n'est pas active, aucun message de ce type ne peut etre affiche, excepte les messages d'erreur en cas d'echec. Defaut : false.", action="store_true")
args = parser.parse_args()
verbose = args.v
output_fd = args.f
nb_nodes = None
nb_edges = None
if verbose:
# Exemple de message que vous pouvez ecrire si le mode verbose est actif.
print(args, file=sys.stderr)
graph = read_graph(args.input_file)
for source in range(nb_nodes):
dist, path = bellman_ford(graph, source)
binary_data = binary_data[8:]
table = []
if output_fd == sys.stdout or output_fd == sys.stderr: if output_fd == sys.stdout or output_fd == sys.stderr:
print(nb_nodes) print("source : " + str(source))
print("Distances: ", dist)
d, n = get_max(dist, source)
print("\tdestination : " + str(n))
print("\tcout : " + str(d))
p = get_path(n, path, source)
print("\tnombre de noeuds : "+str(len(p)))
print("\tchemin : "+" ".join(str(x) for x in p))
else: else:
output_fd.write(nb_nodes.to_bytes(4, "big")) output_fd.write(source.to_bytes(4, "big"))
d, n = get_max(dist, source)
for i in range(nb_edges): output_fd.write(d.to_bytes(4, "big", signed=True))
a = int.from_bytes(binary_data[i*12:i*12+4], "big", signed=True) output_fd.write(n.to_bytes(4, "big"))
b = int.from_bytes(binary_data[i*12+4:i*12+8], "big", signed=True) r = get_path(n, path, source)
cab = int.from_bytes( output_fd.write(len(r).to_bytes(4, "big", signed=True))
binary_data[i*12+8:i*12+12], "big", signed=True) for j in range(len(r)):
l1 = [a, b, cab] output_fd.write(r[j].to_bytes(4, "big"))
table.append(l1)
for i in range(nb_nodes):
dist, path = bellman_ford(table, i)
if dist == -1:
continue # TODO: if there is no shortest path (negative cycle or empty path), put a 0 value instead of not showing it at all
if output_fd == sys.stdout or output_fd == sys.stderr:
print("source : "+str(i))
d, n = get_max(dist, i)
print("destination : " + str(n))
print("cout : " + str(d))
p = get_path(n, path, i)
print("nombre de noeuds : "+str(len(p)))
print("chemin : "+" ".join(str(x) for x in p))
print("-----------------------")
else:
output_fd.write(i.to_bytes(4, "big"))
d, n = get_max(dist, i)
output_fd.write(d.to_bytes(4, "big", signed=True))
output_fd.write(n.to_bytes(4, "big"))
r = get_path(n, path, i)
output_fd.write(len(r).to_bytes(4, "big", signed=True))
for j in range(len(r)):
output_fd.write(r[j].to_bytes(4, "big"))
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter