def algoritmo2(g: UndirectedGraph) -> Tuple[int, Dict[Tuple[int, int], int]]: color_dic = {} n_colores = 0 maxHeap = MaxHeapMap() for v in g.V: maxHeap[v] = (0, len(g.succs(v)), v[0], v[1]) while len(maxHeap) > 0: v_actual = maxHeap.extract_opt() colores = [color_dic.get(vecino) for vecino in g.succs(v_actual)] c = 0 while True: if c not in colores: color_dic[v_actual] = c for vecino in g.succs(v_actual): if vecino in maxHeap: maxHeap[vecino] = (maxHeap[vecino][0] + 1, maxHeap[vecino][1], maxHeap[vecino][2], maxHeap[vecino][3]) break c += 1 if c > n_colores: n_colores = c return n_colores + 1, color_dic
def BFS_wallbraker(g: UndirectedGraph, source: Vertex, distances: dict) -> Edge: seen = set() min = float('infinity') wall = ((-1, -1), (-1, -1)) queue = Fifo() queue.push((source, 0)) seen.add(source) while len(queue) > 0: vertex, n = queue.pop() u, v = vertex # Comprobacion de vecinos tras los muros for x, y in [(1, 0), (0, 1), (-1, 0), (0, -1)]: neigh = (u + x, v + y) if neigh not in g.succs((u, v)) and neigh in distances: tdistance = n + distances[neigh] if tdistance < min: min = tdistance wall = ((u, v), neigh) for suc in g.succs(vertex): if suc not in seen: seen.add(suc) queue.push((suc, n + 1)) return wall
def create_labyrinth_mod(rows: int, cols: int, n: int = 0) -> UndirectedGraph: vertex = [(r, c) for r in range(rows) for c in range(cols)] mfs = MergeFindSet() for v in vertex: mfs.add(v) edges = [] for (i, j) in vertex: edges.append(((i, j), (i, j + 1))) if j + 1 < cols else "" edges.append(((i, j), (i + 1, j))) if i + 1 < rows else "" random.shuffle(edges) corridors = [] discarded_edges = [] for (u, v) in edges: if mfs.find(u) != mfs.find(v): mfs.merge(u, v) corridors.append((u, v)) else: discarded_edges.append((u, v)) graph_wo_mod = UndirectedGraph(E=corridors) new_corridors = corridors[:] new_corridors.extend(discarded_edges[:n]) graph_mod = UndirectedGraph(E=new_corridors) return graph_wo_mod, graph_mod
def create_labyrinth(rows, cols): # general expressions of all vertexes vertices = [(row, col) for row in range(rows) for col in range(cols)] mfs = MergeFindSet() edges = [] for v in vertices: # print(v) mfs.add(v) # add the bottom row and right column to edge list and shuffle it for row, col in vertices: if row + 1 < rows: edges.append([(row, col), (row + 1, col)]) if col + 1 < cols: edges.append([(row, col), (row, col + 1)]) shuffle(edges) # # # # for i in edges: # a, b = i # print(a, b) ### corridors = [] # if the edges are not in the same set, merge them in the same one and add them to corridors for u, v in edges: if mfs.find(u) != mfs.find(v): mfs.merge(u, v) corridors.append((u, v)) # for u, v in corridors: # print("Path: {} -> {}".format(u, v)) return UndirectedGraph(E=corridors)
def __init__(self, g, window_size=(400, 400), vertexmode=X_Y): EasyCanvas.__init__(self) if not isinstance(g, UndirectedGraph) or \ any([type(p) != type((1, 1)) or len(p) != 2 or type(p[0]) != type(p[1]) for p in g.V]) or \ any([type(p[0]) != type(1) and type(p[0]) != type(1.0) for p in g.V]): raise TypeError( "The graph must be an UndirectedGraph. Vertices must be tuples of two integers or floats" ) if vertexmode == Graph2dViewer.ROW_COL: if any([type(p[0]) != type(1) for p in g.V]): raise TypeError( "In this mode, vertices must be tuples of two integers") g = UndirectedGraph(V=[(v[1], -v[0]) for v in g.V], E=[((u[1], -u[0]), (v[1], -v[0])) for (u, v) in g.E]) self.g = g self.max_y = max(p[1] for p in self.g.V) self.max_x = max(p[0] for p in self.g.V) self.min_y = min(p[1] for p in self.g.V) self.min_x = min(p[0] for p in self.g.V) self.window_size = window_size
def kruskal2(aristas): aristas_ordenadas = sorted(aristas.items(), key=lambda x: x[1]) mfs = MergeFindSet() limite = [2] * len(puntos) path = [] for v in range(len(puntos)): mfs.add(v) for edge, w in aristas_ordenadas: u = edge[0] v = edge[1] if limite[u] > 0 and limite[ v] > 0: # puedo meter la arista si no tiene ciclo if mfs.find(u) != mfs.find(v): # no hace ciclo mfs.merge(u, v) path.append(edge) limite[u] -= 1 limite[v] -= 1 vertice_extra = [] for i, x in enumerate(limite): if x == 1: vertice_extra.append(i) path.append(tuple(vertice_extra)) g = UndirectedGraph(E=path) return path, g
def create_labyrinth(rows: int, cols: int, corridors) -> UndirectedGraph: vertices = [(r, c) for r in range(rows) for c in range(cols)] mfs = MergeFindSet() for v in vertices: mfs.add(v) return UndirectedGraph(E=corridors)
def load_labyrinth(file: str) -> UndirectedGraph: """ @param file: Fichero que contiene un laberinto. @return: Devuelve un UndirectedGraph equivalente al laberinto del fichero. """ f = open(file, "r") lines = f.readlines() f.close() corridors = [] global cols global rows rows = len(lines) for r in range(rows): cells = lines[r].rstrip('\n').split(',') if r == 0: cols = len(cells) for c in range(cols): if 's' not in cells[c] and r + 1 < rows: corridors.append(((r, c), (r + 1, c))) if 'e' not in cells[c] and c + 1 < cols: corridors.append(((r, c), (r, c + 1))) return UndirectedGraph(E=corridors)
def create_labyrinth(rows: int, cols: int) -> UndirectedGraph: # Paso 1 = Creamos una lista con los vertices de nuestro grafo vertices = [(r, c) for r in range(rows) for c in range(cols)] # Paso 2 = Creamos un MergeFindSet vacio y le vamos añadiendo UNO A UNO # los vertices de la lista creada en el paso 1 mfs = MergeFindSet() for v in vertices: mfs.add(v) # Paso 3 = Creamos una lista llamada "edges" con los pares de vertices # vecinos, y la barajamos edges = [] for (r, c) in vertices: if r + 1 < rows: edges.append(((r, c), (r + 1, c))) if c + 1 < cols: edges.append(((r, c), (r, c + 1))) random.shuffle(edges) # Paso 4 = Creamos una lista vacia que contiene los pasillos del laberinto corridors = [] # Paso 5 = Recorremos la lista de bordes, y para cada arista (u, v), # encuentra la clase a la que pertenece cada uno de los vertices # usando "find()". u y v son VERTICES, u = (r,c) y v = (r2,c2) for (u, v) in edges: if mfs.find(u) != mfs.find(v): mfs.merge(u, v) corridors.append((u, v)) # Paso 6 = Devolvemos el resultado return UndirectedGraph(E=corridors)
def create_labyrinth(rows, cols): #Intentar Edges con expresion generatriz #Paso 1 vertices = [(i, j) for i in range(rows) for j in range(cols)] #Paso 2 mfs = MergeFindSet() for v in vertices: mfs.add(v) #Paso 3 edges = [] for r in range(rows): for c in range(cols): if r + 1 < rows: edges.append(((r, c), (r + 1, c))) if c + 1 < cols: edges.append(((r, c), (r, c + 1))) random.shuffle(edges) #Paso 4 corridors = [] #Paso 5 for (u, v) in edges: if mfs.find(u) != mfs.find(v): mfs.merge(u, v) corridors.append((u, v)) #Paso 6 return UndirectedGraph(E=corridors)
def create_labyrinth(rows: int, cols: int, n: int = 0) -> UndirectedGraph: vertices = [(r, c) for r in range(rows) for c in range(cols)] mfs = MergeFindSet() for v in vertices: mfs.add(v) edges = [] for r, c in vertices: if r + 1 < rows: edges.append(((r, c), (r + 1, c))) if c + 1 < cols: edges.append(((r, c), (r, c + 1))) random.shuffle(edges) corridors = [] for (u, v) in edges: if mfs.find(u) != mfs.find(v): corridors.append((u, v)) mfs.merge(u, v) elif n > 0: corridors.append((u, v)) n -= 1 return UndirectedGraph(E=corridors)
def create_labyrinth(num_rows: int, num_cols: int, n: int = 0) -> UndirectedGraph: vertices: List[Tuple] = [] for r in range(num_rows): for c in range(num_cols): vertices.append((r, c)) mfs = MergeFindSet() for v in vertices: mfs.add(v) edges: List[Edge] = [] for r, c in vertices: if r > 0: edges.append(((r, c), (r - 1, c))) if c > 0: edges.append(((r, c), (r, c - 1))) shuffle(edges) corridors: List[Edge] = [] for e in edges: (v, u) = e if mfs.find(v) != mfs.find(u): mfs.merge(v, u) corridors.append(e) else: if n > 0: corridors.append((u, v)) n -= 1 return UndirectedGraph(E=corridors)
def create_labyrinth(rows, cols): #Definition #Step 1 vertices = [(r, c) for r in range(rows) for c in range(cols)] #Step 2 mfs = MergeFindSet() for v in vertices: mfs.add(v) #Step 3 edges = [] for (r, c) in vertices: if r + 1 < rows: edges.append(((r, c), (r + 1, c))) if c + 1 < cols: edges.append(((r, c), (r, c + 1))) shuffle(edges) #Step 4 corridors = [] #Step 5 for (u, v) in edges: if mfs.find(u) != mfs.find(v): mfs.merge(u, v) corridors.append((u, v)) #Step 6 return UndirectedGraph(E=corridors)
def crea_laberinto_mod(nfil, ncol, n): ##Problema3 vertices = [(i, j) for (i) in range(nfil) for (j) in range(ncol)] mfs = MergeFindSet() for v in vertices: mfs.add(v) aristasV = [((f, c), (f + 1, c)) for f in range(nfil - 1) for c in range(ncol)] aristasH = [((f, c), (f, c + 1)) for f in range(nfil) for c in range(ncol - 1)] aristas = aristasV + aristasH shuffle(aristas) nCamino = n pasillos = [] for (u, v) in aristas: if mfs.find(u) != mfs.find(v): if nCamino == 0: mfs.merge(u, v) else: nCamino -= 1 pasillos.append((u, v)) return UndirectedGraph(E=pasillos)
def load_lab(fichero): fich = open(fichero) #Lee la primera linea #cols = len de la lista que devuelve split cols = len(fich.readline().split(",")) #Lee el resto de filas #rows = num de filas + la leida antes rows = len(fich.readlines()) + 1 fich.seek(0) edges = [] for r in range(rows): #Vector que guarda cada linea row = fich.readline().split(",") for c in range(cols): column = row[c] #Si la celda no tiene pared al norte o al este se añaden los pasillos if "s" not in column: edges.append(((r, c), (r + 1, c))) if "e" not in column: edges.append(((r, c), (r, c + 1))) #Devolvemos el grafo construido, junto con sus dimensiones return UndirectedGraph(E=edges), rows, cols
def recorredor_anchura(g: UndirectedGraph, source: "T", r: int, c: int): #Crear e inicializar matriz distances = [] for row in range(r): distances.append([0] * c) queue = Fifo() seen = set() #Añadir el punto inicial a la cola queue.push((source, source)) seen.add(source) while len(queue) > 0: u, v = queue.pop() #Miramos los sucesores del elemento extraido de la cola for s in g.succs(v): #Si no lo hemos visitado ya lo añadimos a los visitados y anotamos en la matriz su distancia al origen if s not in seen: seen.add(s) distances[s[0]][s[1]] = distances[v[0]][ v[1]] + 1 #En la posición del sucesor el antecesor mas 1 queue.push((v, s)) return distances
def hourse_graph(rows, cols) -> UndirectedGraph: vertexes = [(fil, col) for fil in range(rows) for col in range(cols)] edges = [] for fil, col in vertexes: for sr, sc in [(1, -2), (2, -1), (2, 1), (1, 2)]: if sr + fil < rows and 0 <= col + sc < cols: edges.append(((fil, col), (fil + sr, col + sc))) return UndirectedGraph(E=edges, V=vertexes)
def algoritmo1(g: UndirectedGraph) -> Tuple[int, Dict[Tuple[int, int], int]]: vertices = sorted(g.V, key=lambda x: (-len(g.succs(x)), -x[0], -x[1])) dic = {v: -1 for v in g.V} n_colores = 0 for v in vertices: colores_vecinos = set() for vecino in g.succs(v): color = dic[vecino] if color != -1: colores_vecinos.add(color) for color in range(n_colores): if color not in colores_vecinos: dic[v] = color break else: dic[v] = n_colores n_colores += 1 return n_colores, dic
def horse_graph(rows: int, cols: int) -> UndirectedGraph: vertices = [(u, v) for u in range(rows) for v in range(cols)] edges = [] for (u, v) in vertices: for (ir, ic) in [(-2, 1), (-2, -1), (-1, 2), (-1, -2)]: if u + ir >= 0 and 0 <= v + ic < cols: edges.append(((u, v), (u + ir, v + ic))) g = UndirectedGraph(E=edges, V=vertices) return g
def horse_graph(rows, cols): edges = [] saltos = [(1, -2), (2, -1), (2, 1), (1, 2)] for r in range(rows): for c in range(cols): for (ri, ci) in saltos: if r + ri < rows and 0 <= c + ci < cols: edges.append(((r, c), (r + ri, c + ci))) return UndirectedGraph(E=edges)
def horse_graph(rows: int, cols: int) -> UndirectedGraph: vertices = [(r, c) for r in range(rows) for c in range(cols)] edges = [] jumps = [(1, 2), (1, -2), (2, -1), (2, 1)] for r, c in vertices: for ir, ic in jumps: if r + ir < rows and 0 <= c + ic < cols: edges.append(((r, c), (r + ir, c + ic))) return UndirectedGraph(V=vertices, E=edges)
def load_graph(filename: str): def string_to_tuple(linea: str) -> Tuple: linea = linea.split() return (int(linea[0]), int(linea[1])), (int(linea[2]), int(linea[3])) with open(filename, "r") as f: edges = [] for line in f: edges.append(string_to_tuple(line)) graph = UndirectedGraph(E=edges) return graph
def setUp(self): self.G = UndirectedGraph( E={ 0: [1, 2], 1: [2], 2: [], 3: [4], 4: [], 5: [6, 7, 8], 6: [7, 8], 7: [8], 8: [] }) self.chain = UndirectedGraph(E=[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]) self.loop = UndirectedGraph(E=[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0)]) self.islands = UndirectedGraph(E=[(0, 1), (1, 2), (2, 0), (3, 4), (4, 3)])
def setUp(self): self.iberia = UndirectedGraph(V=cities, E=roads) self.unconnected = Digraph(E={ 0: [1, 2], 1: [2, 3], 2: [5, 6], 3: [5], 4: [2], 5: [6] }) self.unconnected_weight = WeightingFunction( (((u, v), 1) for (u, v) in self.unconnected.E))
def create_labyrinth(rows, cols, n=0): # Crea una lista, vertices, con los vértices del grafo (nuestras celdas del laberinto). vertices = [] for row in range(rows): for col in range(cols): vertices.append((row, col)) # vertices = [(r,c) for r in range(rows) for c in range(cols)] <-- versión del profesor # Crea un MFSet vacío, mfs, y añádele uno a uno los vértices de la lista vertices usando su método add. # Para crear un MFSet utiliza la clase MergeFindSet disponible en algoritmia.datastructures.mergefindsets. mfs = MergeFindSet() for vertice in vertices: mfs.add(vertice) # Crea una lista, edges, con todos los pares de vértices vecinos y barájala. Usa la función # shuffle del módulo random. edges = [] for row in range(rows): for col in range(cols): if col > 0: edges.append(((row, col), (row, col - 1))) if row > 0: edges.append(((row, col), (row - 1, col))) # edges = [((row, col), (row, col + 1)) for r in range(rows) for c in range(cols-1)] # edges.extend( # [((row, col), (row, col + 1)) for r in range(rows-1) for c in range(cols)] # ) random.shuffle(edges) # Crea una lista vacía, corridors. Aquí pondremos las aristas (pasillos) que tendrá al final # nuestro grafo (laberinto). corridors = [] # Recorre la lista edges y, para cada arista (u,v), encuentra la clase a la que pertenece # cada uno de los dos vértices usando find. Si son diferentes, fusiónalas en la misma clase con # merge y añade la arista (u,v) a la lista corridors. for u, v in edges: if mfs.find(u) != mfs.find(v): corridors.append((u, v)) mfs.merge(u, v) else: if n > 0: corridors.append((u, v)) #mfs.merge(u, v) n -= 1 # El laberinto es el grafo no dirigido que tiene a la lista corridors como conjunto de aristas: # return UndirectedGraph(E = corridors) # print("Corridors: ") # print(corridors) return UndirectedGraph(E=corridors)
def knight_graph(num_rows: int, num_cols: int) -> UndirectedGraph: vertices: List[Tuple] = [] for r in range(num_rows): for c in range(num_cols): vertices.append((r, c)) edges: List[Edge] = [] for r, c in vertices: for (ir, ic) in [(-2, -1), (-1, -2), (-2, 1), (-1, 2)]: if 0 <= r + ir < num_rows and 0 <= c + ic < num_cols: edges.append(((r, c), (r + ir, c + ic))) return UndirectedGraph(V=vertices, E=edges)
def setUp(self): self.edges = [(0,1), (1,2), (2,3), (3,4), (4,5),(5,0), (0,3), (3,0), (0,2), (0,4), (0,7)] self.undirected_edges = set() for (u,v) in self.edges: self.undirected_edges.add((u,v)) self.undirected_edges.add((v,u)) self.g1 = UndirectedGraph(V=range(8), E=self.edges) self.g1bis = UndirectedGraph(E=self.edges) self.g1bis.V.add(6) self.g2 = AdjacencyDigraph(V=range(8), E=self.edges, directed=False, createMap=lambda V: IntKeyMap(capacity=max(V)+1), createSet=lambda V: IntSet(capacity=max(V)+1)) self.g3 = LinkedListSetAdjacencyDigraph(V=range(8), E=self.edges, directed=False, createMap=lambda V: IntKeyMap(capacity=max(V)+1)) self.g4 = ListSetAdjacencyDigraph(V=range(8), E=self.edges, directed=False, createMap=lambda V: IntKeyMap(capacity=max(V)+1)) self.g5 = SetAdjacencyDigraph(V=range(8), E=self.edges, directed=False, createMap=lambda V: IntKeyMap(capacity=max(V)+1)) self.g6 = AdjacencyMatrixDigraph(V=range(8), E=self.edges, directed=False) self.g7 = InvAdjacencyDigraph(V=range(8), E=self.edges, directed=False, createMap=lambda V: IntKeyMap(capacity=max(V)+1), createSet=lambda V: IntSet(capacity=max(V)+1))
def shortest_path(g: UndirectedGraph, source: Vertex, target: Vertex): aristas = [] queue = Fifo() seen = set() queue.push((source, source)) seen.add(source) while len(queue) > 0: u, v = queue.pop() aristas.append((u, v)) for suc in g.succs(): if suc not in seen: seen.add(suc) queue.push((v, suc)) return recover_path(aristas, target)
def anchura(g: UndirectedGraph, source: tuple) -> list: visitados = set() aristas = [] queue = Fifo() queue.push((source, source)) visitados.add(source) while len(queue) > 0: u, v = queue.pop() for suc in g.succs(v): if suc not in visitados: visitados.add(suc) aristas.append((v, suc)) queue.push((v, suc)) return aristas
def recorredor_aristas_anchura(g: UndirectedGraph, v_inicial: Vertex) -> List[Edge]: aristas = [] queue = Fifo() seen = set() queue.push((v_inicial, v_inicial)) seen.add(v_inicial) while len(queue) > 0: u, v = queue.pop() aristas.append((u, v)) for suc in g.succs(v): if suc not in seen: seen.add(suc) queue.push((v, suc)) return aristas