class_docstr: A Transformed Distribution.
  
  A `TransformedDistribution` models `p(y)` given a base distribution `p(x)`,
  and a deterministic, invertible, differentiable transform, `Y = g(X)`. The
  transform is typically an instance of the `Bijector` class and the base
  distribution is typically an instance of the `Distribution` class.
  
  A `Bijector` is expected to implement the following functions:
  - `forward`,
  - `inverse`,
  - `inverse_log_det_jacobian`.
  The semantics of these functions are outlined in the `Bijector` documentation.
  
  We now describe how a `TransformedDistribution` alters the input/outputs of a
  `Distribution` associated with a random variable (rv) `X`.
  
  Write `cdf(Y=y)` for an absolutely continuous cumulative distribution function
  of random variable `Y`; write the probability density function `pdf(Y=y) :=
  d^k / (dy_1,...,dy_k) cdf(Y=y)` for its derivative wrt to `Y` evaluated at
  `y`. Assume that `Y = g(X)` where `g` is a deterministic diffeomorphism,
  i.e., a non-random, continuous, differentiable, and invertible function.
  Write the inverse of `g` as `X = g^{-1}(Y)` and `(J o g)(x)` for the Jacobian
  of `g` evaluated at `x`.
  
  A `TransformedDistribution` implements the following operations:
  
    * `sample`
      Mathematically:   `Y = g(X)`
      Programmatically: `bijector.forward(distribution.sample(...))`
  
    * `log_prob`
      Mathematically:   `(log o pdf)(Y=y) = (log o pdf o g^{-1})(y)
                         + (log o abs o det o J o g^{-1})(y)`
      Programmatically: `(distribution.log_prob(bijector.inverse(y))
                         + bijector.inverse_log_det_jacobian(y))`
  
    * `log_cdf`
      Mathematically:   `(log o cdf)(Y=y) = (log o cdf o g^{-1})(y)`
      Programmatically: `distribution.log_cdf(bijector.inverse(x))`
  
    * and similarly for: `cdf`, `prob`, `log_survival_function`,
     `survival_function`.
  
  A simple example constructing a Log-Normal distribution from a Normal
  distribution:
  
  ```python
  ds = tfp.distributions
  log_normal = ds.TransformedDistribution(
    distribution=ds.Normal(loc=0., scale=1.),
    bijector=ds.bijectors.Exp(),
    name="LogNormalTransformedDistribution")
  ```
  
  A `LogNormal` made from callables:
  
  ```python
  ds = tfp.distributions
  log_normal = ds.TransformedDistribution(
    distribution=ds.Normal(loc=0., scale=1.),
    bijector=ds.bijectors.Inline(
      forward_fn=tf.exp,
      inverse_fn=tf.math.log,
      inverse_log_det_jacobian_fn=(
        lambda y: -tf.reduce_sum(tf.math.log(y), axis=-1)),
    name="LogNormalTransformedDistribution")
  ```
  
  Another example constructing a Normal from a StandardNormal:
  
  ```python
  ds = tfp.distributions
  normal = ds.TransformedDistribution(
    distribution=ds.Normal(loc=0., scale=1.),
    bijector=ds.bijectors.Affine(
      shift=-1.,
      scale_identity_multiplier=2.)
    name="NormalTransformedDistribution")
  ```
  
  A `TransformedDistribution`'s batch- and event-shape are implied by the base
  distribution unless explicitly overridden by `batch_shape` or `event_shape`
  arguments. Specifying an overriding `batch_shape` (`event_shape`) is
  permitted only if the base distribution has scalar batch-shape (event-shape).
  The bijector is applied to the distribution as if the distribution possessed
  the overridden shape(s). The following example demonstrates how to construct a
  multivariate Normal as a `TransformedDistribution`.
  
  ```python
  ds = tfp.distributions
  # We will create two MVNs with batch_shape = event_shape = 2.
  mean = [[-1., 0],      # batch:0
          [0., 1]]       # batch:1
  chol_cov = [[[1., 0],
               [0, 1]],  # batch:0
              [[1, 0],
               [2, 2]]]  # batch:1
  mvn1 = ds.TransformedDistribution(
      distribution=ds.Normal(loc=0., scale=1.),
      bijector=ds.bijectors.Affine(shift=mean, scale_tril=chol_cov),
      batch_shape=[2],  # Valid because base_distribution.batch_shape == [].
      event_shape=[2])  # Valid because base_distribution.event_shape == [].
  mvn2 = ds.MultivariateNormalTriL(loc=mean, scale_tril=chol_cov)
  # mvn1.log_prob(x) == mvn2.log_prob(x)
  ```
