Skip to content
Extraits de code Groupes Projets
shortest_path.py 3,96 ko
Newer Older
  • Learn to ignore specific revisions
  • Louis Navarre's avatar
    Louis Navarre a validé
    import math
    
    import argparse
    import sys
    
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    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")
    
    Louis Navarre's avatar
    Louis Navarre a validé
    args = parser.parse_args()
    
    verbose = args.v
    output_fd = args.f
    nb_nodes = None
    nb_edges = None
    
    if verbose:
        print(args, file=sys.stderr)
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    def get_file_infos(data):
    
    Louis Navarre's avatar
    Louis Navarre a validé
        nb_nodes = int.from_bytes(data[0:4], "big", signed=True)
        nb_edges = int.from_bytes(data[4:], "big", signed=True)
        return nb_nodes, nb_edges
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    def bellman_ford(table, s):
    
    Louis Navarre's avatar
    Louis Navarre a validé
        dist = [math.inf]*nb_nodes
    
    Louis Navarre's avatar
    Louis Navarre a validé
        dist[s] = 0
    
    Louis Navarre's avatar
    Louis Navarre a validé
        path = [-1]*nb_nodes
        for _ in range(nb_nodes-1):
            for j in range(len(table)):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                a, b, cab = table[j][0], table[j][1], table[j][2]
                if (dist[a] != math.inf and dist[b] > dist[a]+cab):
                    dist[b] = dist[a]+cab
                    path[b] = a
    
    Louis Navarre's avatar
    Louis Navarre a validé
        for j in range(len(table)):
    
    Louis Navarre's avatar
    Louis Navarre a validé
            a, b, cab = table[j][0], table[j][1], table[j][2]
            if (dist[a] != math.inf and dist[b] > dist[a]+cab):
                print("Cycle négatif détecté")
    
                dist = [math.inf] * nb_nodes
                dist[s] = 0
                path = [-1] * nb_nodes
    
    Louis Navarre's avatar
    Louis Navarre a validé
        return dist, path
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    def get_path(dest, path, source):
    
    Louis Navarre's avatar
    Louis Navarre a validé
        r = [dest]
        i = dest
    
    Louis Navarre's avatar
    Louis Navarre a validé
        while (True):
            if (i == source):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                break
    
    Louis Navarre's avatar
    Louis Navarre a validé
            r.insert(0, path[i])
    
    Louis Navarre's avatar
    Louis Navarre a validé
            i = path[i]
        return r
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    def get_max(dist, s):
    
    Louis Navarre's avatar
    Louis Navarre a validé
        max = -math.inf
        n = s
        for i in range(len(dist)):
    
    Louis Navarre's avatar
    Louis Navarre a validé
            if (i != s and dist[i] != math.inf and dist[i] >= max):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                max = dist[i]
    
    Louis Navarre's avatar
    Louis Navarre a validé
                n = i
        if (max == -math.inf):
            if (dist[s] != math.inf and dist[s] >= max):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                max = dist[s]
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
        return max, n
    
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
    if __name__ == "__main__":
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
        with open(args.input_file, "rb") as input_file:
            binary_data = input_file.read()
            nb_nodes, nb_edges = get_file_infos(binary_data[:8])
            if verbose:
    
    Louis Navarre's avatar
    Louis Navarre a validé
                print("Number of nodes :", nb_nodes,
                      ", number of links :", nb_edges)
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
            binary_data = binary_data[8:]
            table = []
            if output_fd == sys.stdout or output_fd == sys.stderr:
                print(nb_nodes)
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
            else:
    
    Louis Navarre's avatar
    Louis Navarre a validé
                output_fd.write(nb_nodes.to_bytes(4, "big"))
    
            for i in range(nb_edges):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                a = int.from_bytes(binary_data[i*12:i*12+4], "big", signed=True)
                b = int.from_bytes(binary_data[i*12+4:i*12+8], "big", signed=True)
                cab = int.from_bytes(
                    binary_data[i*12+8:i*12+12], "big", signed=True)
                l1 = [a, b, cab]
                table.append(l1)
    
    Louis Navarre's avatar
    Louis Navarre a validé
            for i in range(nb_nodes):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                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
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
    
    Louis Navarre's avatar
    Louis Navarre a validé
                if output_fd == sys.stdout or output_fd == sys.stderr:
                    print("source : "+str(i))
    
    Louis Navarre's avatar
    Louis Navarre a validé
                    d, n = get_max(dist, i)
                    print("destination : " + str(n))
                    print("cout : " + str(d))
                    p = get_path(n, path, i)
    
    Louis Navarre's avatar
    Louis Navarre a validé
                    print("nombre de noeuds : "+str(len(p)))
                    print("chemin : "+" ".join(str(x) for x in p))
                    print("-----------------------")
    
    Louis Navarre's avatar
    Louis Navarre a validé
    
                else:
    
    Louis Navarre's avatar
    Louis Navarre a validé
                    output_fd.write(i.to_bytes(4, "big"))
    
    Louis Navarre's avatar
    Louis Navarre a validé
                    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)):
    
    Louis Navarre's avatar
    Louis Navarre a validé
                        output_fd.write(r[j].to_bytes(4, "big"))