from jax.tree_util import tree_flatten, tree_unflatten, register_pytree_node from jax import numpy as np # The structured value to be transformed value_structured = [1., (2., 3.)] # The leaves in value_flat correspond to the `*` markers in value_tree value_flat, value_tree = tree_flatten(value_structured) print("value_flat={}\nvalue_tree={}".format(value_flat, value_tree)) # Transform the flt value list using an element-wise numeric transformer transformed_flat = list(map(lambda v: v * 2., value_flat)) print("transformed_flat={}".format(transformed_flat)) # Reconstruct the structured output, using the original transformed_structured = tree_unflatten(value_tree, transformed_flat) print("transformed_structured={}".format(transformed_structured)) from collections import namedtuple Point = namedtuple('Point', ['x', 'y']) example_containers = [ (1., [2., 3.]), (1., {'b': 2., 'a': 3.}), 1., None, np.zeros(2), Point(1., 2.) ] def show_example(structured): flat, tree = tree_flatten(structured) unflattened = tree_unflatten(tree, flat) print("structured={}\n flat={}\n tree={}\n unflattened={}".format( structured, flat, tree, unflattened)) for structured in example_containers: show_example(structured) class Special(object): def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return "Special(x={}, y={})".format(self.x, self.y) show_example(Special(1., 2.)) class RegisteredSpecial(Special): def __repr__(self): return "RegisteredSpecial(x={}, y={})".format(self.x, self.y) def special_flatten(v): """Specifies a flattening recipe. Params: v: the value of registered type to flatten. Returns: a pair of an iterable with the children to be flattened recursively, and some opaque auxiliary data to pass back to the unflattening recipe. The auxiliary data is stored in the treedef for use during unflattening. The auxiliary data could be used, e.g., for dictionary keys. """ children = (v.x, v.y) aux_data = None return (children, aux_data) def special_unflatten(aux_data, children): """Specifies an unflattening recipe. Params: aux_data: the opaque data that was specified during flattening of the current treedef. children: the unflattened children Returns: a re-constructed object of the registered type, using the specified children and auxiliary data. """ return RegisteredSpecial(*children) # Global registration register_pytree_node( RegisteredSpecial, special_flatten, # tell JAX what are the children nodes special_unflatten # tell JAX how to pack back into a RegisteredSpecial ) show_example(RegisteredSpecial(1., 2.))