Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions busquedas.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,19 @@ def es_meta(estado):
class Nodo:
"""
Clase para implementar un árbol como estructura de datos.

"""
def __init__(self, estado, accion=None, padre=None, costo_local=0):
def __init__(self, estado, problema, accion=None, padre=None, costo_local=0):
"""
Inicializa un nodo como una estructura

@param estado: El estado del nodo.
@param problema: El problema que se está resolviendo.
@param accion: La acción que llevó a este nodo.
@param padre: El nodo padre.
@param costo_local: El costo local de alcanzar este nodo.
"""
self.estado = estado
self.problema = problema
self.accion = accion
self.padre = padre
self.costo = 0 if not padre else padre.costo + costo_local
Expand All @@ -120,11 +125,11 @@ def expande(self, modelo):
@param modelo: Un objeto de una clase heredada de ModeloBusqueda

@return: Una lista de posibles nodos sucesores

"""
return (
Nodo(
modelo.sucesor(self.estado, a),
self.problema, # Pasamos el problema a los nodos hijos
a,
self,
modelo.costo_local(self.estado, a))
Expand All @@ -134,8 +139,7 @@ def genera_plan(self):
"""
Genera el plan (parcial o completo) que representa el nodo.

@return: Una lista [(x0, c0), a1, (x1, c1), a2, (x2, c2), ..., aT, (xT, cT)], donde los x0, x1, ..., xT son tuplas con los estados a cada paso del plan, c0, c1, ..., cT es el costo total hasta ese momento del plan, a1, a2, ..., aT son las acciónes que hay que implementar para llegar desde el estado inicial x0 hasta el testado final xT

@return: Una lista con el plan generado
"""
return ([(self.estado, self.costo)] if not self.padre else
(self.padre.genera_plan()
Expand All @@ -144,7 +148,6 @@ def genera_plan(self):
def __str__(self):
"""
Muestra el nodo como lo que es en realidad, un plan.

"""
plan = self.genera_plan()
return (f"Costo: {self.costo}\n" +
Expand All @@ -154,12 +157,14 @@ def __str__(self):
for (x, a, xp)
in zip(plan[:-1:2], plan[1::2], plan[2::2])]))

# Este método de sobrecarga del operador < es necesario
# para poder utilizar los nodos en la heapq
def __lt__(self, other):
"""
Sobrecarga del operador < para poder usar los nodos en la heapq.
"""
return self.profundidad < other.profundidad



def busqueda_ancho(problema):
"""
Búsqueda a lo ancho para un problema de búsquedas dado
Expand Down Expand Up @@ -283,5 +288,21 @@ def busqueda_A_estrella(problema, heuristica):
@return Un objeto tipo Nodo con la estructura completa

"""
raise NotImplementedError('Hay que hacerlo de tarea \
(problema 2 en el archivo busquedas.py)')
frontera = []
nodo_inicial = Nodo(problema.x0)
heapq.heappush(frontera, (heuristica(nodo_inicial),nodo_inicial))
visitados = {problema.x0: 0}

while frontera:
_, nodo = heapq.heappop(frontera) # Extrae el nodo con menor f(n)

if problema.es_meta(nodo.estado): # Si es la meta, regresa la solución
nodo.nodos_visitados = problema.num_nodos
return nodo

for hijo in nodo.expande(problema.modelo):
costo_hijo = hijo.costo + heuristica(hijo) # f(n) = g(n) + h(n)

if hijo.estado not in visitados or visitados[hijo.estado] > hijo.costo:
heapq.heappush(frontera, (costo_hijo, hijo))
visitados[hijo.estado] = hijo.costo
78 changes: 35 additions & 43 deletions problemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@

import busquedas



# ------------------------------------------------------------
# Desarrolla el modelo del Camión mágico
# ------------------------------------------------------------

class CamionMagico.busquedas.ModeloBusqueda):
"""
class CamionMagico(busquedas.ModeloBusqueda):
"""
---------------------------------------------------------------------------------
Supongamos que quiero trasladarme desde la posición discreta $1$ hasta
la posicion discreta $N$ en una vía recta usando un camión mágico.
Expand All @@ -28,42 +26,48 @@ class CamionMagico.busquedas.ModeloBusqueda):
de 2 minutos.

Desarrollar la clase del modelo del camión mágico
----------------------------------------------------------------------------------

----------------------------------------------------------------------------------
"""
def __init__(self):
raise NotImplementedError('Hay que hacerlo de tarea')
def __init__(self, N):
self.N = N

def acciones_legales(self, estado):
raise NotImplementedError('Hay que hacerlo de tarea')
acciones = []
if estado + 1 <= self.N:
acciones.append("caminar")
if 2 * estado <= self.N:
acciones.append("saltar")
return acciones

def sucesor(self, estado, accion):
raise NotImplementedError('Hay que hacerlo de tarea')
"""Devolver el estado al hacer una accion"""
if accion == "caminar":
return estado + 1
elif accion == "saltar":
return 2 * estado

def costo_local(self, estado, accion):
raise NotImplementedError('Hay que hacerlo de tarea')
"""costo de la accion"""
return 1 if accion == "caminar" else 2

