SHOW:
|
|
- or go back to the newest paste.
1 | - | # 99373 ALVAREZ - 99192 OTERO |
1 | + | import sys |
2 | - | import random |
2 | + | from grafo import Grafo |
3 | import heapq | |
4 | - | import math |
4 | + | import collections |
5 | - | from time import time |
5 | + | import re |
6 | - | from collections import deque |
6 | + | RANGO_WALKS = 100 |
7 | CANTIDAD_WALKS = 50 | |
8 | - | visitar_nulo = lambda a,b,c,d: True |
8 | + | RANGO_CENTRALIDAD = 700 |
9 | - | heuristica_nula = lambda actual,destino: 0 |
9 | + | OPCIONES = ['1','2','3','4','5','6','7','8'] |
10 | ||
11 | - | class Grafo(object): |
11 | + | def crear_grafo(ruta): |
12 | - | '''Clase que representa un grafo. El grafo puede ser dirigido, o no, y puede |
12 | + | ''' Recibe una ruta de un archivo y devuelve un grafo a partir de sus datos |
13 | - | no indicarsele peso a las aristas (se comportara como peso = 1). |
13 | + | PRE: la ruta debe existir, el archivo debe ser de la siguiente manera: |
14 | - | Implementado como "diccionario de diccionarios" |
14 | + | Vertices cant |
15 | . | |
16 | . | |
17 | - | def __init__(self, es_dirigido = False): |
17 | + | Arcs* |
18 | - | '''Crea el grafo. El parametro 'es_dirigido' indica si sera dirigido, o no.''' |
18 | + | . |
19 | - | self.es_dirigido = es_dirigido |
19 | + | |
20 | - | self.cant_vertices = 0 |
20 | + | with open(ruta) as archivo: |
21 | - | self.vertices = {} |
21 | + | grafo = Grafo(True) |
22 | - | self.personajes = {} |
22 | + | for i,linea in enumerate(archivo): |
23 | - | self.nodos = {} |
23 | + | if i == 0: continue |
24 | - | self.cant_aristas = 0 |
24 | + | linea = linea.rstrip("\n") |
25 | if linea == "*Arcs": break | |
26 | - | def __iter__(self): |
26 | + | vertice = linea.split(" ", 1) |
27 | - | '''Devuelve un iterador para el grafo''' |
27 | + | vertice[1] = vertice[1].rstrip('"') |
28 | - | return iter(self.vertices) |
28 | + | vertice[1] = vertice[1].lstrip('"') |
29 | grafo.__setitem__(vertice[0], vertice[1]) | |
30 | - | def __len__(self): |
30 | + | for linea in archivo: |
31 | - | '''Devuelve la cantidad de vertices del grafo''' |
31 | + | linea = linea.rstrip("\n") |
32 | - | return self.cant_vertices |
32 | + | arista = linea.split(" ") |
33 | grafo.agregar_arista(arista[0],arista[1],int(arista[2])) | |
34 | - | def __setitem__(self, id, valor): |
34 | + | return grafo |
35 | - | '''Agrega un nuevo vertice con el par <id, valor> indicado. ID debe |
35 | + | |
36 | - | ser de identificador unico del vertice. En caso que el identificador |
36 | + | |
37 | - | ya se encuentre asociado a un vertice, se actualizara el valor. |
37 | + | def frecuencia_random_walks(grafo, cantidad , id = None, recomendados = False, rang_walk = RANGO_WALKS): |
38 | - | ''' |
38 | + | ''' Ejecuta varias veces la funcion random_walks. |
39 | Parametros: | |
40 | - | if not id in self.nodos: |
40 | + | *grafo: el grafo sobre el cual se aplicara la funcion |
41 | - | self.vertices[id] = {} |
41 | + | *cantidad: la cantidad de veces que se hara random_walks |
42 | - | self.personajes[valor] = id |
42 | + | *id: es la id origen, por defecto es None |
43 | - | self.cant_vertices += 1 |
43 | + | *rang_walk: es el rango del random_walks |
44 | - | self.nodos[id] = Nodo_Grafo(id, valor) |
44 | + | *recomendados: es un booleano que indica si se esta utilizando para la funcion recomendados |
45 | - | self.nodos[id].nombre = valor |
45 | + | Salida: |
46 | Devuelve una lista con los id's que mas aparecen en los recorridos randoms, | |
47 | - | def __contains__(self, id): |
47 | + | en caso de que recomendados = True devolvera una lista con los que aparecen |
48 | - | ''' Determina si el grafo contiene un vertice con el identificador indicado.''' |
48 | + | mas veces en los recorridos a partir del origen, pero no estaran sus |
49 | - | return id in self.vertices.keys() |
49 | + | adyacentes |
50 | ''' | |
51 | - | def cantidad_aristas(self): |
51 | + | cantidad += 1 #Le sumo 1 por el tema de que most_common va desde 0 - cant-1 |
52 | - | return self.cant_aristas |
52 | + | frecuencia = [] |
53 | frecuentes = [] | |
54 | ||
55 | - | def agregar_arista(self, desde, hasta, peso = 1): |
55 | + | if id: |
56 | - | '''Agrega una arista que conecta los vertices indicados. |
56 | + | if not id in grafo: |
57 | - | Parametros: |
57 | + | raise KeyError("No se encuentra el personaje") |
58 | - | * desde y hasta: identificadores de vertices dentro del grafo. Si alguno |
58 | + | for i in range(rang_walk): |
59 | - | de estos no existe dentro del grafo, lanzara KeyError. |
59 | + | id_origen = id |
60 | - | * Peso: valor de peso que toma la conexion. Si no se indica, valdra 1. |
60 | + | lista_aux = grafo.random_walk(CANTIDAD_WALKS, id_origen, True) |
61 | - | Si el grafo es no-dirigido, tambien agregara la arista reciproca. |
61 | + | frecuencia += lista_aux |
62 | - | ''' |
62 | + | |
63 | - | if not desde or not hasta in self.vertices: |
63 | + | if recomendados: |
64 | - | raise KeyError("No se encontro uno de los vertices") |
64 | + | frecuencia = [v for v in frecuencia if v not in grafo.adyacentes(id_origen)] |
65 | - | self.cant_aristas += 1 |
65 | + | apariciones = collections.Counter(frecuencia).most_common(cantidad) |
66 | - | self.vertices[desde][hasta] = peso |
66 | + | |
67 | - | if self.es_dirigido: |
67 | + | for id,aparicion in apariciones: |
68 | - | self.vertices[hasta][desde] = peso |
68 | + | if not id or id == id_origen: continue |
69 | frecuentes.append(id) | |
70 | - | def adyacentes(self, id): |
70 | + | return frecuentes |
71 | - | '''Devuelve una lista con los vertices (identificadores) adyacentes |
71 | + | |
72 | - | al indicado. Si no existe el vertice, se lanzara KeyError |
72 | + | def imprimir_personajes(grafo, ids): |
73 | - | ''' |
73 | + | '''A partir de una lista de ids imprime en pantalla los nombres |
74 | - | if not id in self.vertices: |
74 | + | de cada id respectivamente''' |
75 | - | raise KeyError("No se encontro el vertice") |
75 | + | for i, id in enumerate(ids): |
76 | - | return list(self.vertices[id].keys()) |
76 | + | i += 1 |
77 | nombre = grafo.obtener_personaje(id) | |
78 | - | def obtener_personaje(self, id): |
78 | + | print(str(i)+") "+ nombre) |
79 | - | '''Devuelve el valor de la id''' |
79 | + | |
80 | - | if not id in self.nodos: |
80 | + | def op_recomendados(grafo, personaje, cantidad): |
81 | - | raise KeyError("No se encontro la id") |
81 | + | |
82 | - | return self.nodos[id].nombre |
82 | + | id = grafo.obtener_id(personaje) |
83 | recomendados = frecuencia_random_walks(grafo, int(cantidad), id, True) | |
84 | - | def grado(self): |
84 | + | print("Las recomendaciones respecto de", personaje,"son:") |
85 | - | '''Devuelve el grado total del grafo''' |
85 | + | imprimir_personajes(grafo, recomendados) |
86 | - | grado_total = 0 |
86 | + | |
87 | - | for vertice in self.vertices: |
87 | + | def op_similares(grafo, personaje, cantidad): |
88 | - | for adyacente in Grafo.adyacentes(self, vertice): |
88 | + | id = grafo.obtener_id(personaje) |
89 | - | grado_total += 1 |
89 | + | similares = frecuencia_random_walks(grafo, int(cantidad), id) |
90 | - | return grado_total |
90 | + | personaje = grafo.obtener_personaje(id) |
91 | print("Los similares respecto de", personaje,"son:") | |
92 | - | def obtener_id(self, valor): |
92 | + | imprimir_personajes(grafo, similares) |
93 | - | '''Devuelve la ide del valor''' |
93 | + | |
94 | - | if not valor in self.personajes: |
94 | + | def op_centralidad(grafo, cantidad): |
95 | - | raise KeyError("La No se encontro el nombre") |
95 | + | centrales = frecuencia_random_walks(grafo,int(cantidad), None, False, RANGO_CENTRALIDAD) |
96 | - | return self.personajes[valor] |
96 | + | imprimir_personajes(grafo, centrales) |
97 | ||
98 | - | |
98 | + | def op_camino(grafo, personaje1, personaje2): |
99 | - | def random_walk(self, largo, origen = None, pesado = False): |
99 | + | id1 = grafo.obtener_id(personaje1) |
100 | - | ''' Devuelve una lista con un recorrido aleatorio de grafo. |
100 | + | id2 = grafo.obtener_id(personaje2) |
101 | - | Parametros: |
101 | + | camino = grafo.dijkstra(id1, id2, False) |
102 | - | * largo: El largo del recorrido a realizar |
102 | + | print("El camino es:") |
103 | - | * origen: Vertice (id) por el que se debe comenzar el recorrido. |
103 | + | imprimir_personajes(grafo, camino) |
104 | - | Si origen = None, se comenzara por un vertice al azar. |
104 | + | |
105 | - | * pesado: indica si se tienen en cuenta los pesos de las aristas para determinar |
105 | + | def op_distancia(grafo, personaje): |
106 | - | las probabilidades de movernos de un vertice a uno de sus vecinos (False = todo equiprobable). |
106 | + | id = grafo.obtener_id(personaje) |
107 | - | Devuelve: |
107 | + | orden, padres, vertice = grafo.bfs(id) |
108 | - | Una lista con los vertices (ids) recorridos, en el orden del recorrido. |
108 | + | distancias = {} |
109 | - | ''' |
109 | + | for id, distancia in orden.items(): |
110 | - | if not self.vertices: |
110 | + | distancias.setdefault(distancia, []).append(id) |
111 | - | raise ValueError("No hay vertices en el grafo") |
111 | + | list_distancias = list(distancias.keys()) |
112 | - | recorrido = [] |
112 | + | list_distancias.sort() |
113 | - | cont_recorrido = 0 |
113 | + | for distancia in list_distancias: |
114 | - | if origen: |
114 | + | if distancia == 0: continue |
115 | - | if not origen in self.vertices: |
115 | + | cantidad = len(distancias[distancia]) |
116 | - | raise KeyError("No se encontro el vertice origen") |
116 | + | print("La cantidad de personajes a distancia "+str(distancia)+" es: "+ str(cantidad)) |
117 | - | recorrido.append(origen) |
117 | + | |
118 | - | else: |
118 | + | def desviacion_estandar(grafo, grado_grafo, cantidad_vertices): |
119 | - | lista_claves = list(self.vertices.keys()) |
119 | + | |
120 | - | vertice_random = random.choice(lista_claves) |
120 | + | '''Devuelve la desviacion estandar''' |
121 | - | while not vertice_random: |
121 | + | |
122 | - | vertice_random = random.choice(lista_claves) |
122 | + | sumatoria = 0 |
123 | - | recorrido.append(vertice_random) |
123 | + | for vertice in grafo.vertices: |
124 | grado_vertice = 0 | |
125 | - | vertice_partida = recorrido[cont_recorrido] |
125 | + | for adyacente in grafo.adyacentes(vertice): |
126 | grado_vertice += 1 | |
127 | - | while cont_recorrido < largo: |
127 | + | sumatoria += (grado_vertice - grado_grafo /cantidad_vertices)**2 |
128 | - | if not vertice_partida: break |
128 | + | desvio_estandar = ((1/(cantidad_vertices - 1))* sumatoria)**(0.5) |
129 | - | diccionario_adyacentes = self.vertices[vertice_partida] |
129 | + | return desvio_estandar |
130 | - | if pesado: |
130 | + | |
131 | - | vertice_random = vertice_random_por_peso(diccionario_adyacentes) |
131 | + | |
132 | - | else: |
132 | + | def op_estadisticas(grafo): |
133 | - | lista_claves = list(self.vertices[vertice_partida].keys()) |
133 | + | |
134 | - | vertice_random = random.choice(lista_claves) |
134 | + | cantidad_vertices = grafo.cant_vertices |
135 | - | |
135 | + | cantidad_aristas = grafo.cant_aristas |
136 | - | recorrido.append(vertice_random) |
136 | + | grado_total = grafo.grado() |
137 | - | cont_recorrido+= 1 |
137 | + | desv_std = desviacion_estandar(grafo, grado_total, cantidad_vertices) |
138 | - | vertice_partida = recorrido[cont_recorrido] |
138 | + | numero_max_aristas = cantidad_vertices * (cantidad_vertices - 1) |
139 | ||
140 | print("Cantidad de vertices: {}".format(cantidad_vertices)) | |
141 | - | return recorrido |
141 | + | print("Cantidad de aristas: {}".format(cantidad_aristas)) |
142 | - | |
142 | + | print("Promedio del grado de cada vértice: %.2f" % (grado_total/cantidad_vertices)) |
143 | - | def dijkstra(self, origen, destino, minimo = True): |
143 | + | print("Desvio estándar del grado de cada vértice: %.2f" % (desv_std)) |
144 | print("Densidad del grafo: %.6f" % (cantidad_aristas/numero_max_aristas)) | |
145 | - | '''Devuelve el recorrido dependiendo si es maximo o minimo desde el |
145 | + | |
146 | - | origen hasta el destino, aplicando el algoritmo de Dijkstra. |
146 | + | |
147 | - | Parametros: |
147 | + | def max_freq(list_adyacentes, nodos): |
148 | - | * minimo: indica si el camino devuelto sera el minimo si minimo es True |
148 | + | |
149 | - | devolvera el maximo si es False |
149 | + | mayor_freq = {} |
150 | - | * origen y destino: identificadores de vertices dentro del grafo. |
150 | + | for adyacente in list_adyacentes: #Contador de frecuencia de cada label |
151 | - | Si alguno de estos no existe dentro del grafo, lanzara KeyError. |
151 | + | label = nodos[adyacente].label_act |
152 | - | Devuelve: |
152 | + | if not label in mayor_freq: |
153 | - | * Listado de vertices (identificadores) ordenado con el recorrido, incluyendo |
153 | + | mayor_freq[label] = 0 |
154 | - | a los vertices de origen y destino. En caso que no exista camino entre |
154 | + | mayor_freq[label] += 1 |
155 | - | el origen y el destino, se devuelve None. |
155 | + | |
156 | - | ''' |
156 | + | label_mayor_freq = 0 |
157 | - | heap = [] |
157 | + | frecuencia = 0 |
158 | - | camino = [] |
158 | + | |
159 | - | for vertice in self.vertices: |
159 | + | for label in mayor_freq: # Detector del que tiene mayor frecuencia |
160 | - | nodo = self.nodos[vertice] |
160 | + | if mayor_freq[label] > frecuencia: |
161 | - | nodo.visitado = False |
161 | + | label_mayor_freq = label |
162 | - | nodo.distancia = math.inf |
162 | + | frecuencia = mayor_freq[label] |
163 | - | if vertice == origen: |
163 | + | |
164 | - | heapq.heappush(heap,nodo) |
164 | + | return label_mayor_freq |
165 | - | nodo.distancia = 0 |
165 | + | |
166 | - | while heap: |
166 | + | def _op_comunidades(grafo, nodos): |
167 | - | nodo = heapq.heappop(heap) |
167 | + | |
168 | - | nodo.visitado = True |
168 | + | comunidades = {} #label : [vertices] |
169 | - | vertice = nodo.vertice |
169 | + | for vertice in nodos: |
170 | - | dist = nodo.distancia |
170 | + | nodos[vertice].label = max_freq(grafo.adyacentes(vertice), nodos) |
171 | - | for adyacente in self.vertices[vertice]: |
171 | + | label = nodos[vertice].label |
172 | - | if not adyacente: continue |
172 | + | if not label in comunidades: |
173 | - | peso = self.vertices[vertice][adyacente] |
173 | + | comunidades[label] = [] |
174 | - | nodo_ad = self.nodos[adyacente] |
174 | + | comunidades[label].append(vertice) |
175 | - | if not nodo_ad.visitado and nodo_ad.distancia > (dist + peso): |
175 | + | |
176 | - | |
176 | + | eliminar = [] |
177 | - | if minimo: |
177 | + | for comunidad in comunidades: |
178 | - | nodo_ad.cambiar_dist(dist + peso) |
178 | + | if len(comunidades[comunidad]) <= 4 or len(comunidades[comunidad]) >= 1000: |
179 | - | else: |
179 | + | eliminar.append(comunidad) |
180 | - | nodo_ad.cambiar_dist(dist + 1/peso) |
180 | + | |
181 | - | nodo_ad.cambiar_padre(vertice) |
181 | + | for comunidad in eliminar: |
182 | - | heapq.heappush(heap,nodo_ad) |
182 | + | comunidades.pop(comunidad) |
183 | ||
184 | - | vertice = destino |
184 | + | return comunidades |
185 | - | camino.append(vertice) |
185 | + | |
186 | - | while vertice != origen: |
186 | + | |
187 | - | padre = self.nodos[vertice].padre |
187 | + | def op_comunidades(grafo): |
188 | - | camino.append(padre) |
188 | + | nodos = grafo.nodos |
189 | - | vertice = padre |
189 | + | comunidades = _op_comunidades(grafo, nodos) |
190 | - | return camino |
190 | + | desigualdad = False |
191 | while True: | |
192 | test_comunidad = _op_comunidades(grafo,nodos) | |
193 | if comunidades == test_comunidad: break | |
194 | - | def bfs(self, inicio = None, visitar = None, extra = None): |
194 | + | comunidades = test_comunidad |
195 | for i, comunidad in enumerate(comunidades): | |
196 | - | '''Realiza un recorrido BFS dentro del grafo |
196 | + | print("\n\nCantidad de Integrantes: {}".format(len(comunidades[comunidad]))) |
197 | - | Parametros: |
197 | + | imprimir_personajes(grafo, comunidades[comunidad]) |
198 | - | - inicio: identificador del vertice que se usa como inicio. Si se indica un vertice, el recorrido se comenzara en dicho vertice, |
198 | + | |
199 | - | y solo se seguira hasta donde se pueda (no se seguira con los vertices que falten visitar) |
199 | + | |
200 | - | Salida: |
200 | + | def verificar_personaje(grafo, personaje): |
201 | - | Tupla (padres, orden), donde : |
201 | + | if not personaje in grafo.personajes: |
202 | - | - 'padres' es un diccionario que indica para un identificador, cual es el identificador del vertice padre en el recorrido BFS (None si es el inicio) |
202 | + | intentos = 0 |
203 | - | - 'orden' es un diccionario que indica para un identificador, cual es su orden en el recorrido BFS |
203 | + | while intentos < 5 and not personaje in grafo.personajes: |
204 | - | ''' |
204 | + | personaje = input("El personaje no se encuentra en la base de datos, vuelva a ingresar: ") |
205 | - | padres = {} |
205 | + | personaje = personaje.upper() |
206 | - | orden = {} |
206 | + | intentos += 1 |
207 | if intentos == 5 and not personaje in grafo.personajes: | |
208 | - | for nodo in self.nodos: |
208 | + | return False |
209 | - | nodo = self.nodos[nodo] |
209 | + | return personaje |
210 | - | nodo.visitado = False |
210 | + | |
211 | - | padres[nodo.vertice] = None |
211 | + | def verificar_numero(opcion): |
212 | - | orden[nodo.vertice] = math.inf |
212 | + | if not opcion.isdigit(): |
213 | intentos = 0 | |
214 | - | if inicio: |
214 | + | while intentos < 5 and not opcion.isdigit(): |
215 | - | nodo = self.nodos[inicio] |
215 | + | opcion = input("Vuelva a seleccionar la cantidad: ") |
216 | - | vertice = inicio |
216 | + | intentos += 1 |
217 | - | else: |
217 | + | if intentos == 5 or not opcion.isdigit(): return False |
218 | - | nodos = list(self.nodos.keys()) |
218 | + | return opcion |
219 | - | vertice = random.choice(nodos) |
219 | + | |
220 | - | nodo = self.nodos[vertice] |
220 | + | |
221 | - | vertice_origen = vertice |
221 | + | |
222 | - | padres[vertice] = None |
222 | + | def menu(grafo): |
223 | - | nodo.visitado = True |
223 | + | print("************** MENU - MARVEL ***************") |
224 | - | orden[vertice] = 0 |
224 | + | print("1- Recomendados") |
225 | - | cola = deque([]) |
225 | + | print("2- Similares") |
226 | - | cola.append(nodo) |
226 | + | print("3- Centralidad") |
227 | - | while cola: |
227 | + | print("4- Camino") |
228 | - | nodo = cola.popleft() |
228 | + | print("5- Distancias") |
229 | - | vertice = nodo.vertice |
229 | + | print("6- Estadisticas") |
230 | - | if visitar and not visitar(nodo,extra): break |
230 | + | print("7- Comunidades") |
231 | - | for adyacente in self.vertices[vertice]: |
231 | + | print("8- Salir") |
232 | - | nodo_ad = self.nodos[adyacente] |
232 | + | opcion = input("Ingrese una opcion: ") |
233 | - | if nodo_ad.visitado == False: |
233 | + | print("") |
234 | - | nodo_ad.visitado = True |
234 | + | posibilidades = 0 |
235 | - | cola.append(nodo_ad) |
235 | + | while not opcion in OPCIONES and posibilidades != 5 : |
236 | - | orden[adyacente] = orden[vertice] + 1 |
236 | + | print("Error al ingresar la opcion") |
237 | - | padres[adyacente] = vertice |
237 | + | opcion = input("Ingrese una opcion nuevamente: ") |
238 | posibilidades += 1 | |
239 | - | return (orden, padres, vertice_origen) |
239 | + | |
240 | if posibilidades == 5: return | |
241 | ||
242 | - | class Nodo_Grafo(): |
242 | + | opcion = int(opcion) |
243 | ||
244 | - | def __init__(self, vertice, nombre, distancia = 0, visitado = False, padre = None): |
244 | + | if opcion == 1: |
245 | - | self.vertice = vertice |
245 | + | print("************** Recomendados ***************") |
246 | - | self.distancia = distancia |
246 | + | personaje = input("Ingrese el nombre del personaje: ") |
247 | - | self.visitado = visitado |
247 | + | personaje = personaje.upper() |
248 | - | self.padre = padre |
248 | + | personaje = verificar_personaje(grafo, personaje) |
249 | - | self.nombre = nombre |
249 | + | if not personaje: return |
250 | - | self.label_act = int(vertice) |
250 | + | cantidad = input("Ingrese cantidad de recomendados: ") |
251 | cantidad = verificar_numero(cantidad) | |
252 | - | def visitado(self): |
252 | + | if not cantidad: return |
253 | - | return self.visitado |
253 | + | op_recomendados(grafo, personaje, cantidad) |
254 | ||
255 | - | def cambiar_dist(self, distancia_nueva): |
255 | + | elif opcion == 2: |
256 | - | self.distancia = distancia_nueva |
256 | + | print("************** Similares ***************") |
257 | personaje = input("Ingrese el nombre del personaje: ") | |
258 | - | def cambiar_padre(self, padre_nuevo): |
258 | + | personaje = personaje.upper() |
259 | - | self.padre = padre_nuevo |
259 | + | personaje = verificar_personaje(grafo, personaje) |
260 | if not personaje: return | |
261 | - | def __lt__(self,otro): |
261 | + | cantidad = input("Ingrese cantidad de similares: ") |
262 | - | return self.distancia < otro.distancia |
262 | + | cantidad = verificar_numero(cantidad) |
263 | if not cantidad: return | |
264 | - | def __gt__(self,otro): |
264 | + | op_similares(grafo, personaje, cantidad) |
265 | - | return self.distancia > otro.distancia |
265 | + | |
266 | elif opcion == 3: | |
267 | - | def __eq__(self,otro): |
267 | + | print("************** Centralidad ***************") |
268 | - | return self.distancia == otro.distancia |
268 | + | cantidad = input("Ingrese cantidad de personajes centrales: ") |
269 | cantidad = verificar_numero(cantidad) | |
270 | - | def __str__(self): |
270 | + | if not cantidad: return |
271 | - | return str(self.vertice)+"; "+str(self.distancia) |
271 | + | op_centralidad(grafo, cantidad) |
272 | ||
273 | elif opcion == 4: | |
274 | - | def vertice_random_por_peso(diccionario_adyacentes): |
274 | + | print("************** Camino ***************") |
275 | - | '''Devuelve un vertice adyacente random, con altas prioridades de que su peso sea mayor al de los demas''' |
275 | + | personaje1 = input("Ingrese el nombre del personaje de origen: ") |
276 | personaje1 = personaje1.upper() | |
277 | - | total = sum(diccionario_adyacentes.values()) |
277 | + | personaje1 = verificar_personaje(grafo, personaje1) |
278 | - | rand = random.uniform(0, total) |
278 | + | if not personaje1: return |
279 | - | acum = 0 |
279 | + | personaje2 = input("Ingrese el nombre del personaje de destino: ") |
280 | - | for vertice, peso_arista in diccionario_adyacentes.items(): |
280 | + | personaje2 = personaje2.upper() |
281 | - | if acum + peso_arista >= rand: |
281 | + | personaje2 = verificar_personaje(grafo, personaje2) |
282 | - | return vertice |
282 | + | if not personaje2: return |
283 | - | acum += peso_arista |
283 | + | op_camino(grafo, personaje1, personaje2) |
284 | ||
285 | elif opcion == 5: | |
286 | print("************** Distancias ***************") | |
287 | personaje = input("Ingrese el nombre del personaje: ") | |
288 | personaje = personaje.upper() | |
289 | personaje = verificar_personaje(grafo, personaje) | |
290 | if not personaje: return | |
291 | op_distancia(grafo, personaje) | |
292 | ||
293 | elif opcion == 6: | |
294 | print("************** Estadisticas ***************") | |
295 | op_estadisticas(grafo) | |
296 | ||
297 | elif opcion == 7: | |
298 | print("************** Comunidades ***************") | |
299 | op_comunidades(grafo) | |
300 | ||
301 | elif opcion == 8: return | |
302 | ||
303 | ||
304 | def main(): | |
305 | ruta = sys.argv[1] | |
306 | grafo = crear_grafo(ruta) | |
307 | menu(grafo) | |
308 | ||
309 | main() |