Advertisement
Guest User

Untitled

a guest
Dec 5th, 2016
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # 99192 OTERO - 99373 ALVAREZ,     JORGE COLLINET
  2. import sys
  3. from grafo import Grafo
  4. import heapq
  5. import collections
  6. import re
  7. RANGO_WALKS = 100
  8. CANTIDAD_WALKS = 50
  9. RANGO_CENTRALIDAD = 700
  10. OPCIONES = ['1','2','3','4','5','6','7','8']
  11.  
  12. def crear_grafo(ruta):
  13.     ''' Recibe una ruta de un archivo y devuelve un grafo a partir de sus datos
  14.        PRE: la ruta debe existir, el archivo debe ser de la siguiente manera:
  15.            Vertices cant
  16.            .
  17.            .
  18.            Arcs*
  19.            .
  20.    '''
  21.     with open(ruta) as archivo:
  22.         grafo = Grafo(True)
  23.         for i,linea in enumerate(archivo):
  24.             if i == 0: continue
  25.             linea = linea.rstrip("\n")
  26.             if linea == "*Arcs": break
  27.             vertice = linea.split(" ", 1)
  28.             vertice[1] = vertice[1].rstrip('"')
  29.             vertice[1] = vertice[1].lstrip('"')
  30.             grafo.__setitem__(vertice[0], vertice[1])
  31.         for linea in archivo:
  32.             linea = linea.rstrip("\n")
  33.             arista = linea.split(" ")
  34.             grafo.agregar_arista(arista[0],arista[1],int(arista[2]))
  35.     return grafo
  36.  
  37.    
  38. def frecuencia_random_walks(grafo, cantidad , id = None, recomendados = False,  rang_walk = RANGO_WALKS):
  39.     ''' Ejecuta varias veces la funcion random_walks.
  40.      Parametros:
  41.       *grafo: el grafo sobre el cual se aplicara la funcion
  42.       *cantidad: la cantidad de veces que se hara random_walks
  43.       *id: es la id origen, por defecto es None
  44.       *rang_walk: es el rango del random_walks
  45.       *recomendados: es un booleano que indica si se esta utilizando para la funcion recomendados
  46.      Salida:
  47.        Devuelve una lista con los id's que mas aparecen en los recorridos randoms,
  48.        en caso de que recomendados = True devolvera una lista con los que aparecen
  49.        mas veces en los recorridos a partir del origen, pero no estaran sus                    
  50.        adyacentes
  51.    '''
  52.     cantidad += 1 #Le sumo 1 por el tema de que most_common va desde 0 - cant-1
  53.     frecuencia = []
  54.     frecuentes = []
  55.    
  56.     if id:
  57.         if not id in grafo:
  58.             raise KeyError("No se encuentra el personaje")
  59.     for i in range(rang_walk):    
  60.         id_origen = id
  61.         lista_aux = grafo.random_walk(CANTIDAD_WALKS, id_origen, True)
  62.         frecuencia += lista_aux
  63.        
  64.     if recomendados:
  65.         frecuencia = [v for v in frecuencia if v not in grafo.adyacentes(id_origen)]
  66.     apariciones = collections.Counter(frecuencia).most_common(cantidad)
  67.    
  68.     for id,aparicion in apariciones:
  69.         if not id or id == id_origen: continue
  70.         frecuentes.append(id)
  71.     return frecuentes
  72.    
  73. def imprimir_personajes(grafo, ids):
  74.     '''A partir de una lista de ids imprime en pantalla los nombres
  75.       de cada id respectivamente'''
  76.     for i, id in enumerate(ids):
  77.         i += 1
  78.         nombre = grafo.obtener_personaje(id)
  79.         print(str(i)+") "+ nombre)
  80.    
  81. def op_recomendados(grafo, personaje, cantidad):
  82.  
  83.     id = grafo.obtener_id(personaje)
  84.     recomendados = frecuencia_random_walks(grafo, int(cantidad), id, True)
  85.     print("Las recomendaciones respecto de", personaje,"son:")
  86.     imprimir_personajes(grafo, recomendados)
  87.        
  88. def op_similares(grafo, personaje, cantidad):
  89.     id = grafo.obtener_id(personaje)
  90.     similares = frecuencia_random_walks(grafo, int(cantidad), id)
  91.     personaje = grafo.obtener_personaje(id)
  92.     print("Los similares respecto de", personaje,"son:")
  93.     imprimir_personajes(grafo, similares)
  94.            
  95. def op_centralidad(grafo, cantidad):
  96.     centrales = frecuencia_random_walks(grafo,int(cantidad), None, False, RANGO_CENTRALIDAD)
  97.     imprimir_personajes(grafo, centrales)
  98.        
  99. def op_camino(grafo, personaje1, personaje2):
  100.     id1 = grafo.obtener_id(personaje1)
  101.     id2 = grafo.obtener_id(personaje2)
  102.     camino = grafo.dijkstra(id1, id2, False)
  103.     print("El camino es:")
  104.     imprimir_personajes(grafo, camino)
  105.    
  106. def op_distancia(grafo, personaje):
  107.     id = grafo.obtener_id(personaje)
  108.     orden, padres, vertice = grafo.bfs(id)
  109.     distancias = {}
  110.     for id, distancia in orden.items():
  111.         distancias.setdefault(distancia, []).append(id)
  112.     list_distancias = list(distancias.keys())
  113.     list_distancias.sort()
  114.     for distancia in list_distancias:
  115.         if distancia == 0: continue
  116.         cantidad = len(distancias[distancia])
  117.         print("La cantidad de personajes a distancia "+str(distancia)+" es: "+ str(cantidad))
  118.  
  119. def desviacion_estandar(grafo, grado_grafo, cantidad_vertices):  
  120.  
  121.     '''Devuelve la desviacion estandar'''
  122.    
  123.     sumatoria = 0
  124.     for vertice in grafo.vertices:
  125.         grado_vertice = 0
  126.         for adyacente in grafo.adyacentes(vertice):
  127.             grado_vertice += 1
  128.         sumatoria += (grado_vertice - grado_grafo /cantidad_vertices)**2
  129.     desvio_estandar = ((1/(cantidad_vertices - 1))* sumatoria)**(0.5)
  130.     return desvio_estandar
  131.    
  132.    
  133. def op_estadisticas(grafo):
  134.    
  135.     cantidad_vertices = grafo.cant_vertices
  136.     cantidad_aristas = grafo.cant_aristas
  137.     grado_total = grafo.grado()
  138.     desv_std = desviacion_estandar(grafo, grado_total, cantidad_vertices)
  139.     numero_max_aristas = cantidad_vertices * (cantidad_vertices - 1)
  140.    
  141.     print("Cantidad de vertices: {}".format(cantidad_vertices))
  142.     print("Cantidad de aristas: {}".format(cantidad_aristas))
  143.     print("Promedio del grado de cada vértice: %.2f" % (grado_total/cantidad_vertices))
  144.     print("Desvio estándar del grado de cada vértice: %.2f" % (desv_std))
  145.     print("Densidad del grafo: %.6f" % (cantidad_aristas/numero_max_aristas))
  146.  
  147.  
  148. def max_freq(list_adyacentes, nodos):
  149.    
  150.     mayor_freq = {}
  151.     for adyacente in list_adyacentes: #Contador de frecuencia de cada label
  152.         label = nodos[adyacente].label_act
  153.         if not label in mayor_freq:
  154.             mayor_freq[label] = 0
  155.         mayor_freq[label] += 1
  156.  
  157.     label_mayor_freq = 0
  158.     frecuencia = 0
  159.    
  160.     for label in mayor_freq: # Detector del que tiene mayor frecuencia
  161.         if mayor_freq[label] > frecuencia:
  162.             label_mayor_freq = label
  163.             frecuencia = mayor_freq[label]
  164.            
  165.     return label_mayor_freq
  166.  
  167. def _op_comunidades(grafo, nodos):
  168.    
  169.     comunidades = {} #label : [vertices]
  170.     for vertice in nodos:
  171.         nodos[vertice].label = max_freq(grafo.adyacentes(vertice), nodos)
  172.         label = nodos[vertice].label
  173.         if not label in comunidades:
  174.             comunidades[label] = []
  175.         comunidades[label].append(vertice)
  176.        
  177.     eliminar = []
  178.     for comunidad in comunidades:
  179.         if len(comunidades[comunidad]) <= 4 or len(comunidades[comunidad]) >= 1000:
  180.             eliminar.append(comunidad)
  181.    
  182.     for comunidad in eliminar:
  183.         comunidades.pop(comunidad)
  184.        
  185.     return comunidades
  186.  
  187.  
  188. def op_comunidades(grafo):
  189.     nodos = grafo.nodos
  190.     comunidades = _op_comunidades(grafo, nodos)
  191.     desigualdad = False
  192.     while True:
  193.         test_comunidad = _op_comunidades(grafo,nodos)
  194.         if comunidades == test_comunidad: break
  195.         comunidades = test_comunidad
  196.     for i, comunidad in enumerate(comunidades):
  197.         print("\n\nCantidad de Integrantes: {}".format(len(comunidades[comunidad])))
  198.         imprimir_personajes(grafo, comunidades[comunidad])
  199.    
  200.    
  201. def verificar_personaje(grafo, personaje):
  202.     if not personaje in grafo.personajes:
  203.         intentos = 0
  204.         while intentos < 5 and not personaje in grafo.personajes:
  205.             personaje = input("El personaje no se encuentra en la base de datos, vuelva a ingresar: ")
  206.             personaje = personaje.upper()
  207.             intentos += 1
  208.         if intentos == 5 and not personaje in grafo.personajes:
  209.             return False
  210.     return personaje
  211.    
  212. def verificar_numero(opcion):
  213.     if not opcion.isdigit():
  214.         intentos = 0
  215.         while intentos < 5 and not opcion.isdigit():
  216.             opcion = input("Vuelva a seleccionar la cantidad: ")
  217.             intentos += 1
  218.         if intentos == 5 or not opcion.isdigit(): return False
  219.     return opcion
  220.        
  221.    
  222.    
  223. def menu(grafo):
  224.     print("************** MENU - MARVEL ***************")
  225.     print("1- Recomendados")
  226.     print("2- Similares")
  227.     print("3- Centralidad")
  228.     print("4- Camino")
  229.     print("5- Distancias")
  230.     print("6- Estadisticas")
  231.     print("7- Comunidades")
  232.     print("8- Salir")
  233.     opcion = input("Ingrese una opcion: ")
  234.     print("")
  235.     posibilidades = 0
  236.     while not opcion in OPCIONES and posibilidades != 5 :
  237.         print("Error al ingresar la opcion")
  238.         opcion = input("Ingrese una opcion nuevamente: ")
  239.         posibilidades += 1
  240.  
  241.     if posibilidades == 5: return
  242.    
  243.     opcion = int(opcion)
  244.    
  245.     if opcion == 1:
  246.         print("************** Recomendados ***************")
  247.         personaje = input("Ingrese el nombre del personaje: ")
  248.         personaje = personaje.upper()
  249.         personaje = verificar_personaje(grafo, personaje)
  250.         if not personaje: return
  251.         cantidad = input("Ingrese cantidad de recomendados: ")
  252.         cantidad = verificar_numero(cantidad)
  253.         if not cantidad: return
  254.         op_recomendados(grafo, personaje, cantidad)
  255.        
  256.     elif opcion == 2:
  257.         print("************** Similares ***************")
  258.         personaje = input("Ingrese el nombre del personaje: ")
  259.         personaje = personaje.upper()
  260.         personaje = verificar_personaje(grafo, personaje)
  261.         if not personaje: return
  262.         cantidad = input("Ingrese cantidad de similares: ")
  263.         cantidad = verificar_numero(cantidad)
  264.         if not cantidad: return
  265.         op_similares(grafo, personaje, cantidad)
  266.    
  267.     elif opcion == 3:
  268.         print("************** Centralidad ***************")
  269.         cantidad = input("Ingrese cantidad de personajes centrales: ")
  270.         cantidad = verificar_numero(cantidad)
  271.         if not cantidad: return
  272.         op_centralidad(grafo, cantidad)
  273.    
  274.     elif opcion == 4:  
  275.         print("************** Camino ***************")
  276.         personaje1 = input("Ingrese el nombre del personaje de origen: ")
  277.         personaje1 = personaje1.upper()
  278.         personaje1 = verificar_personaje(grafo, personaje1)
  279.         if not personaje1: return
  280.         personaje2 = input("Ingrese el nombre del personaje de destino: ")
  281.         personaje2 = personaje2.upper()
  282.         personaje2 = verificar_personaje(grafo, personaje2)
  283.         if not personaje2: return
  284.         op_camino(grafo, personaje1, personaje2)
  285.        
  286.  
  287.  
  288.  
  289.  
  290.  
  291.     elif opcion == 5:
  292.         print("************** Distancias ***************")
  293.         personaje = input("Ingrese el nombre del personaje: ")
  294.         personaje = personaje.upper()
  295.         personaje = verificar_personaje(grafo, personaje)
  296.         if not personaje: return
  297.         op_distancia(grafo, personaje)
  298.        
  299.     elif opcion == 6:
  300.         print("************** Estadisticas ***************")
  301.         op_estadisticas(grafo)
  302.        
  303.     elif opcion == 7:
  304.         print("************** Comunidades ***************")
  305.         op_comunidades(grafo)
  306.  
  307.     elif opcion == 8: return
  308.        
  309.        
  310. def main():
  311.     ruta = sys.argv[1]
  312.     grafo = crear_grafo(ruta)
  313.     menu(grafo)
  314.            
  315. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement