diff --git a/entornos_o.py b/entornos_o.py index 7345329..a636153 100644 --- a/entornos_o.py +++ b/entornos_o.py @@ -1,125 +1,125 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -entornos_o.py ------------- - -Entornos y agentes desde una prespectiva OO - -""" - -__author__ = 'juliowaissman' - -class Entorno: - """ - Clase abstracta para entornos - - En realidad funciona como un contenedor de funciones - - """ - - def __init__(self, x0=[]): - """ - Inicializa la clase con el estado inicial como una lista - - """ - self.x = x0[:] - self.costo = 0 - - def acción_legal(self, accion): - """ - @param acción: Una accion en el entorno - - @return: True si accion es legal en estado, False en caso contrario - - Por default acepta cualquier acción. - - """ - return True - - def transición(self, accion): - """ - @param accion: Uno de los elementos de acciones_legales( estado) - - Modifica self.x y self.costo - - """ - pass - - def percepcion(self): - """ - @return: Tupla con los valores que se perciben del entorno por - default el estado completo - - """ - return self.x - - -class Agente(object): - """ - Clase abstracta para un agente que interactua con un - entorno discreto determinista observable. - - """ - - def programa(self, percepcion): - """ - @param percepcion: Lista con los valores que se perciben de un entorno - - @return: accion: Acción seleccionada por el agente. - - """ - pass - - -def simulador(entorno, agente, pasos=10, verbose=True): - """Realiza la simulación de un agente actuando en un entorno de forma genérica - - @param entorno: Un objeto de la clase Entorno - @param agente: Un objeto de la clase Agente - @param pasos: Un int con el número de pasos a simular - @param verbose: Si True, imprime el resultado de la simulación - - @retrun (historial_estados, historial_acciones, - historial_desempeño) donde cada una es una lista con los - estados, acciones y medida de desempeño encontradas a lo - largo de la simulación. - - """ - historial_costo = [entorno.costo] - historial_estados = [entorno.x[:]] - historial_acciones = [] - - for _ in range(pasos): - p = entorno.percepcion() - a = agente.programa(p) - entorno.transicion(a) - - historial_costo.append(entorno.costo) - historial_estados.append(entorno.x[:]) - historial_acciones.append(a) - - historial_acciones.append(None) - - if verbose: - print(u"\n\nSimulación de entorno tipo " + - str(type(entorno)) + - " con el agente tipo " + - str(type(agente)) + "\n") - - print('Paso'.center(10) + - 'Estado'.center(40) + - u'Acción'.center(25) + - u'Costo'.center(15)) - - print('_' * (10 + 40 + 25 + 15)) - - for i in range(pasos): - print(str(i).center(10) + - str(historial_estados[i]).center(40) + - str(historial_acciones[i]).center(25) + - str(historial_costo[i]).rjust(12)) - - print('_' * (10 + 40 + 25 + 15) + '\n\n') - - return historial_estados, historial_acciones, historial_costo +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import copy +""" +entornos_o.py +------------ + +Entornos y agentes desde una prespectiva OO + +""" + +__author__ = 'juliowaissman' + +class Entorno: + """ + Clase abstracta para entornos + + En realidad funciona como un contenedor de funciones + + """ + + def __init__(self, x0=[]): + """ + Inicializa la clase con el estado inicial como una lista + + """ + self.x = x0[:] + self.costo = 0 + + def acción_legal(self, accion): + """ + @param acción: Una accion en el entorno + + @return: True si accion es legal en estado, False en caso contrario + + Por default acepta cualquier acción. + + """ + return True + + def transición(self, accion): + """ + @param accion: Uno de los elementos de acciones_legales( estado) + + Modifica self.x y self.costo + + """ + pass + + def percepcion(self): + """ + @return: Tupla con los valores que se perciben del entorno por + default el estado completo + + """ + return self.x + + +class Agente(object): + """ + Clase abstracta para un agente que interactua con un + entorno discreto determinista observable. + + """ + + def programa(self, percepcion): + """ + @param percepcion: Lista con los valores que se perciben de un entorno + + @return: accion: Acción seleccionada por el agente. + + """ + pass + + +def simulador(entorno, agente, pasos=10, verbose=True): + """Realiza la simulación de un agente actuando en un entorno de forma genérica + + @param entorno: Un objeto de la clase Entorno + @param agente: Un objeto de la clase Agente + @param pasos: Un int con el número de pasos a simular + @param verbose: Si True, imprime el resultado de la simulación + + @return (historial_estados, historial_acciones, historial_desempeño) + donde cada una es una lista con los estados, acciones y medidas de desempeño + encontradas a lo largo de la simulación. + """ + historial_costo = [entorno.costo] + historial_estados = [copy.deepcopy(entorno.x)] # Copia profunda del estado inicial + historial_acciones = [] + + for _ in range(pasos): + p = entorno.percepcion() # Obtenemos la percepción (estado actual) + # Pasamos el entorno completo al agente, no solo la percepción + a = agente.programa([entorno] + list(p)) # Ahora pasamos tanto el entorno como la percepción + entorno.transicion(a) + + historial_costo.append(entorno.costo) + historial_estados.append(copy.deepcopy(entorno.x)) # Copia profunda del estado actual + historial_acciones.append(a) + + historial_acciones.append(None) + + if verbose: + print(u"\n\nSimulación de entorno tipo " + + str(type(entorno)) + + " con el agente tipo " + + str(type(agente)) + "\n") + + print('Paso'.center(10) + + 'Estado'.center(40) + + u'Acción'.center(25) + + u'Costo'.center(15)) + + print('_' * (10 + 40 + 25 + 15)) + + for i in range(pasos): + print(str(i).center(10) + + str(historial_estados[i]).center(40) + + str(historial_acciones[i]).center(25) + + str(historial_costo[i]).rjust(12)) + + print('_' * (10 + 40 + 25 + 15) + '\n\n') + + return historial_estados, historial_acciones, historial_costo diff --git a/nuevecuartos.py b/nuevecuartos.py new file mode 100644 index 0000000..c451afc --- /dev/null +++ b/nuevecuartos.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +nuevecuartos.py +---------------- + +Entorno con tres pisos y tres cuartos por piso. +Basado en entornos_o.py. + +""" + +import entornos_o +from random import choice + + +__author__ = 'Miguel Cruz Duarte' + + +class NueveCuartos(entornos_o.Entorno): + def __init__(self, x0=None): + """ + Inicializa el entorno con un estado inicial dado, o por defecto todos los cuartos sucios y el agente en 1A. + """ + if x0 is None: + x0 = { + "robot": "1A", + "estado_cuartos": { + f"{piso}{cuarto}": "sucio" + for piso in range(1, 4) + for cuarto in "ABC" + } + } + self.x = x0 # Ahora es un diccionario, no una lista + self.costo = 0 + + def accion_legal(self, accion): + """ + Verifica si una acción es legal en el estado actual. + """ + robot = self.x["robot"] + piso, cuarto = int(robot[0]), robot[1] + + if accion == "ir_Derecha": + return cuarto != "C" + elif accion == "ir_Izquierda": + return cuarto != "A" + elif accion == "subir": + return piso < 3 and cuarto == "C" + elif accion == "bajar": + return piso > 1 and cuarto == "A" + elif accion in ["limpiar", "nada"]: + return True + return False + + def transicion(self, accion): + """ + Cambia el estado del entorno según la acción. + """ + if not self.accion_legal(accion): + raise ValueError(f"La acción '{accion}' no es legal para este estado.") + + robot = self.x["robot"] + piso, cuarto = int(robot[0]), robot[1] + estado_cuartos = self.x["estado_cuartos"] + + if accion == "ir_Derecha": + self.x["robot"] = f"{piso}{chr(ord(cuarto) + 1)}" + self.costo += 2 + elif accion == "ir_Izquierda": + self.x["robot"] = f"{piso}{chr(ord(cuarto) - 1)}" + self.costo += 2 + elif accion == "subir": + self.x["robot"] = f"{piso + 1}A" + self.costo += 5 + elif accion == "bajar": + self.x["robot"] = f"{piso - 1}C" + self.costo += 5 + elif accion == "limpiar": + estado_cuartos[robot] = "limpio" + self.costo += 1 + elif accion == "nada": + self.costo += 0 + + def percepcion(self): + """ + Devuelve la percepción del agente: posición y estado del cuarto actual. + """ + robot = self.x["robot"] + return robot, self.x["estado_cuartos"][robot] + + +class AgenteAleatorioNueveCuartos(entornos_o.Agente): + def __init__(self): + self.acciones = ["ir_Derecha", "ir_Izquierda", "subir", "bajar", "limpiar", "nada"] + + def programa(self, percepcion): + entorno = percepcion[0] # Aquí estamos obteniendo el objeto completo del entorno + # Filtra las acciones legales según el entorno completo + acciones_legales = [ + accion for accion in self.acciones if entorno.accion_legal(accion) + ] + return choice(acciones_legales) if acciones_legales else "nada" + + +class AgenteReactivoNueveCuartos(entornos_o.Agente): + """ + Un agente reactivo simple para el entorno de nueve cuartos. + """ + def programa(self, percepcion): + print("Percepción:", percepcion) + # Desempaquetar la percepción correctamente + robot, situacion = percepcion # Percepción solo contiene robot y estado de cuarto + + # Implementar la lógica de acción dependiendo del estado percibido + if situacion == "sucio": + return "limpiar" + elif robot.endswith("C") and int(robot[0]) < 3: + return "subir" + elif robot.endswith("A") and int(robot[0]) > 1: + return "bajar" + elif robot.endswith("A"): + return "ir_Derecha" + elif robot.endswith("B"): + return "ir_Derecha" + elif robot.endswith("C"): + return "ir_Izquierda" + return "nada" + + +class AgenteReactivoModeloNueveCuartos(entornos_o.Agente): + """ + Un agente reactivo basado en modelo para el entorno de nueve cuartos. + """ + def __init__(self): + """ + Inicializa el modelo interno. + """ + self.modelo = {"robot": "1A", + "estado_cuartos": {f"{piso}{cuarto}": "sucio" + for piso in range(1, 4) + for cuarto in "ABC"}} + + def programa(self, percepcion): + robot, situacion = percepcion + + # Actualiza el modelo interno + self.modelo["robot"] = robot + self.modelo["estado_cuartos"][robot] = situacion + + # Decide en base al modelo + estado_cuartos = self.modelo["estado_cuartos"] + if all(estado == "limpio" for estado in estado_cuartos.values()): + return "nada" + elif situacion == "sucio": + return "limpiar" + elif robot.endswith("C") and int(robot[0]) < 3: + return "subir" + elif robot.endswith("A") and int(robot[0]) > 1: + return "bajar" + elif robot.endswith("A"): + return "ir_Derecha" + elif robot.endswith("B"): + return "ir_Derecha" + elif robot.endswith("C"): + return "ir_Izquierda" + return "nada" + + +def test(): + """ + Prueba del entorno y los agentes. + """ + print("Prueba del entorno con un agente aleatorio") + entornos_o.simulador(NueveCuartos(), + AgenteAleatorioNueveCuartos(), + 100) + + print("Prueba del entorno con un agente reactivo") + entornos_o.simulador(NueveCuartos(), + AgenteReactivoNueveCuartos(), + 100) + + print("Prueba del entorno con un agente reactivo con modelo") + entornos_o.simulador(NueveCuartos(), + AgenteReactivoModeloNueveCuartos(), + 100) + +if __name__ == "__main__": + test() \ No newline at end of file diff --git a/tarea_1.py b/tarea_1.py index d43959f..d86df6a 100755 --- a/tarea_1.py +++ b/tarea_1.py @@ -1,18 +1,18 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" -tarea_1.py ------------- - -Revisa el archivo README.md con las instrucciones de la tarea. - -""" -__author__ = 'escribe_tu_nombre' - -import entornos_f -import entornos_o - -# Requiere el modulo entornos_f.py o entornos_o.py -# Usa el modulo doscuartos_f.py para reutilizar código -# Agrega los modulos que requieras de python - +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +tarea_1.py +------------ + +Revisa el archivo README.md con las instrucciones de la tarea. + +""" +__author__ = 'Miguel Angel Cruz Duarte' + +import entornos_f +import entornos_o + +# Requiere el modulo entornos_f.py o entornos_o.py +# Usa el modulo doscuartos_f.py para reutilizar código +# Agrega los modulos que requieras de python +