class_docstr: A piecewise rational quadratic spline, as developed in [1].
  
  This transformation represents a monotonically increasing piecewise rational
  quadratic function. Outside of the bounds of `knot_x`/`knot_y`, the transform
  behaves as an identity function.
  
  Typically this bijector will be used as part of a chain, with splines for
  trailing `x` dimensions conditioned on some of the earlier `x` dimensions, and
  with the inverse then solved first for unconditioned dimensions, then using
  conditioning derived from those inverses, and so forth. For example, if we
  split a 15-D `xs` vector into 3 components, we may implement a forward and
  inverse as follows:
  
  ```python
  nsplits = 3
  
  class SplineParams(tf.Module):
  
    def __init__(self, nbins=32, interval_width=2, range_min=-1,
                 min_bin_width=1e-3, min_slope=1e-3):
      self._nbins = nbins
      self._interval_width = interval_width  # Sum of bin widths.
      self._range_min = range_min  # Position of first knot.
      self._min_bin_width = min_bin_width  # Bin width lower bound.
      self._min_slope = min_slope  # Lower bound for slopes at internal knots.
      self._built = False
      self._bin_widths = None
      self._bin_heights = None
      self._knot_slopes = None
  
    def __call__(self, x, nunits):
      if not self._built:
        def _bin_positions(x):
          out_shape = tf.concat((tf.shape(x)[:-1], (nunits, self._nbins)), 0)
          x = tf.reshape(x, out_shape)
          return tf.math.softmax(x, axis=-1) * (
                self._interval_width - self._nbins * self._min_bin_width
                ) + self._min_bin_width
  
        def _slopes(x):
          out_shape = tf.concat((
            tf.shape(x)[:-1], (nunits, self._nbins - 1)), 0)
          x = tf.reshape(x, out_shape)
          return tf.math.softplus(x) + self._min_slope
  
        self._bin_widths = tf_keras.layers.Dense(
          nunits * self._nbins, activation=_bin_positions, name='w')
        self._bin_heights = tf_keras.layers.Dense(
          nunits * self._nbins, activation=_bin_positions, name='h')
        self._knot_slopes = tf_keras.layers.Dense(
          nunits * (self._nbins - 1), activation=_slopes, name='s')
        self._built = True
  
      return tfb.RationalQuadraticSpline(
        bin_widths=self._bin_widths(x),
        bin_heights=self._bin_heights(x),
        knot_slopes=self._knot_slopes(x),
        range_min=self._range_min)
  
  xs = np.random.randn(3, 15).astype(np.float32)  # Keras won't Dense(.)(vec).
  splines = [SplineParams() for _ in range(nsplits)]
  
  def spline_flow():
    stack = tfb.Identity()
    for i in range(nsplits):
      stack = tfb.RealNVP(5 * i, bijector_fn=splines[i])(stack)
    return stack
  
  ys = spline_flow().forward(xs)
  ys_inv = spline_flow().inverse(ys)  # ys_inv ~= xs
  ```
  
  For a one-at-a-time autoregressive flow as in [1], it would be profitable to
  implement a mask over `xs` to parallelize either the inverse or the forward
  pass and implement the other using a `tf.while_loop`. See
  `tfp.bijectors.MaskedAutoregressiveFlow` for support doing so (paired with
  `tfp.bijectors.Invert` depending which direction should be parallel).
  
  #### References
  
  [1]: Conor Durkan, Artur Bekasov, Iain Murray, George Papamakarios. Neural
       Spline Flows. _arXiv preprint arXiv:1906.04032_, 2019.
       https://arxiv.org/abs/1906.04032
