# `Monty.Random.Stream`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/random/stream.ex#L1)

The one random stream an episode draws from.

Monty threads a single mutable `numpy.random.RandomState` through every module
(`ctx.rng`), so what a module draws depends on how many draws the modules
before it made. That object is shared and mutable, which is why it is a process
here: one per model, holding a `Monty.Random.Numpy` state, reseeded when the
episode's seed changes.

Reached through `Monty.Context.rng`, a module draws in the order it is stepped.
That order is Monty's — sensor modules, then learning modules' goals, then the
motor system — and it is why the coordinator steps its sensor modules one at a
time: a barrier would decide which module drew first by which call arrived
first, and the numbers would follow the scheduler.

A draw is a call, so this is the one place in a step where a module is not a
pure function of its inputs; what it stays is a function of the episode, and
two runs of the same episode draw the same numbers in the same order.

Every call here waits as long as it takes. A step is computation-bound and the
rest of the runtime already says so (`:infinity` on every server call); a draw
was the one thing left on the default five seconds, so a step that queued
behind a long one — or a suite running sixteen cases at once behind one stream
— died of a timeout rather than finishing. A draw is not a health check: if the
stream is slow, the step is slow.

# `server`

```elixir
@type server() :: GenServer.server()
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `normal`

```elixir
@spec normal(server(), float(), float()) :: float()
```

One normal draw: Monty's `ctx.rng.normal(loc=..., scale=...)`.

# `normals`

```elixir
@spec normals(server(), non_neg_integer(), float(), float()) :: [float()]
```

`count` normal draws: Monty's `ctx.rng.normal(loc=..., scale=..., size=count)`.

# `random`

```elixir
@spec random(server()) :: float()
```

A float drawn uniformly from `[0, 1)`: Monty's `ctx.rng.uniform()`.

# `reseed`

```elixir
@spec reseed(server(), non_neg_integer()) :: :ok
```

Starts the episode `seed` names, discarding the one before it.

# `start_link`

```elixir
@spec start_link(%{model_id: atom() | String.t(), seed: non_neg_integer()}) ::
  GenServer.on_start()
```

Starts the stream a model's episodes draw from.

# `state`

```elixir
@spec state(server()) :: Monty.Random.Numpy.t()
```

The stream's own state, for a test that has to say where it is.

# `uniform`

```elixir
@spec uniform(server(), float(), float()) :: float()
```

A float drawn uniformly from `[low, high)`: Monty's `ctx.rng.uniform(a, b)`.

# `via`

```elixir
@spec via(atom() | String.t()) :: {:via, module(), {atom(), term()}}
```

A `:via` name for a model's stream.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
