Fecha límite de entrega: Viernes 17 de Mayo antes de la medianoche
Cerciórese de reiniciar y correr el notebook en su totalidad antes de enviarlo. Verifique que todas las salidas se muestran de manera correcta.
Integrantes del grupo (máximo 3):
Instrucciones de envío:
Este notebook debe enviarse a través del siguiente File Request antes de la medianoche de la fecha límite. El archivo debe nombrarse como isi-taller1-unalusername1-unalusername2-unalusername3.ipynb, donde unalusername es el nombre de usuario asignado por la universidad (incluya los nombres de usuario de todos los miembros del grupo).
El objetivo de este taller es construir un agente que planea que sea capaz de jugar el juego de Snake:
El agente tendrá acceso a todo el estado del ambiente. Debe usar esta información para hacer un plan y después actuar de acuerdo a este.
Para esto vamos a usar como base este proyecto desarrollado por Yuriy Guts.
En este caso vamos a utilizar la clase Environment
tal como está definida en el paquete snakeai.gameplay.environment
. El método get_observation()
retorna una arreglo de numpy
con la información de todo el campo de juego.
Se debe modelar el problema de encontrar un plan (secuencia de acciones) para la serpiente como un problema de búsqueda. En particular el problema de búsqueda debe recibir la configuración actual del tablero la cual corresponde al estado inicial, las acciones corresponden a las acciones que puede ejecutar la serpiente, los estados finales son aquellos en que la serpiente se come la fruta.
El estado se debe representar como una tupla con el estado del tablero y el de la serpiente (una instancia de la clase Snake
del paquete snakeai.gameplay.entities
)
import numpy as np
from snakeai.gameplay.entities import SnakeAction, Snake
class SnakeProblem(object):
"""The abstract class for a formal problem. A new domain subclasses this,
overriding `actions` and `results`, and perhaps other methods.
The default heuristic is 0 and the default action cost is 1 for all states.
When yiou create an instance of a subclass, specify `initial`, and `goal` states
(or give an `is_goal` method) and perhaps other keyword args for the subclass."""
def __init__(self, initial=None, **kwds):
self.__dict__.update(initial=initial, **kwds)
def actions(self, state):
raise NotImplementedError
def result(self, state, action):
raise NotImplementedError
def is_goal(self, state):
raise NotImplementedError
def action_cost(self, s, a, s1):
return 1
def h(self, node):
return 0
def __str__(self):
return '{}({!r}, {!r})'.format(
type(self).__name__, self.initial, self.goal)
initial = (
np.array([[4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[4, 0, 0, 0, 4, 0, 0, 0, 0, 4],
[4, 0, 1, 4, 4, 4, 4, 4, 0, 4],
[4, 0, 4, 4, 4, 0, 4, 0, 0, 4],
[4, 0, 0, 0, 4, 2, 0, 0, 0, 4],
[4, 0, 0, 0, 0, 3, 0, 4, 0, 4],
[4, 0, 0, 4, 4, 3, 0, 4, 1, 4],
[4, 0, 0, 0, 4, 3, 0, 4, 0, 4],
[4, 0, 0, 4, 4, 3, 0, 0, 0, 4],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4]]),
Snake(Point(11, 5), length=5)
)
problem = SnakeProblem(initial=initial)
problem.result(initial, SnakeAction.MAINTAIN_DIRECTION)
from snakeai.gameplay.environment import Environment
inicial = {
"field": [
"##########",
"#...#....#",
"#.O#####.#",
"#.###.#..#",
"#...#S...#",
"#....s.#.#",
"#..##s.#.#",
"#...#s.#.#",
"#..##s...#",
"##########"
],
"initial_snake_length": 3,
"max_step_limit": 1000,
"rewards": {
"timestep": 0,
"ate_fruit": 1,
"died": -1
}
}
env = Environment(config=inicial, verbose=0)
env.new_episode()
env.get_observation()
array([[4, 4, 4, 4, 4, 4, 4, 4, 4, 4], [4, 0, 0, 0, 4, 0, 0, 0, 0, 4], [4, 0, 1, 4, 4, 4, 4, 4, 0, 4], [4, 0, 4, 4, 4, 0, 4, 0, 0, 4], [4, 0, 0, 0, 4, 2, 0, 0, 0, 4], [4, 0, 0, 0, 0, 3, 0, 4, 0, 4], [4, 0, 0, 4, 4, 3, 0, 4, 1, 4], [4, 0, 0, 0, 4, 3, 0, 4, 0, 4], [4, 0, 0, 4, 4, 3, 0, 0, 0, 4], [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]])
Escriba diferentes funciones para resolver el problema de búsqueda usando BFS e IDS. Pruebe el algoritmo con diferentes configuraciones del problema (diferentes tamaños del tablero, obstáculos, longitudes de la serpiente, etc.). Evalue y discuta los resultados.
def solveProblemBFS(problem):
"""
Recibe una instancia de SnakeProblem y retorna una lista con la secuencia de acciones que resuelve el problema.
La solución debe ser óptima (mínimo número de pasos).
"""
solucion = []
return solucion
def solveProblemIDS(problem):
"""
Recibe una instancia de SnakeProblem y retorna una lista con la secuencia de acciones que resuelve el problema.
La solución debe ser óptima (mínimo número de pasos).
"""
solucion = []
return solucion
Escriba una función para resolver el problema de búsqueda usando A*. Prueba al menos dos funciones heurísticas diferentes. Las heurísticas deben ser admisibles. Pruebe el algoritmo con diferentes configuraciones del problema (diferentes tamaños del tablero, obstáculos, longitudes de la serpiente, etc.). Evalue y discuta los resultados.
def solveProblemAStar_h1(problem):
"""
Recibe una instancia de SnakeProblem y retorna una lista con la secuencia de acciones que resuelve el problema.
La solución debe ser óptima (mínimo número de pasos).
"""
solucion = []
return solucion
def solveProblemAStar_h2(problem):
"""
Recibe una instancia de SnakeProblem y retorna una lista con la secuencia de acciones que resuelve el problema.
La solución debe ser óptima (mínimo número de pasos).
"""
solucion = []
return solucion
Desarrolle un agente para jugar Snake que construya un plan cada vez que aparece una nueva fruta. El agente debe precalcular el plan y después ejecutarlo. Cuando termine de ejecutar las acciones del plan, debe volver a calcular un nuevo plan.
from snakeai.agent import AgentBase
class MasterMindPlanningAgent(AgentBase):
""" Represents a Snake agent that takes a random action at every step. """
def __init__(self):
pass
def begin_episode(self):
pass
def act(self, observation, reward):
raise NotImplementedError
def plan(self, observation):
raise NotImplementedError
def end_episode(self):
pass
Utilice el siguiente código para ejecutar el agente. Evaluelo en diferentes tableros iniciales. Reporte las estadísticas y compare el desempeño con los agentes al azar y reactivos de la Práctica 1. Analice y discuta los resultados.
from snakeai.gameplay.entities import ALL_SNAKE_ACTIONS, Point
import numpy as np
import random
class EnvironmentFull(Environment):
"""
Full observation environment. Same as base class environment, overloads
`get_observation` so that it returns the Field array and the Snake.
(From Environment doc): Represents the RL environment for the Snake game that implements the game logic,
provides rewards for the agent and keeps track of game statistics.
"""
def __init__(self, config, verbose=0):
super().__init__(config, verbose)
def get_observation(self):
""" Observe the state of the environment. """
return (np.copy(self.field._cells), self.snake)
def show_field(self):
return self.field.__str__()
def play(env, agent, num_episodes=1, verbose=1):
"""
Play a set of episodes using the specified Snake agent.
Use the non-interactive command-line interface and print the summary statistics afterwards.
Args:
env: an instance of Snake environment.
agent: an instance of Snake agent.
num_episodes (int): the number of episodes to run.
"""
fruit_stats = []
print()
print('Playing:')
for episode in range(num_episodes):
timestep = env.new_episode()
agent.begin_episode()
game_over = False
step = 0
while not game_over:
if verbose > 0:
print("------ Step ", step, " ------")
print (env.show_field())
print ("Observation:", env.get_observation())
print ("Head:", env.snake.head)
print ("Direction:", env.snake.direction)
step += 1
action = agent.act(timestep.observation, timestep.reward)
env.choose_action(action)
timestep = env.timestep()
game_over = timestep.is_episode_end
fruit_stats.append(env.stats.fruits_eaten)
summary = '******* Episode {:3d} / {:3d} | Timesteps {:4d} | Fruits {:2d}'
print(summary.format(episode + 1, num_episodes, env.stats.timesteps_survived, env.stats.fruits_eaten))
print()
print('Fruits eaten {:.1f} +/- stddev {:.1f}'.format(np.mean(fruit_stats), np.std(fruit_stats)))
inicial = {
"field": [
"#######",
"#.....#",
"#.....#",
"#..S..#",
"#.....#",
"#.....#",
"#######"
],
"initial_snake_length": 2,
"max_step_limit": 1000,
"rewards": {
"timestep": -0.01,
"ate_fruit": 1,
"died": -1
}
}
env = EnvironmentFull(config=inicial, verbose=0)
agent = MasterMindPlanningAgent()
play(env, agent, num_episodes= 10, verbose=0)