Struct
Overview
Similarly to flax.struct, the struct submodule implements datastructures
that are automatically registered as JAX pytrees with jax.tree_util, allowing us to
pass them to JAX transformations. The two datastructures defined fullfil two main
purposes in envelope:
FrozenPyTreeNodecreates a dataclass with fixed fields that you can mark as either static or dynamic usingstruct.field.
For example, environments are instances ofFrozenPyTreeNode, allowing them to have both static (structural, e.g. world size) and dynamic params (not affecting array shapes and control flow, e.g. wind speed).Containercreates a dataclass with a core set of fields that will always be present. Additionally, instances ofContainercan be updated to hold any additional fields at runtime (and even within traced methods).
For example, thestepfunction of an environment emits anInfoobject that is aContainer, and holds observation, reward and terminated/truncated flags. Wrappers can add information to this, such as current episode statistics.
API Reference
envelope.struct.FrozenPyTreeNode
Frozen dataclass base that is a JAX pytree node. Fields can be declared as either
dynamic (pytree nodes) or static (not pytree nodes) using the field and
static_field helpers.
Usage
class Foo(FrozenPyTreeNode):
a: Any # pytree leaf
b: int = static_field() # static, not a leaf
x = Foo(a={"w": 1.0}, b=0)
y = x.replace(b=1)
Functions
replace(**changes)
Shorthand for dataclasses.replace(self, **changes).
envelope.struct.field(*, pytree_node=True, **kwargs)
Dataclass field helper. See typing.FrozenPyTreeNode for more details.
Set pytree_node=False for static (non-transformed) fields.
envelope.struct.static_field(**kwargs)
Shorthand for field(pytree_node=False, ...).
envelope.struct.Container
dataclass
This class implements a container for arbitrary PyTree-valued fields. While subclasses can define arbitrary core fields, instances of this class can be updated to hold any additional extras fields.
Usage example
class Foo(Container):
bar: int
foo = Foo(bar=1)
foo = foo.update(bar=2, baz=3.0)
print(foo) # Foo(bar=2, baz=3.0)
Functions
update(**changes)
Update the container with new values. The changes overwrite fields in the
container, both for core fields and extras.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**changes
|
dict[str, PyTree]
|
A dictionary of field names and values to update. |
{}
|
Returns:
| Type | Description |
|---|---|
Self
|
A new instance of the container with the updated values. |