Implementación de Algoritmos de Búsqueda Heurística y Minimax en Python
Enviado por Chuletator online y clasificado en Informática y Telecomunicaciones
Escrito el en
español con un tamaño de 5,15 KB
Algoritmos de Búsqueda Informada y Estratégica
1. Búsqueda Voraz (Greedy Search)
Propiedades: Completo, no óptimo. Complejidad de tiempo y espacio: O(b*m).
def busquedavoraz(nodoInicial):
objetivo = False
abiertos = []
sucesores = []
raiz = nodoInicial()
abiertos.append(raiz)
while not objetivo and len(abiertos) != 0:
nodo = abiertos.pop(0)
if testObjetivo(nodo.estado):
objetivo = True
else:
sucesores = expandir(nodo)
for nodosucesor in sucesores:
posicion = 0
heu = heuristica(nodosucesor.estado)
while posicion < len(abiertos) and (heuristica(abiertos[posicion].estado) < heu):
posicion += 1
abiertos.insert(posicion, nodosucesor)
if objetivo:
dispSolucion(nodo)
elif not objetivo:
print("No se ha encontrado una solución\n")
return objetivo2. Búsqueda Voraz con Control de Repetidos
Implementación que utiliza un conjunto de cerrados para gestionar la exploración de estados ya visitados mediante hashing.
def busquedavorazrepetidos() -> bool: # f(n) = h(n)
objetivo = False
abiertos = []
sucesores = []
cerrados = set()
raiz = nodoInicial()
abiertos.append(raiz)
while not objetivo and len(abiertos) != 0:
nodo = abiertos.pop(0)
if testObjetivo(nodo.estado):
objetivo = True
else:
# Se añade el hash del nodo a la lista de cerrados
cerrados.add(nodo.estado.calcular_hash())
sucesores = expandir(nodo)
for nodosucesor in sucesores:
# Se comprueba que el hash del nodo sucesor no esté en dicha lista
if nodosucesor.estado.calcular_hash() not in cerrados:
posicion = 0
heu = heuristica(nodosucesor.estado)
while posicion < len(abiertos) and (heuristica(abiertos[posicion].estado) < heu):
posicion += 1
abiertos.insert(posicion, nodosucesor)
if objetivo:
dispSolucion(nodo)
elif not objetivo:
print("No ha sido posible encontrar una solución\n")
return objetivo3. Búsqueda A* con Distancia Manhattan
Propiedades: Completo y óptimo cuando la heurística es admisible (no sobreestima el coste real).
Complejidad de tiempo y espacio: O(b*m); si la heurística es admisible, se define como O(b^d).
def busquedaAmanhattan(): # f(n) = g(n) + h(n)
objetivo = False
abiertos = []
sucesores = []
cerrados = {}
raiz = nodoInicial()
abiertos.append(raiz)
while not objetivo and len(abiertos) != 0:
nodo = abiertos.pop(0)
if testObjetivo(nodo.estado):
objetivo = True
else:
# Si el estado no está en cerrados o se encuentra un camino mejor (menor coste total)
if (nodo.estado.calcular_hash() not in cerrados or
cerrados[nodo.estado.calcular_hash()] > (nodo.costeCamino + manhattan(nodo.estado))):
sucesores = expandir(nodo)
abiertos += sucesores
abiertos.sort() # Ordena la lista según f(n) = g(n) + h(n)
# Guarda el mejor coste encontrado para ese estado
cerrados[nodo.estado.calcular_hash()] = nodo.costeCamino + manhattan(nodo.estado)
if objetivo:
dispSolucion(nodo)
elif not objetivo:
print("No ha sido posible encontrar la solución\n")
return objetivo4. Algoritmo Minimax para Juegos
Complejidad: O(b^m). Este algoritmo es fundamental en la toma de decisiones para juegos de suma cero.
def minimax(nodo: Nodo) -> Nodo:
mejor_accion = None
mejor_utilidad = float('-inf')
inicial = estadoinicial(nodo)
# Por cada acción posible desde el nodo inicial
for accion in nodo.acciones(inicial):
resultado = nodo.resultado(inicial, accion)
utilidad = valormin(resultado) # Valor del nivel MIN
if utilidad > mejor_utilidad:
mejor_accion = accion
mejor_utilidad = utilidad
return mejor_accion
def valormin(nodo: Nodo) -> int:
if terminal(nodo):
return utilidad(nodo)
valor_min = float('inf')
for jugada in jugadas:
if esvalida(nodo, jugada):
valor_min = min(
valor_min,
valormax(aplicaJugada(nodo, jugada), opuesto(jugador))
)
return valor_min
def valormax(nodo: Nodo, jugador: int) -> int:
if terminal(nodo):
return utilidad(nodo)
valor_max = float('-inf')
for jugada in jugadas:
if esvalida(nodo, jugada):
valor_max = max(
valor_max,
valormin(aplicaJugada(nodo, jugada), opuesto(jugador))
)
return valor_max