Mundo de la aspiradora¶
Este notebook presenta un agente que interactúa en el mundo de la aspiradora, tal como se presenta en Russel & Norvig (2021). Una versión más compleja de este mundo puede encontrarse en
Describiremos la forma en que se puede crear este mundo, para que un agente aspiradora actúe en éste.
Definición de los cuartos¶
En primer lugar construiremos los cuartos o cuadrados en los que va interactuar el agente aspiradora. El ambiente se conformará de un conjunto de cuartos dispuestos en ciertas posiciones.
class Square(object):
def __init__(self, name):
"""
Crea un objeto square, que representa los cuadrados del ambiente.
Argumentos
----------
name : str
Nombre del cuadrado ('A', 'B', etc.)
"""
self.name = name
self.dirt = 0
# Hasta que no se coloque con cuadrados vecinos, los movimientos no llevan a ningún lado
self.left = self
self.right = self
self.up = self
self.down = self
def __str__(self):
return self.name
Creación del ambiente¶
El ambiente del mundo de la aspiradora consta de un conjunto de cuadros estructurados en diferentes posiciones; estos cuadros pueden estar al lado de otros, o bien abajo o arriba de estos.
En este ejemplo, consideramos un mundo con cuatro cuadros en los que se puede posicionar el agente. El agente puede moverse en 4 posiciones, izquierda, derecha, arriba y abajo. La configuración en los cuartos que exploramos está configurada de la siguiente forma:
$$[A] [B] \\ [C] [D]$$
Los nombres de los cuartos son A, B, C y D. Los cuadros A y B están en la parte superior y C y D en la parte inferior. A y C están del lado izquierdo y B, D del lado derecho. Asimismo, uno o ambos cuadrados pueden estar sucios (lo que se indica con 1) o limpios (indicado con 0). El ambiente indicará, de manera, aleatoria qué cuadrado está o no sucio.
import random
random.seed(12345)
class VacuumWorld(object):
def __init__(self, dirt_init='random'):
"""
Objeto que crea el ambiente para el mundo de la aspiradora:
Se conforma de:
- Dos cuadrados: A y B (A a la izquierda de B)
- Indicación de la limpieza (0) o suciedad (1) de los cuadrados.
Argumentos
----------
dirt_init : str
Forma en que se inicializará la suciedad de los cuadrados.
"""
self.squares = []
self.A,self.B,self.C,self.D = Square('A'),Square('B'),Square('C'),Square('D')
self.squares.append(self.A)
self.squares.append(self.B)
self.squares.append(self.C)
self.squares.append(self.D)
#Configuración de los cuartos
self.A.left,self.A.right,self.A.up,self.A.down = self.A,self.B,self.A,self.C
self.B.left,self.B.right,self.B.up,self.B.down = self.A,self.B,self.B,self.D
self.C.left,self.C.right,self.C.up,self.C.down = self.C,self.D,self.A,self.C
self.D.left,self.D.right,self.D.up,self.D.down = self.C,self.D,self.B,self.D
#Inicialización de suciedad
self.dirt_init = dirt_init
self.initialize_dirt()
def __str__(self):
return '[({},{}) ({},{})]\n[({},{}) ({},{})]'.format(self.A.name,self.A.dirt, self.B.name,self.B.dirt,
self.C.name,self.C.dirt, self.D.name,self.D.dirt)
def initialize_dirt(self):
"""
Inicializa la suciedad de los cuadrados:
Opciones (se indican en init)
--------
random : Inicializa con uno de los cuadrados sucios y otro limpio de forma aleatoria.
dirty : Inicializa con los dos cuadrados sucios
clean : Inicializa con los dos cuadrados limpios
"""
if self.dirt_init=='random':
for square in self.squares:
if random.random() > 0.5:
square.dirt = 1
else:
square.dirt = 0
elif self.dirt_init=='dirty':
for square in self.squares:
square.dirt = 1
else:
for square, value in zip(self.squares, self.dirt_init):
square.dirt = value
Creación del ambiente¶
Finalmente, podemos crear el ambiente y observar como se comporta la suciedad en ésta. Cada cuarto tiene asociado un 0 (limpio) o un 1 (sucio).
env = VacuumWorld(dirt_init='random')
print(env)
[(A,0) (B,0)] [(C,1) (D,0)]
Creación del agente¶
El agente será un objeto que pueda interactuar con el ambiente. Este se compondrá de los siguientes elementos:
- Sensores: El agente tiene acceso a la información del lugar (cuadrado) en que está y si este cuadrado está sucio.
- Actuadores: El agente puede realizar las siguientes acciones:
- Moverse a la izquierda ('Left').
- Moverse a la derecha ('Right').
- Moverse hacia arriba ('Up').
- Moverse hacia abajo ('Down').
- Limpiar ('Clean').
class Agent(VacuumWorld):
"""
Agente de aspiradora. Cuyas acciones son limpiar, o moverse en las cuatro direcciones.
Asimismo, el agente guarda una secuencia de percepciones.
"""
def __init__(self, location=None):
self.location = location
self.perceptions = [(self.location.name, self.location.dirt)]
def act(self,action):
"""Función para actuar"""
if action == 'Clean':
self.location.dirt = 0
self.perceptions.append((self.location.name,self.location.dirt))
elif action == 'Left':
self.location = self.location.left
self.perceptions.append((self.location.name,self.location.dirt))
elif action == 'Right':
self.location = self.location.right
self.perceptions.append((self.location.name,self.location.dirt))
elif action == 'Up':
self.location = self.location.up
self.perceptions.append((self.location.name,self.location.dirt))
elif action == 'Down':
self.location = self.location.down
self.perceptions.append((self.location.name,self.location.dirt))
else:
print('No es una acción permitida')
Ahora podemos generar el agente posicionándolo en alguno de los cuartos del ambiente.
agent = Agent(location=env.A)
print(env)
print(agent.location)
[(A,0) (B,0)] [(C,1) (D,0)] A
Asimismo, el agente puede realizar acciones que se le indiquen, de tal forma que estas afecten a la disposición del ambiente:
agent.act(action='Clean')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
agent.act(action='Right')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
agent.act(action='Clean')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
agent.act(action='Down')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
agent.act(action='Clean')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
agent.act(action='Left')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
agent.act(action='Clean')
print('Ambiente después de la acción:\n{} {}'.format(env,agent.location))
Ambiente después de la acción: [(A,0) (B,0)] [(C,1) (D,0)] A Ambiente después de la acción: [(A,0) (B,0)] [(C,1) (D,0)] B Ambiente después de la acción: [(A,0) (B,0)] [(C,1) (D,0)] B Ambiente después de la acción: [(A,0) (B,0)] [(C,1) (D,0)] D Ambiente después de la acción: [(A,0) (B,0)] [(C,1) (D,0)] D Ambiente después de la acción: [(A,0) (B,0)] [(C,1) (D,0)] C Ambiente después de la acción: [(A,0) (B,0)] [(C,0) (D,0)] C
Finalmente, podemos ver que el agente guarda una secuencia de percepciones:
print(agent.perceptions)
[('A', 0), ('A', 0), ('B', 0), ('B', 0), ('D', 0), ('D', 0), ('C', 1), ('C', 0)]