class_docstr_tok: ["A","piecewise","rational","quadratic","spline",",","as","developed","in","[","1","]",".","This","transformation","represents","a","monotonically","increasing","piecewise","rational","quadratic","function",".","Outside","of","the","bounds","of","`","knot_x","`","\/","`","knot_y","`",",","the","transform","behaves","as","an","identity","function",".","Typically","this","bijector","will","be","used","as","part","of","a","chain",",","with","splines","for","trailing","`","x","`","dimensions","conditioned","on","some","of","the","earlier","`","x","`","dimensions",",","and","with","the","inverse","then","solved","first","for","unconditioned","dimensions",",","then","using","conditioning","derived","from","those","inverses",",","and","so","forth",".","For","example",",","if","we","split","a","15-D","`","xs","`","vector","into","3","components",",","we","may","implement","a","forward","and","inverse","as","follows",":","``","`","python","nsplits","=","3","class","SplineParams","(","tf.Module",")",":","def","__init__","(","self",",","nbins=32",",","interval_width=2",",","range_min=-1",",","min_bin_width=1e-3",",","min_slope=1e-3",")",":","self._nbins","=","nbins","self._interval_width","=","interval_width","#","Sum","of","bin","widths",".","self._range_min","=","range_min","#","Position","of","first","knot",".","self._min_bin_width","=","min_bin_width","#","Bin","width","lower","bound",".","self._min_slope","=","min_slope","#","Lower","bound","for","slopes","at","internal","knots",".","self._built","=","False","self._bin_widths","=","None","self._bin_heights","=","None","self._knot_slopes","=","None","def","__call__","(","self",",","x",",","nunits",")",":","if","not","self._built",":","def","_bin_positions","(","x",")",":","out_shape","=","tf.concat","(","(","tf.shape","(","x",")","[",":","-1","]",",","(","nunits",",","self._nbins",")",")",",","0",")","x","=","tf.reshape","(","x",",","out_shape",")","return","tf.math.softmax","(","x",",","axis=-1",")","*","(","self._interval_width","-","self._nbins","*","self._min_bin_width",")","+","self._min_bin_width","def","_slopes","(","x",")",":","out_shape","=","tf.concat","(","(","tf.shape","(","x",")","[",":","-1","]",",","(","nunits",",","self._nbins","-","1",")",")",",","0",")","x","=","tf.reshape","(","x",",","out_shape",")","return","tf.math.softplus","(","x",")","+","self._min_slope","self._bin_widths","=","tf_keras.layers.Dense","(","nunits","*","self._nbins",",","activation=_bin_positions",",","name=","'","w","'",")","self._bin_heights","=","tf_keras.layers.Dense","(","nunits","*","self._nbins",",","activation=_bin_positions",",","name=","'","h","'",")","self._knot_slopes","=","tf_keras.layers.Dense","(","nunits","*","(","self._nbins","-","1",")",",","activation=_slopes",",","name='s","'",")","self._built","=","True","return","tfb.RationalQuadraticSpline","(","bin_widths=self._bin_widths","(","x",")",",","bin_heights=self._bin_heights","(","x",")",",","knot_slopes=self._knot_slopes","(","x",")",",","range_min=self._range_min",")","xs","=","np.random.randn","(","3",",","15",")",".astype","(","np.float32",")","#","Keras","wo","n't","Dense","(",".",")","(","vec",")",".","splines","=","[","SplineParams","(",")","for","_","in","range","(","nsplits",")","]","def","spline_flow","(",")",":","stack","=","tfb.Identity","(",")","for","i","in","range","(","nsplits",")",":","stack","=","tfb.RealNVP","(","5","*","i",",","bijector_fn=splines","[","i","]",")","(","stack",")","return","stack","ys","=","spline_flow","(",")",".forward","(","xs",")","ys_inv","=","spline_flow","(",")",".inverse","(","ys",")","#","ys_inv","~=","xs","``","`","For","a","one-at-a-time","autoregressive","flow","as","in","[","1","]",",","it","would","be","profitable","to","implement","a","mask","over","`","xs","`","to","parallelize","either","the","inverse","or","the","forward","pass","and","implement","the","other","using","a","`","tf.while_loop","`",".","See","`","tfp.bijectors.MaskedAutoregressiveFlow","`","for","support","doing","so","(","paired","with","`","tfp.bijectors.Invert","`","depending","which","direction","should","be","parallel",")",".","#","#","#","#","References","[","1","]",":","Conor","Durkan",",","Artur","Bekasov",",","Iain","Murray",",","George","Papamakarios",".","Neural","Spline","Flows",".","_arXiv","preprint","arXiv:1906.04032_",",","2019.","https",":","\/\/arxiv.org\/abs\/1906.04032"]
docstr: Construct a new RationalQuadraticSpline bijector.
  
  For each argument, the innermost axis indexes bins/knots and batch axes
  index axes of `x`/`y` spaces. A `RationalQuadraticSpline` with a separate
  transform for each of three dimensions might have `bin_widths` shaped
  `[3, 32]`. To use the same spline for each of `x`'s three dimensions we may
  broadcast against `x` and use a `bin_widths` parameter shaped `[32]`.
  Parameters will be broadcast against each other and against the input
  `x`/`y`s, so if we want fixed slopes, we can use kwarg `knot_slopes=1`.
  
  A typical recipe for acquiring compatible bin widths and heights would be:
  
  ```python
  nbins = unconstrained_vector.shape[-1]
  range_min, range_max, min_bin_size = -1, 1, 1e-2
  scale = range_max - range_min - nbins * min_bin_size
  bin_widths = tf.math.softmax(unconstrained_vector) * scale + min_bin_size
  ```
  
  Args:
    bin_widths: The widths of the spans between subsequent knot `x` positions,
      a floating point `Tensor`. Must be positive, and at least 1-D. Innermost
      axis must sum to the same value as `bin_heights`. The knot `x` positions
      will be a first at `range_min`, followed by knots at `range_min +
      cumsum(bin_widths, axis=-1)`.
    bin_heights: The heights of the spans between subsequent knot `y`
      positions, a floating point `Tensor`. Must be positive, and at least
      1-D. Innermost axis must sum to the same value as `bin_widths`. The knot
      `y` positions will be a first at `range_min`, followed by knots at
      `range_min + cumsum(bin_heights, axis=-1)`.
    knot_slopes: The slope of the spline at each knot, a floating point
      `Tensor`. Must be positive. `1`s are implicitly padded for the first and
      last implicit knots corresponding to `range_min` and `range_min +
      sum(bin_widths, axis=-1)`. Innermost axis size should be 1 less than
      that of `bin_widths`/`bin_heights`, or 1 for broadcasting.
    range_min: The `x`/`y` position of the first knot, which has implicit
      slope `1`. `range_max` is implicit, and can be computed as `range_min +
      sum(bin_widths, axis=-1)`. Scalar floating point `Tensor`.
    validate_args: Toggles argument validation (can hurt performance).
    name: Optional name scope for associated ops. (Defaults to
      `'RationalQuadraticSpline'`).
