Source code for mlpy.agents

"""
====================================
Agent design (:mod:`mlpy.agents`)
====================================

.. currentmodule:: mlpy.agents

This module contains functionality for designing agents
navigating inside an :class:`.Environment`.

Control of the agents is specified by an agent module which
is handled by the :class:`Agent` base class.

An agent class deriving from :class:`Agent` can also make use
of a finite state machine (FSM) to control the agent's behavior
and a world model to maintain a notion of the current state of
the world.


Agents
======

.. autosummary::
   :toctree: generated/
   :nosignatures:

   Agent
   ~modules.AgentModuleFactory
   ~modules.IAgentModule
   ~modules.LearningModule
   ~modules.FollowPolicyModule
   ~modules.UserModule


World Model
===========

.. autosummary::
   :toctree: generated/
   :nosignatures:

   ~world.WorldObject
   ~world.WorldModel


Finite State Machine
====================

.. autosummary::
   :toctree: generated/
   :nosignatures:

   ~fsm.Event
   ~fsm.EmptyEvent
   ~fsm.FSMState
   ~fsm.Transition
   ~fsm.OnUpdate
   ~fsm.StateMachine

"""
from __future__ import division, print_function, absolute_import

from ..modules import Module
from .modules import AgentModuleFactory

__all__ = ['fsm', 'modules', 'world']


[docs]class Agent(Module): """The agent base class. Agents act in an environment (:class:`.Environment`) usually performing a task (:class:`.Task`). Depending on the agent module they either follow a policy (:class:`.FollowPolicyModule`), are user controlled via the keyboard or a PS2 controller (:class:`.UserModule`), or learn according to a learner (:class:`.LearningModule`). New agent modules can be created by inheriting from the :class:`.IAgentModule` class. Parameters ---------- mid : str, optional The agent's unique identifier. module_type : str The agent module type, which is the name of the class. task: Task The task the agent must complete. args: tuple Positional parameters passed to the agent module. kwargs: dict Non-positional parameters passed to the agent module. Examples -------- >>> from mlpy.agents import Agent >>> Agent(module_type='learningmodule', learner_type='qlearner', max_steps=10) >>> Agent(None, 'learningmodule', None, 'qlearner', max_steps=10) This creates an agent with a :class:`.LearningModule` agent module that performs qlearning. The parameters are given in the order in which the objects are created. Internally the agent creates the learning agent module and the learning agent module creates the qlearner. Alternatively, non-positional arguments can be used: >>> Agent(module_type='learningmodule', learner_type='qlearner', max_steps=10) >>> from mlpy.experiments.task import Task >>> task = Task() >>> Agent(None, 'learningmodule', task, 'qlearner', max_steps=10) This creates an agent that performs the given task. If a task is given, the method :meth:`.Task.get_reward` is passed as the reward callback to the learning module to retrieve the reward. By default :meth:`.Task.get_reward` returns `None`. """ @property def module(self): """The agent module controlling the actions of the agent. Returns ------- IAgentModule : The agent module instance. """ return self._module @property def task(self): """The task the agent is to perform. Returns ------- Task : The task to perform. """ return self._task def __init__(self, mid=None, module_type=None, task=None, *args, **kwargs): super(Agent, self).__init__(mid) self._module = None if module_type is not None: if module_type == 'learningmodule' and task is not None: if "learner_type" in kwargs: kwargs.update({'cb_get_reward': task.get_reward}) else: args_ = list(args) args_.insert(1, task.get_reward) args = tuple(args_) self._module = AgentModuleFactory.create(module_type, *args, **kwargs) self._task = task
[docs] def reset(self, t, **kwargs): """Reset the agent's state. Parameters ---------- t : float The current time (sec). kwargs : dict, optional Non-positional parameters. """ super(Agent, self).reset(t, **kwargs) if self._task is not None: self._task.reset(t, **kwargs) if self._module is not None: self._module.reset(t, **kwargs) if self._module.is_complete(): self._task.terminate(True)
[docs] def enter(self, t): """Enter the agent and the agent module. Perform initialization tasks here. Parameters ---------- t : float The current time (sec). """ super(Agent, self).enter(t) if self._module is not None: self._module.enter(t)
[docs] def update(self, dt): """Update the agent and the agent module. The agent and the agent module are updated at every time step in the program loop. Parameters ---------- dt : float The elapsed time (sec) """ super(Agent, self).update(dt) if self._module is not None: self._module.update(dt)
[docs] def exit(self): """Exit the agent and the agent module. Perform cleanup tasks here. """ super(Agent, self).exit() if self._module is not None: self._module.exit()
[docs] def is_task_complete(self): """Check if the agent's task is completed. This could be because a terminal state was reached. Returns ------- bool : The value of the termination flag. """ if self._task is None: raise UserWarning("No task registered") return self._task.is_complete()