Packages

Gyx allows designing and training Reinforcement Learning tasks. It includes environment abstractions that allows interaction with Python based environments like OpenAI Gym.

Current section

Files

Jump to
gyx lib core env.ex
Raw

lib/core/env.ex

defmodule Gyx.Core.Env do
@moduledoc """
This behaviour is intended to be followed for any `Environment` implementation
The most critical function to be exposed is `step/1` , which serves as a direct bridge
between the environment and any agent.
Here, an important design question to address is the fundamental difference between
the environment state (its internal representation) and an _observation_ of such state.
In principle, the environment returns an observation as part of step/1 response.
Should it be a way to obtain an evironment state abstraction as suposed to be shown
to an agent? i.e. an indirect observation.
"""
alias Gyx.Core.Exp
@type initial_state :: Exp.t()
@type observation :: any()
@type action :: any()
@type environment :: any()
@doc "Sets the state of the environment to its default"
@callback reset(environment) :: initial_state()
@doc "Gets an environment representation usable by the agent"
@callback observe(environment) :: observation()
@doc """
Recieves an agent's `action` and responds to it,
informing the agent back with a reward, a modified environment
and a termination signal
"""
@callback step(environment, action()) :: Exp.t() | {:error, reason :: String.t()}
defmacro __using__(_params) do
quote do
@before_compile Gyx.Core.Env
@behaviour Gyx.Core.Env
@enforce_keys [:action_space, :observation_space]
@impl true
def observe(environment), do: GenServer.call(environment, :observe)
@impl true
def step(environment, action) do
case action_checked = GenServer.call(environment, {:check, action}) do
{:error, _} -> action_checked
{:ok, action} -> GenServer.call(environment, {:act, action})
end
end
end
end
defmacro __before_compile__(_) do
quote do
def handle_call({:check, action}, _from, state = %__MODULE__{action_space: action_space}) do
case Gyx.Core.Spaces.contains?(action_space, action) do
false -> {:reply, {:error, "invalid_action"}, state}
_ -> {:reply, {:ok, action}, state}
end
end
end
end
end