docstr_tok: ["Construct","a","new","RationalQuadraticSpline","bijector",".","For","each","argument",",","the","innermost","axis","indexes","bins\/knots","and","batch","axes","index","axes","of","`","x","`","\/","`","y","`","spaces",".","A","`","RationalQuadraticSpline","`","with","a","separate","transform","for","each","of","three","dimensions","might","have","`","bin_widths","`","shaped","`","[","3",",","32","]","`",".","To","use","the","same","spline","for","each","of","`","x","`","'s","three","dimensions","we","may","broadcast","against","`","x","`","and","use","a","`","bin_widths","`","parameter","shaped","`","[","32","]","`",".","Parameters","will","be","broadcast","against","each","other","and","against","the","input","`","x","`","\/","`","y","`","s",",","so","if","we","want","fixed","slopes",",","we","can","use","kwarg","`","knot_slopes=1","`",".","A","typical","recipe","for","acquiring","compatible","bin","widths","and","heights","would","be",":","``","`","python","nbins","=","unconstrained_vector.shape","[","-1","]","range_min",",","range_max",",","min_bin_size","=","-1",",","1",",","1e-2","scale","=","range_max","-","range_min","-","nbins","*","min_bin_size","bin_widths","=","tf.math.softmax","(","unconstrained_vector",")","*","scale","+","min_bin_size","``","`","Args",":","bin_widths",":","The","widths","of","the","spans","between","subsequent","knot","`","x","`","positions",",","a","floating","point","`","Tensor","`",".","Must","be","positive",",","and","at","least","1-D.","Innermost","axis","must","sum","to","the","same","value","as","`","bin_heights","`",".","The","knot","`","x","`","positions","will","be","a","first","at","`","range_min","`",",","followed","by","knots","at","`","range_min","+","cumsum","(","bin_widths",",","axis=-1",")","`",".","bin_heights",":","The","heights","of","the","spans","between","subsequent","knot","`","y","`","positions",",","a","floating","point","`","Tensor","`",".","Must","be","positive",",","and","at","least","1-D.","Innermost","axis","must","sum","to","the","same","value","as","`","bin_widths","`",".","The","knot","`","y","`","positions","will","be","a","first","at","`","range_min","`",",","followed","by","knots","at","`","range_min","+","cumsum","(","bin_heights",",","axis=-1",")","`",".","knot_slopes",":","The","slope","of","the","spline","at","each","knot",",","a","floating","point","`","Tensor","`",".","Must","be","positive",".","`","1","`","s","are","implicitly","padded","for","the","first","and","last","implicit","knots","corresponding","to","`","range_min","`","and","`","range_min","+","sum","(","bin_widths",",","axis=-1",")","`",".","Innermost","axis","size","should","be","1","less","than","that","of","`","bin_widths","`","\/","`","bin_heights","`",",","or","1","for","broadcasting",".","range_min",":","The","`","x","`","\/","`","y","`","position","of","the","first","knot",",","which","has","implicit","slope","`","1","`",".","`","range_max","`","is","implicit",",","and","can","be","computed","as","`","range_min","+","sum","(","bin_widths",",","axis=-1",")","`",".","Scalar","floating","point","`","Tensor","`",".","validate_args",":","Toggles","argument","validation","(","can","hurt","performance",")",".","name",":","Optional","name","scope","for","associated","ops",".","(","Defaults","to","`","'RationalQuadraticSpline","'","`",")","."]
code: def __init__(
      self,
      bin_widths,
      bin_heights,
      knot_slopes,
      range_min=-1,
      validate_args=False,
      name=None,
  ):
      """Construct a new RationalQuadraticSpline bijector.
  
      For each argument, the innermost axis indexes bins/knots and batch axes
      index axes of `x`/`y` spaces. A `RationalQuadraticSpline` with a separate
      transform for each of three dimensions might have `bin_widths` shaped
      `[3, 32]`. To use the same spline for each of `x`'s three dimensions we may
      broadcast against `x` and use a `bin_widths` parameter shaped `[32]`.
      Parameters will be broadcast against each other and against the input
      `x`/`y`s, so if we want fixed slopes, we can use kwarg `knot_slopes=1`.
  
      A typical recipe for acquiring compatible bin widths and heights would be:
  
      ```python
      nbins = unconstrained_vector.shape[-1]
      range_min, range_max, min_bin_size = -1, 1, 1e-2
      scale = range_max - range_min - nbins * min_bin_size
      bin_widths = tf.math.softmax(unconstrained_vector) * scale + min_bin_size
      ```
  
      Args:
        bin_widths: The widths of the spans between subsequent knot `x` positions,
          a floating point `Tensor`. Must be positive, and at least 1-D. Innermost
          axis must sum to the same value as `bin_heights`. The knot `x` positions
          will be a first at `range_min`, followed by knots at `range_min +
          cumsum(bin_widths, axis=-1)`.
        bin_heights: The heights of the spans between subsequent knot `y`
          positions, a floating point `Tensor`. Must be positive, and at least
          1-D. Innermost axis must sum to the same value as `bin_widths`. The knot
          `y` positions will be a first at `range_min`, followed by knots at
          `range_min + cumsum(bin_heights, axis=-1)`.
        knot_slopes: The slope of the spline at each knot, a floating point
          `Tensor`. Must be positive. `1`s are implicitly padded for the first and
          last implicit knots corresponding to `range_min` and `range_min +
          sum(bin_widths, axis=-1)`. Innermost axis size should be 1 less than
          that of `bin_widths`/`bin_heights`, or 1 for broadcasting.
        range_min: The `x`/`y` position of the first knot, which has implicit
          slope `1`. `range_max` is implicit, and can be computed as `range_min +
          sum(bin_widths, axis=-1)`. Scalar floating point `Tensor`.
        validate_args: Toggles argument validation (can hurt performance).
        name: Optional name scope for associated ops. (Defaults to
          `'RationalQuadraticSpline'`).
      """
      parameters = dict(locals())
      with tf.name_scope(name or "RationalQuadraticSpline") as name:
          dtype = dtype_util.common_dtype(
              [bin_widths, bin_heights, knot_slopes, range_min],
              dtype_hint=tf.float32,
          )
          self._bin_widths = tensor_util.convert_nonref_to_tensor(
              bin_widths, dtype=dtype, name="bin_widths"
          )
          self._bin_heights = tensor_util.convert_nonref_to_tensor(
              bin_heights, dtype=dtype, name="bin_heights"
          )
          self._knot_slopes = tensor_util.convert_nonref_to_tensor(
              knot_slopes, dtype=dtype, name="knot_slopes"
          )
          self._range_min = tensor_util.convert_nonref_to_tensor(
              range_min, dtype=dtype, name="range_min"
          )
          super(RationalQuadraticSpline, self).__init__(
              dtype=dtype,
              forward_min_event_ndims=0,
              validate_args=validate_args,
              parameters=parameters,
              name=name,
          )
  
imports: import collections
  import functools
  import tensorflow.compat.v2
  from tensorflow_probability.python.bijectors import bijector
  from tensorflow_probability.python.bijectors import softplus
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import tensor_util
  from tensorflow_probability.python.internal import tensorshape_util
label_desc: Use image node_id 1 to create a new RationalQuadraticSpline object from inherited base classes: bijector with example: obj = RationalQuadraticSpline(bin_widths, bin_heights, knot_slopes, range_min, validate_args, name)