class_docstr: Converts between nested structures of Tensors.
  
  This is useful when constructing non-trivial chains of multipart bijectors.
  It partitions inputs into different logical "blocks", which may be fed as
  arguments to downstream multipart bijectors.
  
  Example Usage:
  
    ```python
  
    # Pack a 3-element list of tensors into a dict. The output structure,
    # `structure_1`, is defined as a dict in which the values are list
    # indices.
    structure_1 = {'a': 1, 'b': 2, 'c': 0}
    list_to_dict = Restructure(output_structure=structure_1)
    input_list = [0.01, 0.02, 0.03]
    assert list_to_dict.forward(input_list) == {
      'a': 0.02, 'b': 0.03, 'c': 0.01}
  
    # Now assume that, instead of a list/tuple (the default), the input
    # structure is another dict. The output structure is the same as
    # defined above, and consecutive integers are again used to associate
    # components of the input and output structures.
    structure_2 = {'c': 2, 'd': 1, 'e': 0}
    dict_to_dict = Restructure(
      structure_1, input_structure=structure_2)
    input_dict = {'c': -3.5, 'd': 96.0, 'e': 12.0}
    assert dict_to_dict.forward(input_dict) == {
      'a': 96.0, 'b': -3.5, 'c': 12.0}
  
    # Restructure a dict to a namedtuple.
    Example = collections.namedtuple('Example', ['x', 'y', 'z'])
    structure_3 = Example(2, 0, 1)
    namedtuple_to_dict = Restructure(structure_3, input_structure=structure_2)
    assert namedtuple_to_dict(input_dict) == Example(x=-3.5, y=12.0, z=96.0)
  
    assert namedtuple_to_dict.inverse(Example(x=0.01, y=0.02, z=0.03)) == {
      'c': 0.01, 'd': 0.03, 'e': 0.02}
  
    # Restructure can be applied to structures of mixed type and arbitrary
    # depth:
    restructure = Restructure({
      'foo': [0, 1],
      'bar': [3, 2],
      'baz': [4, 5, 6]
    })
  
    # Note that x is a *python-list* of tensors.
    # To permute elements of an individual Tensor, see `tfb.Permute`.
    x = [1, 2, 4, 8, 16, 32, 64]
  
    assert restructure.forward(x) == {
        'foo': [1, 2],
        'bar': [8, 4],
        'baz': [16, 32, 64]
    }
  
    # Where Restructure is useful:
    complex_bijector = Chain([
      # Apply different transformations to each block.
      JointMap({
        'foo': ScaleMatVecLinearOperator(...),  # Operates on the full block
        'bar': ScaleMatVecLinearOperator(...),  # Operates on the full block
        'baz': [Exp(), Scale(10.), Shift(-1.)]  # Different bijectors for each
      }),
      # Group the tensor into logical blocks.
      Restructure({
        'foo': [0, 1],
        'bar': [3, 2],
        'baz': [4, 5, 6],
      }),
      # Split an input tensor into 7 chunks.
      Split([2, 4, 6, 8, 10, 12, 14])
    ])
    ```
docstr: Creates a `Restructure` bijector.
  
  Args:
    output_structure: A tf.nest-compatible structure of tokens describing the
      output of `forward` (equivalently, the input of `inverse`).
    input_structure: A tf.nest-compatible structure of tokens describing the
      input to `forward`. If unspecified, a default structure is inferred from
      `output_structure`. The default structure expects a `list` if tokens are
      integers, or a `dict` if the tokens are strings.
    name: Name of this bijector.
  Raises:
    ValueError: If tokens are duplicated, or a required default structure
      cannot be inferred.
docstr_tok: ["Creates","a","`","Restructure","`","bijector",".","Args",":","output_structure",":","A","tf.nest-compatible","structure","of","tokens","describing","the","output","of","`","forward","`","(","equivalently",",","the","input","of","`","inverse","`",")",".","input_structure",":","A","tf.nest-compatible","structure","of","tokens","describing","the","input","to","`","forward","`",".","If","unspecified",",","a","default","structure","is","inferred","from","`","output_structure","`",".","The","default","structure","expects","a","`","list","`","if","tokens","are","integers",",","or","a","`","dict","`","if","the","tokens","are","strings",".","name",":","Name","of","this","bijector",".","Raises",":","ValueError",":","If","tokens","are","duplicated",",","or","a","required","default","structure","can","not","be","inferred","."]
code: def __init__(
      self, output_structure, input_structure=None, name="restructure"
  ):
      """Creates a `Restructure` bijector.
  
      Args:
        output_structure: A tf.nest-compatible structure of tokens describing the
          output of `forward` (equivalently, the input of `inverse`).
        input_structure: A tf.nest-compatible structure of tokens describing the
          input to `forward`. If unspecified, a default structure is inferred from
          `output_structure`. The default structure expects a `list` if tokens are
          integers, or a `dict` if the tokens are strings.
        name: Name of this bijector.
      Raises:
        ValueError: If tokens are duplicated, or a required default structure
          cannot be inferred.
      """
      parameters = dict(locals())
  
      # Get the flat set of tokens, making sure they're unique.
      output_tokens = unique_token_set(output_structure)
  
      # Create a default input_structure when it isn't provided.
      if input_structure is None:
          # If all tokens are strings, assume input is a dict.
          if all(
              isinstance(tok, six.string_types) for tok in output_tokens
          ):
              input_structure = {
                  token: token for token in output_tokens
              }
  
          # If tokens are contiguous 0-based ints, return a list.
          elif all(
              isinstance(tok, six.integer_types)
              for tok in output_tokens
          ) and output_tokens == set(range(len(output_tokens))):
              input_structure = list(range(len(output_tokens)))
  
          # Otherwise, we cannot infer a default structure.
          else:
              raise ValueError(
                  (
                      "Tokens in output_structure must be all strings or "
                      "contiguous 0-based indices when input_structure "
                      "is not specified. Saw: {}"
                  ).format(output_tokens)
              )
  
      # If input_structure _is_ provided, make sure tokens are unique
      # and that they match the output_structure tokens.
      else:
          input_tokens = unique_token_set(output_structure)
          if input_tokens != output_tokens:
              raise ValueError(
                  (
                      "The `input_structure` tokens must match the "
                      "`output_structure` tokens exactly. Missing from "
                      "`input_structure`: {}. Missing from "
                      "`output_structure`: {}."
                  ).format(
                      output_tokens - input_tokens,
                      input_tokens - output_tokens,
                  )
              )
  
      self._input_structure = self._no_dependency(input_structure)
      self._output_structure = self._no_dependency(output_structure)
      super(Restructure, self).__init__(
          forward_min_event_ndims=nest_util.broadcast_structure(
              self._input_structure, 0
          ),
          inverse_min_event_ndims=nest_util.broadcast_structure(
              self._output_structure, 0
          ),
          is_constant_jacobian=True,
          validate_args=False,
          parameters=parameters,
          name=name,
      )
  
imports: import six
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import bijector
  from tensorflow_probability.python.bijectors import invert
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import nest_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow.python.util import nest
label_desc: Use image node_id 1 to create a new Restructure object from inherited base classes: bijector with example: obj = Restructure(output_structure, input_structure, name)