Advertisement
Guest User

Untitled

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