@staticmethod
def bonito(estado):
"""
El prettyprint de un estado dado

"""
raise NotImplementedError('Hay que hacerlo de tarea')

# ------------------------------------------------------------
# Desarrolla el problema del Camión mágico
# ------------------------------------------------------------

class PblCamionMágico(busquedas.ProblemaBusqueda):
class PblCamionMagico(busquedas.ProblemaBusqueda):
"""
El problema a resolver es establecer un plan para ir desde el
punto $1$ hasta el punto $N$ en el menor tiempo posible.

"""
def __init__(self):
raise NotImplementedError('Hay que hacerlo de tarea')

def __init__(self, N):
super().__init__(1, lambda estado: estado == N, CamionMagico(N))

# ------------------------------------------------------------
# Desarrolla una política admisible.
Expand All @@ -73,10 +77,8 @@ def h_1_camion_magico(nodo):
"""
DOCUMENTA LA HEURÍSTICA QUE DESARROLLES Y DA UNA JUSTIFICACIÓN
PLATICADA DE PORQUÉ CREES QUE LA HEURÍSTICA ES ADMISIBLE

"""
return 0

return nodo.problema.N - nodo.estado # Distancia hasta la meta

# ------------------------------------------------------------
# Desarrolla otra política admisible.
Expand All @@ -88,15 +90,15 @@ def h_2_camion_magico(nodo):
"""
DOCUMENTA LA HEURÍSTICA DE DESARROLLES Y DA UNA JUSTIFICACIÓN
PLATICADA DE PORQUÉ CREES QUE LA HEURÍSTICA ES ADMISIBLE

"""
return 0
x = nodo.estado
return (nodo.problema.N - x) // x # Estimación de número de saltos

# ------------------------------------------------------------
# Desarrolla el modelo del cubo de Rubik
# ------------------------------------------------------------

class CuboRubik.busquedas.ModeloBusqueda):
class CuboRubik(busquedas.ModeloBusqueda):
"""
La clase para el modelo de cubo de rubik, documentación, no olvides poner
la documentación de forma clara y concisa.
Expand All @@ -120,50 +122,45 @@ def costo_local(self, estado, accion):
def bonito(estado):
"""
El prettyprint de un estado dado

"""
raise NotImplementedError('Hay que hacerlo de tarea')
# ------------------------------------------------------------

# ------------------------------------------------------------
# Desarrolla el problema del Cubo de Rubik
# ------------------------------------------------------------

class PblCuboRubik(busquedas.ProblemaBusqueda):
"""
El problema a resolver es establecer un plan para resolver el cubo de rubik.

"""
def __init__(self):
raise NotImplementedError('Hay que hacerlo de tarea')


# ------------------------------------------------------------
# Desarrolla una política admisible.
# ------------------------------------------------------------
def h_1_problema_1(nodo):

def h_1_camion_magico(nodo):
"""
DOCUMENTA LA HEURÍSTICA QUE DESARROLLES Y DA UNA JUSTIFICACIÓN
PLATICADA DE PORQUÉ CREES QUE LA HEURÍSTICA ES ADMISIBLE

"""
return 0

problema = nodo.problema
return problema.N - nodo.estado # Distancia hasta la meta

# ------------------------------------------------------------
# Desarrolla otra política admisible.
# Analiza y di porque piensas que es (o no es) dominante una
# respecto otra política
# ------------------------------------------------------------

def h_2_problema_1(nodo):
"""
DOCUMENTA LA HEURÍSTICA DE DESARROLLES Y DA UNA JUSTIFICACIÓN
PLATICADA DE PORQUÉ CREES QUE LA HEURÍSTICA ES ADMISIBLE

"""
return 0



def compara_metodos(problema, heuristica_1, heuristica_2):
"""
Compara en un cuadro lo nodos expandidos y el costo de la solución
Expand All @@ -177,7 +174,6 @@ def compara_metodos(problema, heuristica_1, heuristica_2):

Si la búsqueda no informada es muy lenta, posiblemente tendras que quitarla
de la función

"""
solucion1 = busquedas.busqueda_A_estrella(problema, heuristica_1)
solucion2 = busquedas.busqueda_A_estrella(problema, heuristica_2)
Expand All @@ -193,17 +189,13 @@ def compara_metodos(problema, heuristica_1, heuristica_2):
+ str(solucion2.nodos_visitados))
print('-' * 50 + '\n\n')


if __name__ == "__main__":


# Compara los métodos de búsqueda para el problema del camión mágico
# con las heurísticas que desarrollaste
problema = PblCamionMágico( XXXXXXXXXX ) # <--- PONLE LOS PARÁMETROS QUE NECESITES
problema = PblCamionMagico(10) # Ejemplo con N=10
compara_metodos(problema, h_1_camion_magico, h_2_camion_magico)

# Compara los métodos de búsqueda para el problema del cubo de rubik
# con las heurísticas que desarrollaste
problema = PblCuboRubik( XXXXXXXXXX ) # <--- PONLE LOS PARÁMETROS QUE NECESITES
problema = PblCuboRubik() # Asegúrate de tener los parámetros necesarios
compara_metodos(problema, h_1_problema_1, h_2_problema_1)