class_docstr_tok: ["A","Transformed","Distribution",".","A","`","TransformedDistribution","`","models","`","p","(","y",")","`","given","a","base","distribution","`","p","(","x",")","`",",","and","a","deterministic",",","invertible",",","differentiable","transform",",","`","Y","=","g","(","X",")","`",".","The","transform","is","typically","an","instance","of","the","`","Bijector","`","class","and","the","base","distribution","is","typically","an","instance","of","the","`","Distribution","`","class",".","A","`","Bijector","`","is","expected","to","implement","the","following","functions",":","-","`","forward","`",",","-","`","inverse","`",",","-","`","inverse_log_det_jacobian","`",".","The","semantics","of","these","functions","are","outlined","in","the","`","Bijector","`","documentation",".","We","now","describe","how","a","`","TransformedDistribution","`","alters","the","input\/outputs","of","a","`","Distribution","`","associated","with","a","random","variable","(","rv",")","`","X","`",".","Write","`","cdf","(","Y=y",")","`","for","an","absolutely","continuous","cumulative","distribution","function","of","random","variable","`","Y","`",";","write","the","probability","density","function","`","pdf","(","Y=y",")",":","=","d^k","\/","(","dy_1",",","...",",","dy_k",")","cdf","(","Y=y",")","`","for","its","derivative","wrt","to","`","Y","`","evaluated","at","`","y","`",".","Assume","that","`","Y","=","g","(","X",")","`","where","`","g","`","is","a","deterministic","diffeomorphism",",","i.e.",",","a","non-random",",","continuous",",","differentiable",",","and","invertible","function",".","Write","the","inverse","of","`","g","`","as","`","X","=","g^","{","-1","}","(","Y",")","`","and","`","(","J","o","g",")","(","x",")","`","for","the","Jacobian","of","`","g","`","evaluated","at","`","x","`",".","A","`","TransformedDistribution","`","implements","the","following","operations",":","*","`","sample","`","Mathematically",":","`","Y","=","g","(","X",")","`","Programmatically",":","`","bijector.forward","(","distribution.sample","(","...",")",")","`","*","`","log_prob","`","Mathematically",":","`","(","log","o","pdf",")","(","Y=y",")","=","(","log","o","pdf","o","g^","{","-1","}",")","(","y",")","+","(","log","o","abs","o","det","o","J","o","g^","{","-1","}",")","(","y",")","`","Programmatically",":","`","(","distribution.log_prob","(","bijector.inverse","(","y",")",")","+","bijector.inverse_log_det_jacobian","(","y",")",")","`","*","`","log_cdf","`","Mathematically",":","`","(","log","o","cdf",")","(","Y=y",")","=","(","log","o","cdf","o","g^","{","-1","}",")","(","y",")","`","Programmatically",":","`","distribution.log_cdf","(","bijector.inverse","(","x",")",")","`","*","and","similarly","for",":","`","cdf","`",",","`","prob","`",",","`","log_survival_function","`",",","`","survival_function","`",".","A","simple","example","constructing","a","Log-Normal","distribution","from","a","Normal","distribution",":","``","`","python","ds","=","tfp.distributions","log_normal","=","ds.TransformedDistribution","(","distribution=ds.Normal","(","loc=0.",",","scale=1",".",")",",","bijector=ds.bijectors.Exp","(",")",",","name=","''","LogNormalTransformedDistribution","''",")","``","`","A","`","LogNormal","`","made","from","callables",":","``","`","python","ds","=","tfp.distributions","log_normal","=","ds.TransformedDistribution","(","distribution=ds.Normal","(","loc=0.",",","scale=1",".",")",",","bijector=ds.bijectors.Inline","(","forward_fn=tf.exp",",","inverse_fn=tf.math.log",",","inverse_log_det_jacobian_fn=","(","lambda","y",":","-tf.reduce_sum","(","tf.math.log","(","y",")",",","axis=-1",")",")",",","name=","''","LogNormalTransformedDistribution","''",")","``","`","Another","example","constructing","a","Normal","from","a","StandardNormal",":","``","`","python","ds","=","tfp.distributions","normal","=","ds.TransformedDistribution","(","distribution=ds.Normal","(","loc=0.",",","scale=1",".",")",",","bijector=ds.bijectors.Affine","(","shift=-1.",",","scale_identity_multiplier=2",".",")","name=","''","NormalTransformedDistribution","''",")","``","`","A","`","TransformedDistribution","`","'s","batch-","and","event-shape","are","implied","by","the","base","distribution","unless","explicitly","overridden","by","`","batch_shape","`","or","`","event_shape","`","arguments",".","Specifying","an","overriding","`","batch_shape","`","(","`","event_shape","`",")","is","permitted","only","if","the","base","distribution","has","scalar","batch-shape","(","event-shape",")",".","The","bijector","is","applied","to","the","distribution","as","if","the","distribution","possessed","the","overridden","shape","(","s",")",".","The","following","example","demonstrates","how","to","construct","a","multivariate","Normal","as","a","`","TransformedDistribution","`",".","``","`","python","ds","=","tfp.distributions","#","We","will","create","two","MVNs","with","batch_shape","=","event_shape","=","2.","mean","=","[","[","-1.",",","0","]",",","#","batch:0","[","0.",",","1","]","]","#","batch:1","chol_cov","=","[","[","[","1.",",","0","]",",","[","0",",","1","]","]",",","#","batch:0","[","[","1",",","0","]",",","[","2",",","2","]","]","]","#","batch:1","mvn1","=","ds.TransformedDistribution","(","distribution=ds.Normal","(","loc=0.",",","scale=1",".",")",",","bijector=ds.bijectors.Affine","(","shift=mean",",","scale_tril=chol_cov",")",",","batch_shape=","[","2","]",",","#","Valid","because","base_distribution.batch_shape","==","[","]",".","event_shape=","[","2","]",")","#","Valid","because","base_distribution.event_shape","==","[","]",".","mvn2","=","ds.MultivariateNormalTriL","(","loc=mean",",","scale_tril=chol_cov",")","#","mvn1.log_prob","(","x",")","==","mvn2.log_prob","(","x",")","``","`"]
docstr: Construct a Transformed Distribution.
  
  Args:
    distribution: The base distribution instance to transform. Typically an
      instance of `Distribution`.
    bijector: The object responsible for calculating the transformation.
      Typically an instance of `Bijector`. `None` means `Identity()`.
    batch_shape: `integer` vector `Tensor` which overrides `distribution`
      `batch_shape`; valid only if `distribution.is_scalar_batch()`.
    event_shape: `integer` vector `Tensor` which overrides `distribution`
      `event_shape`; valid only if `distribution.is_scalar_event()`.
    validate_args: Python `bool`, default `False`. When `True` distribution
      parameters are checked for validity despite possibly degrading runtime
      performance. When `False` invalid inputs may silently render incorrect
      outputs.
    name: Python `str` name prefixed to Ops created by this class. Default:
      `bijector.name + distribution.name`.
docstr_tok: ["Construct","a","Transformed","Distribution",".","Args",":","distribution",":","The","base","distribution","instance","to","transform",".","Typically","an","instance","of","`","Distribution","`",".","bijector",":","The","object","responsible","for","calculating","the","transformation",".","Typically","an","instance","of","`","Bijector","`",".","`","None","`","means","`","Identity","(",")","`",".","batch_shape",":","`","integer","`","vector","`","Tensor","`","which","overrides","`","distribution","`","`","batch_shape","`",";","valid","only","if","`","distribution.is_scalar_batch","(",")","`",".","event_shape",":","`","integer","`","vector","`","Tensor","`","which","overrides","`","distribution","`","`","event_shape","`",";","valid","only","if","`","distribution.is_scalar_event","(",")","`",".","validate_args",":","Python","`","bool","`",",","default","`","False","`",".","When","`","True","`","distribution","parameters","are","checked","for","validity","despite","possibly","degrading","runtime","performance",".","When","`","False","`","invalid","inputs","may","silently","render","incorrect","outputs",".","name",":","Python","`","str","`","name","prefixed","to","Ops","created","by","this","class",".","Default",":","`","bijector.name","+","distribution.name","`","."]
code: def __init__(
      self,
      distribution,
      bijector=None,
      batch_shape=None,
      event_shape=None,
      validate_args=False,
      name=None,
  ):
      """Construct a Transformed Distribution.
  
      Args:
        distribution: The base distribution instance to transform. Typically an
          instance of `Distribution`.
        bijector: The object responsible for calculating the transformation.
          Typically an instance of `Bijector`. `None` means `Identity()`.
        batch_shape: `integer` vector `Tensor` which overrides `distribution`
          `batch_shape`; valid only if `distribution.is_scalar_batch()`.
        event_shape: `integer` vector `Tensor` which overrides `distribution`
          `event_shape`; valid only if `distribution.is_scalar_event()`.
        validate_args: Python `bool`, default `False`. When `True` distribution
          parameters are checked for validity despite possibly degrading runtime
          performance. When `False` invalid inputs may silently render incorrect
          outputs.
        name: Python `str` name prefixed to Ops created by this class. Default:
          `bijector.name + distribution.name`.
      """
      parameters = dict(locals())
      name = name or (
          ("" if bijector is None else bijector.name)
          + distribution.name
      )
      with ops.name_scope(
          name, values=[event_shape, batch_shape]
      ) as name:
          # For convenience we define some handy constants.
          self._zero = constant_op.constant(
              0, dtype=dtypes.int32, name="zero"
          )
          self._empty = constant_op.constant(
              [], dtype=dtypes.int32, name="empty"
          )
  
          if bijector is None:
              bijector = identity_bijector.Identity(
                  validate_args=validate_args
              )
  
          # We will keep track of a static and dynamic version of
          # self._is_{batch,event}_override. This way we can do more prior to graph
          # execution, including possibly raising Python exceptions.
  
          self._override_batch_shape = (
              self._maybe_validate_shape_override(
                  batch_shape,
                  distribution.is_scalar_batch(),
                  validate_args,
                  "batch_shape",
              )
          )
          self._is_batch_override = _logical_not(
              _logical_equal(
                  _ndims_from_shape(self._override_batch_shape),
                  self._zero,
              )
          )
          self._is_maybe_batch_override = bool(
              tensor_util.constant_value(self._override_batch_shape)
              is None
              or tensor_util.constant_value(
                  self._override_batch_shape
              ).size
              != 0
          )
  
          self._override_event_shape = (
              self._maybe_validate_shape_override(
                  event_shape,
                  distribution.is_scalar_event(),
                  validate_args,
                  "event_shape",
              )
          )
          self._is_event_override = _logical_not(
              _logical_equal(
                  _ndims_from_shape(self._override_event_shape),
                  self._zero,
              )
          )
          self._is_maybe_event_override = bool(
              tensor_util.constant_value(self._override_event_shape)
              is None
              or tensor_util.constant_value(
                  self._override_event_shape
              ).size
              != 0
          )
  
          # To convert a scalar distribution into a multivariate distribution we
          # will draw dims from the sample dims, which are otherwise iid. This is
          # easy to do except in the case that the base distribution has batch dims
          # and we're overriding event shape. When that case happens the event dims
          # will incorrectly be to the left of the batch dims. In this case we'll
          # cyclically permute left the new dims.
          self._needs_rotation = _logical_and(
              self._is_event_override,
              _logical_not(self._is_batch_override),
              _logical_not(distribution.is_scalar_batch()),
          )
          override_event_ndims = _ndims_from_shape(
              self._override_event_shape
          )
          self._rotate_ndims = _pick_scalar_condition(
              self._needs_rotation, override_event_ndims, 0
          )
          # We'll be reducing the head dims (if at all), i.e., this will be []
          # if we don't need to reduce.
          self._reduce_event_indices = math_ops.range(
              self._rotate_ndims - override_event_ndims,
              self._rotate_ndims,
          )
  
      self._distribution = distribution
      self._bijector = bijector
      super(TransformedDistribution, self).__init__(
          dtype=self._distribution.dtype,
          reparameterization_type=self._distribution.reparameterization_type,
          validate_args=validate_args,
          allow_nan_stats=self._distribution.allow_nan_stats,
          parameters=parameters,
          # We let TransformedDistribution access _graph_parents since this class
          # is more like a baseclass than derived.
          graph_parents=(
              distribution._graph_parents
              + bijector.graph_parents  # pylint: disable=protected-access
          ),
          name=name,
      )
  
imports: import numpy
  from tensorflow.python.framework import constant_op
  from tensorflow.python.framework import dtypes
  from tensorflow.python.framework import ops
  from tensorflow.python.framework import tensor_util
  from tensorflow.python.ops import array_ops
  from tensorflow.python.ops import array_ops_stack
  from tensorflow.python.ops import check_ops
  from tensorflow.python.ops import control_flow_ops
  from tensorflow.python.ops import math_ops
  from tensorflow.python.ops.distributions import distribution
  from tensorflow.python.ops.distributions import identity_bijector
  from tensorflow.python.ops.distributions import util
  from tensorflow.python.util import deprecation
label_desc: Use image node_id 1 to create a new TransformedDistribution object from inherited base classes: distribution_lib with example: obj = TransformedDistribution(distribution, bijector, batch_shape, event_shape, validate_args, name)