Grafos y Diksra

Run Settings
LanguagePython
Language Version
Run Command
import numpy as np class Grafo: #generador de grafo con 'cant_nodos' nodos def __init__(self, cant_nodos): self.matriz_ad = np.zeros((cant_nodos, cant_nodos)) self.cant_nodos = cant_nodos #agrega 'cant_nodos_nuevos' nodos al grafo def agregar_nodos(self, cant_nodos_nuevos): #cambio el tamaño de la matriz sumandole cant_nodos_nuevos self.cant_nodos += cant_nodos_nuevos #agregar 'cant_nodos_nuevos' filas y columnas for i in range(cant_nodos_nuevos): self.matriz_ad = np.pad(self.matriz_ad, ((0, 1), (0, 1)), mode='constant') #crea una arista dirccionada dede v a u, v y u indices del nodo def agregar_arista(self, v, u, peso): #valido que los nodos existan if 0 <= u < self.cant_nodos and 0 <= v < self.cant_nodos: #cargo el pedo de la arista en el lugar correspondiente de la matriz self.matriz_ad[v][u] = peso else: print('Los modos ingresados no existen') #imprime los valores actuales de la matriz de adyacencia def mostrar_matriz(self): for row in self.matriz_ad: print(f"[ {', '.join(str(int(x)) for x in row)} ]") print() #funcion que devuelve y calcula el peso del el camino mas corto desde el 'nodo_inicio' a todos los nodos del grafo def dijkstra(self, nodo_inicio): if (0 <= nodo_inicio < self.cant_nodos): #la funcion 'obtener_caminos' recorre el array precesores para reconstruir el camino mas corto desde el 'nodo_inicio' al 'nodo_fin' def obtener_camino(precesores, nodo_inicio, nodo_fin): camino = [] actual = nodo_fin #mientras en el array de precesores no aparezca None (lo que significa que no he ya llegado al final del camino), sigo iterando while actual is not None: #inserto en la posicion 0 el valor camino.insert(0, actual) #para el nuevo valor es el precesos del valor actual actual = precesores[actual] #valido que si es nuvo valor es el 'nodo_inicio', si es asi lo agrego y paro el while if actual == nodo_inicio: camino.insert(0, nodo_inicio) break #retorno la lista separada por flechas para mostrar return '->'.join(str(x) for x in camino) distancias = [float('inf')] * self.cant_nodos precesores = [None] * self.cant_nodos distancias[nodo_inicio] = 0 visitado = [False] * self.cant_nodos for _ in range(self.cant_nodos): distancia_minima = float('inf') #en u se va a guardar el nodo con la menor distancia en el array de distancias y que no ha sido visitado u = None for i in range(self.cant_nodos): if not visitado[i] and distancias[i] < distancia_minima: distancia_minima = distancias[i] u = i #si no hay nodos por visitar termino el for if u is None: break #actualizo visitado para u visitado[u] = True #recorro la matriz para encontrar los adyacentes de u for v in range(self.cant_nodos): #chequeo que sea adyasente y que no se haya visitado ya if self.matriz_ad[u][v] != 0 and not visitado[v]: #calculo la distancia del vertice inicio al vertive v alt = distancias[u] + self.matriz_ad[u][v] #si la nueva distancia calculada es menor a la ya guardada actualizo la distancia y el precesor sino no hago nada if alt < distancias[v]: distancias[v] = alt precesores[v] = u #itero sobre las distancias e imprimo, para cada par de nodos calculo el camino y muestro la distancia for i, d in enumerate(distancias): print(f"camino de {nodo_inicio} a {i} es: {obtener_camino(precesores, nodo_inicio, i)} distancia: {d}") else: print('El nodo ingresado no existe') g = Grafo(2) g.agregar_nodos(3) g.agregar_arista(0,2,1) g.agregar_arista(0,3,2) g.agregar_arista(1,0,1) g.agregar_arista(2,1,1) g.agregar_arista(2,3,3) g.agregar_arista(4,0,5) g.mostrar_matriz() g.dijkstra(4)
Editor Settings
Theme
Key bindings
Full width
Lines