Advertisement
tomasfdel

Complementos I Práctica Lab 3

Sep 12th, 2017
505
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.77 KB | None | 0 0
  1. #! /usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. from practica2 import *
  4.  
  5. # 3ra Practica Laboratorio
  6. # Complementos Matematicos I
  7. # Consigna: Implementar los siguientes metodos
  8.  
  9.  
  10. '''
  11. Recordatorio:
  12. - Un camino/ciclo es Euleriano si contiene exactamente 1 vez
  13. a cada arista del grafo
  14. - Un camino/ciclo es Hamiltoniano si contiene exactamente 1 vez
  15. a cada vértice del grafo
  16. '''
  17.  
  18.  
  19. #Falta armar los TypeError y ver de hacer más lindo el código.
  20.  
  21.  
  22. def check_is_hamiltonian_trail(graph, path):
  23.     """Comprueba si una lista de aristas constituye un camino hamiltoniano
  24.    en un grafo.
  25.  
  26.    Args:
  27.        graph (grafo): Grafo en formato de listas.
  28.                       Ej: (['a', 'b', 'c'], [('a', 'b'), ('b', 'c')])
  29.  
  30.        path (lista de aristas): posible camino
  31.                                 Ej: [('a', 'b'), ('b', 'c')]
  32.                                
  33.    Returns:
  34.        boolean: path es camino hamiltoniano en graph
  35.  
  36.    Raises:
  37.        TypeError: Cuando el tipo de un argumento es inválido
  38.    """
  39.     if len(path) == 0:
  40.         if len(graph[0]) == 0:
  41.             return True
  42.         return False
  43.    
  44.     for prueba in path:
  45.         flag = 0
  46.         for arista in graph[1]:
  47.             if prueba == arista:
  48.                 flag = 1
  49.                 break
  50.         if flag == 0:
  51.             return False
  52.    
  53.    
  54.     usosDeVertices = [0 for x in range(len(graph[0]))]
  55.     for (indice, vert) in enumerate(graph[0]):
  56.         if vert == path[0][0]:
  57.             usosDeVertices[indice] += 1
  58.             break
  59.    
  60.     for arista in path:
  61.         for (indice, vert) in enumerate(graph[0]):
  62.             if vert == arista[1]:
  63.                 usosDeVertices[indice] += 1
  64.                 break
  65.    
  66.     for contador in usosDeVertices:
  67.         if contador != 1:
  68.             return False
  69.    
  70.     return True
  71.  
  72.  
  73. def check_is_hamiltonian_circuit(graph, path):
  74.     """Comprueba si una lista de aristas constituye un ciclo hamiltoniano
  75.    en un grafo.
  76.  
  77.    Args:
  78.        graph (grafo): Grafo en formato de listas.
  79.                       Ej: (['a', 'b', 'c'], [('a', 'b'), ('b', 'c')])
  80.  
  81.        path (lista de aristas): posible ciclo
  82.                                 Ej: [('a', 'b'), ('b', 'c')]
  83.  
  84.    Returns:
  85.        boolean: path es ciclo hamiltoniano en graph
  86.  
  87.    Raises:
  88.        TypeError: Cuando el tipo de un argumento es inválido
  89.    """
  90.     if len(path) == 0:
  91.         if len(graph[0]) == 0:
  92.             return True
  93.         return False
  94.    
  95.     for prueba in path:
  96.         flag = 0
  97.         for arista in graph[1]:
  98.             if prueba == arista:
  99.                 flag = 1
  100.                 break
  101.         if flag == 0:
  102.             return False
  103.    
  104.    
  105.     usosDeVertices = [0 for x in range(len(graph[0]))]
  106.     for (indice, vert) in enumerate(graph[0]):
  107.         if vert == path[0][0]:
  108.             usosDeVertices[indice] += 1
  109.             break
  110.    
  111.     for arista in path:
  112.         for (indice, vert) in enumerate(graph[0]):
  113.             if vert == arista[1]:
  114.                 usosDeVertices[indice] += 1
  115.                 break
  116.    
  117.     for (indice, contador) in enumerate(usosDeVertices):
  118.         if graph[0][indice] == path[0][0]:
  119.             if contador != 2:
  120.                 return False
  121.         else:
  122.             if contador != 1:
  123.                 return False
  124.    
  125.     return True
  126.  
  127.  
  128. def check_is_eulerian_trail(graph, path):
  129.     """Comprueba si una lista de aristas constituye un camino euleriano
  130.    en un grafo.
  131.  
  132.    Args:
  133.        graph (grafo): Grafo en formato de listas.
  134.                       Ej: (['a', 'b', 'c'], [('a', 'b'), ('b', 'c')])
  135.  
  136.        path (lista de aristas): posible camino
  137.                                 Ej: [('a', 'b'), ('b', 'c')]
  138.  
  139.    Returns:
  140.        boolean: path es camino euleriano en graph
  141.  
  142.    Raises:
  143.        TypeError: Cuando el tipo de un argumento es inválido
  144.    """
  145.     if len(path) == 0:
  146.         if len(graph[0]) == 0:
  147.             return True
  148.         return False
  149.    
  150.     usosDeVertices = [0 for x in range(len(graph[0]))]
  151.     usosDeAristas = [0 for x in range(len(graph[1]))]
  152.     for (numero, prueba) in enumerate(path):
  153.         if (numero != len(path) - 1) and path[numero][1] !=  path[numero + 1][0]:
  154.             return False
  155.         flag = 0
  156.         for (indice, arista) in enumerate(graph[1]):
  157.             if prueba == arista:
  158.                 flag = 1
  159.                 usosDeAristas[indice] += 1
  160.                 break
  161.                
  162.         for (indice, vertice) in enumerate(graph[0]):
  163.             if vertice == prueba[0]:
  164.                 usosDeVertices[indice] += 1
  165.             if vertice == prueba[1]:
  166.                 usosDeVertices[indice] += 1
  167.            
  168.         if flag == 0:
  169.             return False
  170.            
  171.     for contador in usosDeVertices:
  172.         if contador == 0:
  173.             return False
  174.            
  175.     for contador in usosDeAristas:
  176.         if contador != 1:
  177.             return False
  178.  
  179.     return True
  180.  
  181.  
  182. def check_is_eulerian_circuit(graph, path):
  183.     """Comprueba si una lista de aristas constituye un ciclo euleriano
  184.    en un grafo.
  185.  
  186.    Args:
  187.        graph (grafo): Grafo en formato de listas.
  188.                       Ej: (['a', 'b', 'c'], [('a', 'b'), ('b', 'c')])
  189.  
  190.        path (lista de aristas): posible ciclo
  191.                                 Ej: [('a', 'b'), ('b', 'c')]
  192.  
  193.    Returns:
  194.        boolean: path es ciclo euleriano en graph
  195.  
  196.    Raises:
  197.        TypeError: Cuando el tipo de un argumento es inválido
  198.    """
  199.     if check_is_eulerian_trail(graph, path) and (len(path) == 0 or path[0][0] == path[len(path)-1][1]):
  200.         return True
  201.     return False
  202.    
  203.    
  204. def graph_has_eulerian_circuit(graph):
  205.     """Comprueba si un grafo no dirigido tiene un circuito euleriano.
  206.  
  207.    Args:
  208.        graph (grafo): Grafo en formato de listas.
  209.                       Ej: (['a', 'b', 'c'], [('a', 'b'), ('b', 'c')])
  210.  
  211.    Returns:
  212.        boolean: graph tiene un circuito euleriano
  213.  
  214.    Raises:
  215.        TypeError: Cuando el tipo del argumento es inválido
  216.    """
  217.     if len(componentes_conexas(graph)) > 1:
  218.         return False
  219.    
  220.     gradosDeVertices = [0 for x in range(len(graph[0]))]
  221.    
  222.     for (vert1, vert2) in graph[1]:
  223.         for (indice, vertice) in enumerate(graph[0]):
  224.             if vertice == vert1:
  225.                 gradosDeVertices[indice] += 1
  226.             if vertice == vert2:
  227.                 gradosDeVertices[indice] += 1
  228.        
  229.     for grado in gradosDeVertices:
  230.         if grado % 2 == 1:
  231.             return False
  232.            
  233.     return True
  234.  
  235.  
  236. def estan_conectados(graph, vertA, vertB):
  237.     for (indice, arista) in enumerate(graph[1]):
  238.         if (arista[0] == vertA and arista[1] == vertB) or (arista[0] == vertB and arista[1] == vertA):
  239.             return indice
  240.     return -1
  241.  
  242. def verticeQueNoEs (vertice, arista):
  243.     if vertice == arista[0]:
  244.         return arista[1]
  245.     return arista[0]
  246.  
  247. def find_eulerian_circuit(graph):
  248.     """Obtiene un circuito euleriano en un grafo no dirigido, si es posible
  249.  
  250.    Args:
  251.        graph (grafo): Grafo en formato de listas.
  252.                       Ej: (['a', 'b', 'c'], [('a', 'b'), ('b', 'c')])
  253.  
  254.    Returns:
  255.        path (lista de aristas): circuito euleriano, si existe
  256.        None: si no existe un circuito euleriano
  257.  
  258.    Raises:
  259.        TypeError: Cuando el tipo del argumento es inválido
  260.    """
  261.     if len(componentes_conexas(graph)) > 1:
  262.         return None
  263.        
  264.     aristasRestantes = graph[1]
  265.     verticeInicial = graph[0][0]
  266.     verticeActual = graph[0][0]
  267.     camino = []
  268.        
  269.     while aristasRestantes != []:
  270.         print camino
  271.         posiblesAristas = []
  272.         for vertice in graph[0]:
  273.             conexion = estan_conectados( (graph[0], aristasRestantes), verticeActual, vertice)
  274.             if conexion != -1:
  275.                 compConexasActuales = len(componentes_conexas((graph[0], aristasRestantes)))
  276.                 compConexasNuevas = len(componentes_conexas((graph[0], aristasRestantes[:conexion] + aristasRestantes[conexion+1:])))
  277.                 if compConexasNuevas > compConexasActuales :
  278.                     puente = True
  279.                 else:
  280.                     puente = False
  281.                
  282.                 posiblesAristas = posiblesAristas + [(aristasRestantes[conexion], conexion, puente)]
  283.                
  284.                
  285.         if posiblesAristas == []:
  286.             break
  287.         else:
  288.             flag = 0
  289.             for opcion in posiblesAristas:
  290.                 if opcion[2] == False:
  291.                     flag = 1
  292.                     verticeActual = verticeQueNoEs(verticeActual, opcion[0])
  293.                     camino = camino + [opcion[0]]
  294.                     aristasRestantes = aristasRestantes[:opcion[1]] + aristasRestantes[opcion[1]+1:]
  295.                     break
  296.                    
  297.             if flag == 0:
  298.                 verticeActual = verticeQueNoEs(verticeActual, posiblesAristas[0][0])
  299.                 camino = camino + [posiblesAristas[0][0]]
  300.                 aristasRestantes = aristasRestantes[:posiblesAristas[0][1]] + aristasRestantes[posiblesAristas[0][1]+1:]
  301.                
  302.            
  303.                
  304.     if len(camino) == len(graph[1]) and verticeActual == verticeInicial:
  305.         return camino
  306.    
  307.     return None
  308.  
  309.  
  310. def main():
  311.     grafo = (['A'] , [('A','A')])
  312.     print(find_eulerian_circuit(grafo))
  313.     print()
  314.     print()
  315.     grafo = (['A','B','C','D'], [('A','A'),('A','B'),('B','C'),('C','D'),('D','A'),('B','D'),('A','C'),('A','D'),('B','C')])
  316.     print(find_eulerian_circuit(grafo))
  317.     print()
  318.     print()
  319.     grafo = (['A','B','C','D','E','F','G'], [('A','D'),('A','B'),('B','C'),('D','C'),('E','C'),('G','C'),('E','F'),('G','F')] )
  320.     print(find_eulerian_circuit(grafo))
  321.     print()
  322.     print()
  323.  
  324. if __name__ == '__main__':
  325.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement