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 experience replay_buffer_ets.ex
Raw

lib/experience/replay_buffer_ets.ex

defmodule Gyx.Experience.ReplayBufferETS do
@moduledoc """
Implements ReplayMemory behaviour relying on ETS
"""
alias Gyx.Core.ReplayMemory
use GenServer
use ReplayMemory
@compile {:parse_transform, :ms_transform}
def start_link(_, ops) do
GenServer.start_link(__MODULE__, %{}, ops)
end
def init(_) do
experiences = :ets.new(:replay_buffer, [:ordered_set, :protected, :named_table])
{:ok, experiences}
end
def delete(key) do
GenServer.cast(__MODULE__, {:delete, key})
end
def get(key) do
GenServer.call(__MODULE__, {:get, key})
end
@doc """
Adds a new experience to the reppay buffer
"""
def add(experience) do
GenServer.cast(__MODULE__, {:add, experience})
end
def get_batch({n, sampling_strategy}) do
GenServer.call(__MODULE__, {:get_batch, {n, sampling_strategy}})
end
def delete(), do: GenServer.cast(__MODULE__, :delete)
def handle_cast(:delete, state) do
:ets.delete(:replay_buffer)
{:noreply, state}
end
def handle_cast({:delete, key}, state) do
:ets.delete(:replay_buffer, key)
{:noreply, state}
end
def handle_cast({:add, exp}, _state) do
{:ok, timestamp_key} = DateTime.now("Etc/UTC")
:ets.insert(:replay_buffer, {timestamp_key, exp})
{:noreply, timestamp_key}
end
def handle_call({:get, key}, _from, state) do
reply =
case :ets.lookup(:replay_buffer, key) do
[] -> nil
[{_timestamp, experience}] -> experience
end
{:reply, reply, state}
end
def handle_call({:get_batch, {n, :random}}, _from, state) do
reply =
:replay_buffer
|> :ets.select(all_match_specification())
|> Enum.shuffle()
|> Enum.take(n)
{:reply, reply, state}
end
def handle_call({:get_batch, {n, :latest}}, _from, state) do
reply =
:replay_buffer
|> :ets.select(all_match_specification())
|> Enum.sort_by(fn {d, _exp} -> {d.year, d.month, d.day, d.second, d.microsecond} end)
|> Enum.take(-n)
{:reply, reply, state}
end
defp all_match_specification, do: :ets.fun2ms(fn {k, v} -> {k, v} end)
end