o
    ?e                     @   s&  d Z ddlZddlZddlZddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ 					dWddZdd Z	dXddZdd ZdYddZ						dZddZdd Zd d! Zd"d# Zd$d% Z d&d' Z!d(d) Z"	*d[d+d*Z#	,	-d\d.d/Z$d]d1d0Z%d^d2d3Z&d_d5d4Z'd`d7d6Z(	8dad9d8Z)d:d; Z*d<d= Z+d>d? Z,d@dA Z-dbdBdCZ.dbdDdEZ/dcdFdGZ0					dddHdIZ1dYdJdKZ2dLdM Z3	dYdNdOZ4dedQdRZ5dSdT Z6G dUdV dVZ7dS )fz(Utilities for probability distributions.    N)constant_op)dtypes)ops)tensor_shape)tensor_util)	array_ops)array_ops_stack)	check_ops)cond)control_flow_ops)
linalg_ops)math_ops)nn)
tf_inspectassert_integer_formc              	   C   s   t j|| |gdb t j| dd} | jjr t W  d   S |p&d| }|du rPztj	tj
tjtjtjtji| jj }W n tyO   td| jjw tj| tt| || j||||dW  d   S 1 snw   Y  dS )ax  Assert that x has integer components (or floats equal to integers).

  Args:
    x: Floating-point `Tensor`
    data: The tensors to print out if the condition is `False`. Defaults to
      error message and first few entries of `x` and `y`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    int_dtype: A `tf.dtype` used to cast the float to. The default (`None`)
      implies the smallest possible signed int will be used for casting.
    name: A name for this operation (optional).

  Returns:
    Op raising `InvalidArgumentError` if `cast(x, int_dtype) != x`.
  valuesxnameNz{} has non-integer componentszUnrecognized type {})data	summarizemessager   )r   
name_scopeconvert_to_tensordtype
is_integerr   Zno_opformatr   float16int16float32int32float64int64
base_dtypeKeyError	TypeErrorr   r	   assert_equalr   cast)r   r   r   r   	int_dtyper    r*   i/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/distributions/util.pyr   &   s4   $c                 C   s    t | }tt| |g| S N)r   Zmatrix_transposer   with_dependenciesr	   r'   )matrixZmatrix_tr*   r*   r+   assert_symmetricR   s   
r/   $embed_check_nonnegative_integer_formc                 C   s   t j|| gd0 t j| dd} tj| d| dg}| jjs+|t| d| dg7 }t	
|| W  d   S 1 s;w   Y  dS )z>Assert x is a non-negative tensor, and optionally of integers.r   r   r   z'{}' must be non-negative.r   z*'{}' cannot contain fractional components.N)r   r   r   r	   assert_non_negativer   r   r   r   r   r-   )r   r   
assertionsr*   r*   r+   r0   X   s   

$c                    sP   t j dd t jdd fdd}ttt t|dd S )zReturns whether a and b have the same dynamic shape.

  Args:
    a: `Tensor`
    b: `Tensor`

  Returns:
    `bool` `Tensor` representing if both tensors have the same shape.
  ar   bc                      sB   t t tt tgdttt gdS )Nr   )r   Z
reduce_allequalr   concatshaper*   r4   r5   r*   r+   all_shapes_equalz   s   z,same_dynamic_shape.<locals>.all_shapes_equalc                   S   s
   t dS )NF)r   constantr*   r*   r*   r+   <lambda>   s   
 z$same_dynamic_shape.<locals>.<lambda>)r   r   tf_condr
   r   r6   r   rank)r4   r5   r:   r*   r9   r+   same_dynamic_shapej   s   

r?   c                 C   sR   | du r| S zt | }W n ty   | }Y nw |du s!|du r#|S t||S )a`  Helper which tries to return a static value.

  Given `x`, extract it's value statically, optionally casting to a specific
  dtype. If this is not possible, None is returned.

  Args:
    x: `Tensor` for which to extract a value statically.
    dtype: Optional dtype to cast to.

  Returns:
    Statically inferred value if possible, otherwise None.
  N)r   constant_valuer&   nparray)r   r   Zx_r*   r*   r+   maybe_get_static_value   s   rC   Fget_logits_and_probsc              	   C   s   t j||| gd |du | du krtd|du rRt j| d|d} | jjs*td|rB|r2t| } | tj	| ddfW  d   S | t
j| ddfW  d   S t j|d|d}|jjsbtd	|rt d
< td|j}t|g}|rt|}|tjt
|d|ddg7 }n|tj||ddg7 }t||}W d   n1 sw   Y  t d4 |rt
||fW  d   W  d   S t
|t
d|  |fW  d   W  d   S 1 sw   Y  W d   dS 1 sw   Y  dS )a  Converts logit to probabilities (or vice-versa), and returns both.

  Args:
    logits: Floating-point `Tensor` representing log-odds.
    probs: Floating-point `Tensor` representing probabilities.
    multidimensional: Python `bool`, default `False`. If `True`, represents
      whether the last dimension of `logits` or `probs`, a `[N1, N2, ...  k]`
      dimensional tensor, representing the logit or probability of `shape[-1]`
      classes.
    validate_args: Python `bool`, default `False`. When `True`, either assert `0
      <= probs <= 1` (if not `multidimensional`) or that the last dimension of
      `probs` sums to one.
    name: A name for this operation (optional).
    dtype: `tf.DType` to prefer when converting args to `Tensor`s.

  Returns:
    logits, probs: Tuple of `Tensor`s. If `probs` has an entry that is `0` or
      `1`, then the corresponding entry in the returned logit will be `-Inf` and
      `Inf` respectively.

  Raises:
    ValueError: if neither `probs` nor `logits` were passed in, or both were.
  r   Nz(Must pass probs or logits, but not both.logitsr   r   z!logits must having floating type.probsr   z probs must having floating type.Zvalidate_probsg      ?zprobs does not sum to 1.r1   z$probs has components greater than 1.g      )r   r   
ValueErrorr   r   is_floatingr&   #embed_check_categorical_event_shaper   Zsoftmaxr   Zsigmoidr   r;   r	   r2   Zassert_near
reduce_sumassert_less_equalr   r-   loglog1p)rE   rG   Zmultidimensionalvalidate_argsr   r   onedependenciesr*   r*   r+   rD      s^   
1'"c                 C   s    t jdt jdt jdi| jdS )z7Helper returning True if dtype is known to be unsigned.TF)r   boolZuint8Zuint16getr$   dtr*   r*   r+   _is_known_unsigned_by_dtype   s   
rW   c                 C   s8   t jdt jdt jdt jdt jdt jdt jdi| j	dS )z5Helper returning True if dtype is known to be signed.TF)
r   r   r    r"   Zint8r   r!   r#   rT   r$   rU   r*   r*   r+   _is_known_signed_by_dtype   s   
rX   c                 C   s   t | pt| S )z(Helper returning True if dtype is known.)rW   rX   rU   r*   r*   r+   _is_known_dtype	  s   rY   c                 C   sp   t | std| j| jrtdt| jj	d  S | j
r&t| jjS | jtjkr0tdS td| j)zDHelper returning the largest integer exactly representable by dtype.Unrecognized dtype: {}      )rY   r&   r   r   rJ   intrA   finfoas_numpy_dtypeZnmantr   Ziinfomaxr$   r   rS   rU   r*   r*   r+   _largest_integer_by_dtype  s   ra   c                 C   s0   t | std| jt| rdS dt|  S )zEHelper returning the smallest integer exactly representable by dtype.rZ   r   rH   )rY   r&   r   r   rW   ra   rU   r*   r*   r+   _smallest_integer_by_dtype  s
   rb   c                 C   s*   t | std| j| jp| jtjkS )z7Helper returning True if dtype.is_integer or is `bool`.rZ   )rY   r&   r   r   r   r$   r   rS   rU   r*   r*   r+   _is_integer_like_by_dtype%  s   rc   rK   c                 C   sV  t j|| gd t j| dd}|jj}|jrt|nd}|dkr)td|j	z	|
 d}W n ty=   tdw t|d d	url|jd j}|d
k rUtd||krctd|j	|||W  d	   S tj|ddd }ttj|dddtjt|d d
ddtj||d|j	|dg|W  d	   S 1 sw   Y  d	S )a  Embeds checks that categorical distributions don't have too many classes.

  A categorical-type distribution is one which, e.g., returns the class label
  rather than a one-hot encoding.  E.g., `Categorical(probs)`.

  Since distributions output samples in the same dtype as the parameters, we
  must ensure that casting doesn't lose precision. That is, the
  `parameter.dtype` implies a maximum number of classes. However, since shape is
  `int32` and categorical variables are presumed to be indexes into a `Tensor`,
  we must also ensure that the number of classes is no larger than the largest
  possible `int32` index, i.e., `2**31-1`.

  In other words the number of classes, `K`, must satisfy the following
  condition:

  ```python
  K <= min(
      int(2**31 - 1),  # Largest float as an index.
      {
          dtypes.float16: int(2**11),   # Largest int as a float16.
          dtypes.float32: int(2**24),
          dtypes.float64: int(2**53),
      }.get(categorical_param.dtype.base_dtype, 0))
  ```

  Args:
    categorical_param: Floating-point `Tensor` representing parameters of
      distribution over categories. The rightmost shape is presumed to be the
      number of categories.
    name: A name for this operation (optional).

  Returns:
    categorical_param: Input `Tensor` with appropriate assertions embedded.

  Raises:
    TypeError: if `categorical_param` has an unknown `dtype`.
    ValueError: if we can statically identify `categorical_param` as being too
      large (for being closed under int32/float casting).
  r   categorical_paramr   r   z3Unable to validate size of unrecognized dtype ({}).r\   zDA categorical-distribution parameter must have at least 1 dimension.rH   Nr[   zAA categorical-distribution parameter must have at least 2 events.zZNumber of classes exceeds `dtype` precision, i.e., {} implies shape ({}) cannot exceed {}.Zx_shaper1   zSNumber of classes exceeds `dtype` precision, i.e., {} dtype cannot exceed {} shape.)r   r   r   r   r$   rJ   ra   r&   r   r   	get_shapewith_rank_at_leastrI   r   dimension_valuedimsvaluer   r8   r   r-   r	   Zassert_rank_at_leastassert_greater_equalrM   )rd   r   r   Zx_dtypeZmax_event_sizeZx_shape_staticZ
event_sizer*   r*   r+   rK   ,  sd   )
!$Tembed_check_casting_closedc              	   C   s  t j|| gd t j| dd} t| js"| jjs"td| jjt|s1|js1td|jt| jsFt|sFtd| | jj|jg }|rT|t	j
| ddg7 }| jjrg|t| |d	|jd
g7 }n8t| jt|kr|t	j| t|dt|dg7 }|st| jt|k r|t	j| t|dt|dg7 }|s| W  d   S t|| W  d   S 1 sw   Y  dS )a  Ensures integers remain unaffected despite casting to/from int/float types.

  Example integer-types: `uint8`, `int32`, `bool`.
  Example floating-types: `float32`, `float64`.

  The largest possible integer representable by an IEEE754 floating-point is
  `2**(1 + mantissa_bits)` yet the largest possible integer as an int-type is
  `2**(bits - 1) - 1`. This function ensures that a `Tensor` purporting to have
  integer-form values can be cast to some other type without loss of precision.

  The smallest representable integer is the negative of the largest
  representable integer, except for types: `uint8`, `uint16`, `bool`. For these
  types, the smallest representable integer is `0`.

  Args:
    x: `Tensor` representing integer-form values.
    target_dtype: TF `dtype` under which `x` should have identical values.
    assert_nonnegative: `bool` indicating `x` should contain nonnegative values.
    name: A name for this operation (optional).

  Returns:
    x: Input `Tensor` with appropriate assertions embedded.

  Raises:
    TypeError: if `x` is neither integer- nor floating-type.
    TypeError: if `target_dtype` is neither integer- nor floating-type.
    TypeError: if neither `x` nor `target_dtype` are integer-type.
  r   r   r   z+{}.dtype must be floating- or integer-type.z4target_dtype ({}) must be floating- or integer-type.zIAt least one of {}.dtype ({}) and target_dtype ({}) must be integer-type.zElements must be non-negative.r1   zElements must be {}-equivalent.)r)   r   zElements cannot exceed {}.z#Elements cannot be smaller than {}.N)r   r   r   rc   r   rJ   r&   r   r   r	   r2   r   ra   rM   rb   rj   r   r-   )r   Ztarget_dtypeZassert_nonnegativer   r3   r*   r*   r+   "embed_check_integer_casting_closed  s   !



7$rl   log_combinationsc                 C   s   t j|| |gd0 t j| dd} t j|dd}t| d }t|d }tj|dgd}|| W  d   S 1 s<w   Y  dS )	aX  Multinomial coefficient.

  Given `n` and `counts`, where `counts` has last dimension `k`, we compute
  the multinomial coefficient as:

  ```n! / sum_i n_i!```

  where `i` runs over all `k` classes.

  Args:
    n: Floating-point `Tensor` broadcastable with `counts`. This represents `n`
      outcomes.
    counts: Floating-point `Tensor` broadcastable with `n`. This represents
      counts in `k` classes, where `k` is the last dimension of the tensor.
    name: A name for this operation (optional).

  Returns:
    `Tensor` representing the multinomial coefficient between `n` and `counts`.
  r   nr   countsr\   rH   axisN)r   r   r   r   lgammarL   )rn   ro   r   Ztotal_permutationsZcounts_factorialZredundant_permutationsr*   r*   r+   rm     s   $c                 C   s|   t |d| g, t j| dd} |du r| W  d   S t| }||}t| |}W d   |S 1 s7w   Y  |S )a  Transform diagonal of [batch-]matrix, leave rest of matrix unchanged.

  Create a trainable covariance defined by a Cholesky factor:

  ```python
  # Transform network layer into 2 x 2 array.
  matrix_values = tf.contrib.layers.fully_connected(activations, 4)
  matrix = tf.reshape(matrix_values, (batch_size, 2, 2))

  # Make the diagonal positive. If the upper triangle was zero, this would be a
  # valid Cholesky factor.
  chol = matrix_diag_transform(matrix, transform=tf.nn.softplus)

  # LinearOperatorLowerTriangular ignores the upper triangle.
  operator = LinearOperatorLowerTriangular(chol)
  ```

  Example of heteroskedastic 2-D linear regression.

  ```python
  tfd = tfp.distributions

  # Get a trainable Cholesky factor.
  matrix_values = tf.contrib.layers.fully_connected(activations, 4)
  matrix = tf.reshape(matrix_values, (batch_size, 2, 2))
  chol = matrix_diag_transform(matrix, transform=tf.nn.softplus)

  # Get a trainable mean.
  mu = tf.contrib.layers.fully_connected(activations, 2)

  # This is a fully trainable multivariate normal!
  dist = tfd.MultivariateNormalTriL(mu, chol)

  # Standard log loss. Minimizing this will "train" mu and chol, and then dist
  # will be a distribution predicting labels as multivariate Gaussians.
  loss = -1 * tf.reduce_mean(dist.log_prob(labels))
  ```

  Args:
    matrix:  Rank `R` `Tensor`, `R >= 2`, where the last two dimensions are
      equal.
    transform:  Element-wise function mapping `Tensors` to `Tensors`. To be
      applied to the diagonal of `matrix`. If `None`, `matrix` is returned
      unchanged. Defaults to `None`.
    name:  A name to give created ops. Defaults to "matrix_diag_transform".

  Returns:
    A `Tensor` with same shape and `dtype` as `matrix`.
  matrix_diag_transformr.   r   N)r   r   r   r   Zmatrix_diag_partZmatrix_set_diag)r.   Z	transformr   diagZtransformed_diagZtransformed_matr*   r*   r+   rs     s   2

		rs   rotate_transposec              
   C   sd  t j|| |gd t j| dd} t j|dd}t| t|}|  j}|durk|durk|dk r<| W  d   S t	
|t||  }|dkrT| W  d   S t	t	||}tj| |dW  d   S t| }tt|dt| ||t|| }td|}t||}t||gd}tj| |dW  d   S 1 sw   Y  dS )	a)  Circularly moves dims left or right.

  Effectively identical to:

  ```python
  numpy.transpose(x, numpy.roll(numpy.arange(len(x.shape)), shift))
  ```

  When `validate_args=False` additional graph-runtime checks are
  performed. These checks entail moving data from to GPU to CPU.

  Example:

  ```python
  x = tf.random.normal([1, 2, 3, 4])  # Tensor of shape [1, 2, 3, 4].
  rotate_transpose(x, -1).shape == [2, 3, 4, 1]
  rotate_transpose(x, -2).shape == [3, 4, 1, 2]
  rotate_transpose(x,  1).shape == [4, 1, 2, 3]
  rotate_transpose(x,  2).shape == [3, 4, 1, 2]
  rotate_transpose(x,  7).shape == rotate_transpose(x, 3).shape  # [2, 3, 4, 1]
  rotate_transpose(x, -7).shape == rotate_transpose(x, -3).shape  # [4, 1, 2, 3]
  ```

  Args:
    x: `Tensor`.
    shift: `Tensor`. Number of dimensions to transpose left (shift<0) or
      transpose right (shift>0).
    name: Python `str`. The name to give this op.

  Returns:
    rotated_x: Input `Tensor` with dimensions circularly rotated by shift.

  Raises:
    TypeError: if shift is not integer type.
  r   r   r   shiftNr[   r   )perm)r   r   r   r	   Zassert_integerr   r@   re   ndimsrA   signabsZrollZaranger   Z	transposer>   where_v2r   lessmodranger7   )r   rv   r   Zshift_value_staticrx   rw   firstlastr*   r*   r+   ru   F  s<   $






$pick_vectorc              
   C   s  t j|| ||fdv t j| dd} | jtjkr#td| | jtjf t| }|dur9|r0|n|W  d   S t j|dd}t j|dd}|j|jkrYtd||j||jf t	
|d	 }t	t	||gd	t	| d	|gt	| |d
gW  d   S 1 sw   Y  dS )a  Picks possibly different length row `Tensor`s based on condition.

  Value `Tensor`s should have exactly one dimension.

  If `cond` is a python Boolean or `tf.constant` then either `true_vector` or
  `false_vector` is immediately returned. I.e., no graph nodes are created and
  no validation happens.

  Args:
    cond: `Tensor`. Must have `dtype=tf.bool` and be scalar.
    true_vector: `Tensor` of one dimension. Returned when cond is `True`.
    false_vector: `Tensor` of one dimension. Returned when cond is `False`.
    name: Python `str`. The name to give this op.
  Example:  ```python pick_vector(tf.less(0, 5), tf.range(10, 12), tf.range(15,
    18))  # [10, 11] pick_vector(tf.less(5, 0), tf.range(10, 12), tf.range(15,
    18))  # [15, 16, 17] ```

  Returns:
    true_or_false_vector: `Tensor`.

  Raises:
    TypeError: if `cond.dtype != tf.bool`
    TypeError: if `cond` is not a constant and
      `true_vector.dtype != false_vector.dtype`
  r   r
   r   z%s.dtype=%s which is not %sNtrue_vectorfalse_vectorz&%s.dtype=%s does not match %s.dtype=%sr   rH   )r   r   r   r   r   rS   r&   r   r@   r   r8   slicer7   r{   where)r
   r   r   r   Zcond_value_staticrn   r*   r*   r+   r     s0   

$prefer_static_broadcast_shapec                    s   t j|| |gdC dd   fdd} fdd}|| }||}|dur7|dur7t||W  d   S || }||}t||W  d   S 1 sOw   Y  dS )	a  Convenience function which statically broadcasts shape when possible.

  Args:
    shape1:  `1-D` integer `Tensor`.  Already converted to tensor!
    shape2:  `1-D` integer `Tensor`.  Already converted to tensor!
    name:  A string name to prepend to created ops.

  Returns:
    The broadcast shape, either as `TensorShape` (if broadcast can be done
      statically), or as a `Tensor`.
  r   c                 S   s   t j| dtjdS )Nr8   rF   )r   r   r   r!   r   r*   r*   r+   make_shape_tensor  s   z8prefer_static_broadcast_shape.<locals>.make_shape_tensorc                    s4   t | tjr| S t | }|d urt|S d S r,   )
isinstancer   TensorShaper   r@   )sZs_r   r*   r+   get_tensor_shape  s   
z7prefer_static_broadcast_shape.<locals>.get_tensor_shapec                    s0   t | tjs
 | S |  r |  S td)Nz6Cannot broadcast from partially defined `TensorShape`.)r   r   r   is_fully_definedas_listrI   )r   r   r*   r+   get_shape_tensor  s
   z7prefer_static_broadcast_shape.<locals>.get_shape_tensorN)r   r   r   Zbroadcast_static_shapeZbroadcast_dynamic_shape)Zshape1Zshape2r   r   r   Zshape1_Zshape2_r*   r   r+   r     s   

$c                 C      t t| S )zReturn static rank of tensor `x` if available, else `tf.rank(x)`.

  Args:
    x: `Tensor` (already converted).

  Returns:
    Numpy array (if static rank is obtainable), else `Tensor`.
  )prefer_static_valuer   r>   r   r*   r*   r+   prefer_static_rank     	r   c                 C   r   )zReturn static shape of tensor `x` if available, else `tf.shape(x)`.

  Args:
    x: `Tensor` (already converted).

  Returns:
    Numpy array (if static shape is obtainable), else `Tensor`.
  )r   r   r8   r   r*   r*   r+   prefer_static_shape  r   r   c                 C   s   t | }|dur|S | S )zReturn static value of tensor `x` if available, else `x`.

  Args:
    x: `Tensor` (already converted).

  Returns:
    Numpy array (if static value is obtainable), else `Tensor`.
  N)r   r@   )r   Zstatic_xr*   r*   r+   r     s   
	r   c                 C   s>   | du rdS t | | d}tt| dd dd@ S )z2Generate a new seed, from the given seed and salt.Nzutf-8      i)strencoder]   hashlibmd5	hexdigest)seedsaltstringr*   r*   r+   gen_new_seed  s    r   c           	   	   C   s  t j|d| gd t j| dd} t| jdd durSt| jj	d j
}tdd	|  d
 }|t|krAtd|t|}| jdd ||g}n+t| d }tjtdtjd| tjd tjd}| jddd ddg}t| }|r| tj| d|df |d gdg}n| d|df tj| |d gdg}| r| ntjt| dd ||ggdd}ttj|dd|} tj| |rdnd|rdndd} | | | W  d   S 1 sw   Y  dS )a  Creates a (batch of) triangular matrix from a vector of inputs.

  Created matrix can be lower- or upper-triangular. (It is more efficient to
  create the matrix as upper or lower, rather than transpose.)

  Triangular matrix elements are filled in a clockwise spiral. See example,
  below.

  If `x.get_shape()` is `[b1, b2, ..., bB, d]` then the output shape is
  `[b1, b2, ..., bB, n, n]` where `n` is such that `d = n(n+1)/2`, i.e.,
  `n = int(np.sqrt(0.25 + 2. * m) - 0.5)`.

  Example:

  ```python
  fill_triangular([1, 2, 3, 4, 5, 6])
  # ==> [[4, 0, 0],
  #      [6, 5, 0],
  #      [3, 2, 1]]

  fill_triangular([1, 2, 3, 4, 5, 6], upper=True)
  # ==> [[1, 2, 3],
  #      [0, 5, 6],
  #      [0, 0, 4]]
  ```

  For comparison, a pure numpy version of this function can be found in
  `util_test.py`, function `_fill_triangular`.

  Args:
    x: `Tensor` representing lower (or upper) triangular elements.
    upper: Python `bool` representing whether output matrix should be upper
      triangular (`True`) or lower triangular (`False`, default).
    name: Python `str`. The name to give this op.

  Returns:
    tril: `Tensor` with lower (or upper) triangular elements filled from `x`.

  Raises:
    ValueError: if `x` cannot be mapped to a triangular matrix.
  fill_triangularr   r   r   r\   rH   Ng      ?       @g      ?zGInput right-most shape ({}) does not correspond to a triangular matrix.r[   r   .rp   r   )Z	num_lowerZ	num_upper)r   r   r   r   rg   r8   rf   rA   r!   rh   ri   sqrtfloorrI   r   concatenater   r   r(   r   r    r   reverser   r   r7   reshapeZmatrix_band_part	set_shape)	r   upperr   mrn   static_final_shaperx   Zx_listZ	new_shaper*   r*   r+   r     sJ   +
%&$"
$r   c              	   C   s  t j|d| gd t j| dd} t| jdd dur?t| jj	d j
}t||d  d }| jdd	 |g}nt| d }||d  d }| jddd	 dg}t| }|rw| d
dddf }| d
ddddf }ntj| d
dddf |d gd}| d
ddddf }tjtj||d gd|d gd}	||	 }
t|
tjt| dd	 ||d  ggdd}tj||d
d|| f gdd}|| |W  d   S 1 sw   Y  dS )a  Creates a vector from a (batch of) triangular matrix.

  The vector is created from the lower-triangular or upper-triangular portion
  depending on the value of the parameter `upper`.

  If `x.shape` is `[b1, b2, ..., bB, n, n]` then the output shape is
  `[b1, b2, ..., bB, d]` where `d = n (n + 1) / 2`.

  Example:

  ```python
  fill_triangular_inverse(
    [[4, 0, 0],
     [6, 5, 0],
     [3, 2, 1]])

  # ==> [1, 2, 3, 4, 5, 6]

  fill_triangular_inverse(
    [[1, 2, 3],
     [0, 5, 6],
     [0, 0, 4]], upper=True)

  # ==> [1, 2, 3, 4, 5, 6]
  ```

  Args:
    x: `Tensor` representing lower (or upper) triangular elements.
    upper: Python `bool` representing whether output matrix should be upper
      triangular (`True`) or lower triangular (`False`, default).
    name: Python `str`. The name to give this op.

  Returns:
    flat_tril: (Batch of) vector-shaped `Tensor` representing vectorized lower
      (or upper) triangular elements from `x`.
  fill_triangular_inverser   r   r   r[   rH   Nr\   .r   rp   )r   r   r   r   rg   r8   rf   rA   r!   rh   ri   r   r   r   r   r   r7   r   )r   r   r   rn   r   r   rx   Zinitial_elementsZtriangular_portionZrotated_triangular_portionZconsolidated_matrixZend_sequenceyr*   r*   r+   r     sD   &"("
$r   c                 C   s   dd }dd }t |d| ||gT | dur.t j| dd} t|| d	dd
ddf } |dur>t j|dd}t|}|durYt j|dd}t||d	dddd
f }|| ||W  d   S 1 siw   Y  dS )a'  Creates a matrix with values set above, below, and on the diagonal.

  Example:

  ```python
  tridiag(below=[1., 2., 3.],
          diag=[4., 5., 6., 7.],
          above=[8., 9., 10.])
  # ==> array([[  4.,   8.,   0.,   0.],
  #            [  1.,   5.,   9.,   0.],
  #            [  0.,   2.,   6.,  10.],
  #            [  0.,   0.,   3.,   7.]], dtype=float32)
  ```

  Warning: This Op is intended for convenience, not efficiency.

  Args:
    below: `Tensor` of shape `[B1, ..., Bb, d-1]` corresponding to the below
      diagonal part. `None` is logically equivalent to `below = 0`.
    diag: `Tensor` of shape `[B1, ..., Bb, d]` corresponding to the diagonal
      part.  `None` is logically equivalent to `diag = 0`.
    above: `Tensor` of shape `[B1, ..., Bb, d-1]` corresponding to the above
      diagonal part.  `None` is logically equivalent to `above = 0`.
    name: Python `str`. The name to give this op.

  Returns:
    tridiag: `Tensor` with values set above, below and on the diagonal.

  Raises:
    ValueError: if all inputs are `None`.
  c                 S   sF   t jt | dd dggdd}t j|| jd}t j|| |gddS )zBPrepends and appends a zero to every vector in a batch of vectors.NrH   r\   r   rp   r   )r   r7   r8   Zzerosr   )r   r8   zr*   r*   r+   _pad  s   "ztridiag.<locals>._padc                  W   sB   d}| D ]}|du rq|du r|}q||7 }q|du rt d|S )z&Adds list of Tensors, ignoring `None`.Nz6Must specify at least one of `below`, `diag`, `above`.)rI   )r   r   r   r*   r*   r+   _add  s   
ztridiag.<locals>._addtridiagNbelowr   .rH   r\   rt   above)r   r   r   r   Zmatrix_diag)r   rt   r   r   r   r   r*   r*   r+   r     s   ! 
 
$r   c                 C   sT  t |d| |g t j| dd} |du r8tj| ||d}|r/t|}||fW  d   S |W  d   S t j|| jdd}| tt	| }tj
||dd}	tt|	t|	|	}	t|t||	  }
tj|
||d}|s|t|	|}	t|}|	t||  }|r||fW  d   S |W  d   S 1 sw   Y  dS )	a  Computes `log(abs(sum(weight * exp(elements across tensor dimensions))))`.

  If all weights `w` are known to be positive, it is more efficient to directly
  use `reduce_logsumexp`, i.e., `tf.reduce_logsumexp(logx + tf.math.log(w))` is
  more
  efficient than `du.reduce_weighted_logsumexp(logx, w)`.

  Reduces `input_tensor` along the dimensions given in `axis`.
  Unless `keep_dims` is true, the rank of the tensor is reduced by 1 for each
  entry in `axis`. If `keep_dims` is true, the reduced dimensions
  are retained with length 1.

  If `axis` has no entries, all dimensions are reduced, and a
  tensor with a single element is returned.

  This function is more numerically stable than log(sum(w * exp(input))). It
  avoids overflows caused by taking the exp of large inputs and underflows
  caused by taking the log of small inputs.

  For example:

  ```python
  x = tf.constant([[0., 0, 0],
                   [0, 0, 0]])

  w = tf.constant([[-1., 1, 1],
                   [1, 1, 1]])

  du.reduce_weighted_logsumexp(x, w)
  # ==> log(-1*1 + 1*1 + 1*1 + 1*1 + 1*1 + 1*1) = log(4)

  du.reduce_weighted_logsumexp(x, w, axis=0)
  # ==> [log(-1+1), log(1+1), log(1+1)]

  du.reduce_weighted_logsumexp(x, w, axis=1)
  # ==> [log(-1+1+1), log(1+1+1)]

  du.reduce_weighted_logsumexp(x, w, axis=1, keep_dims=True)
  # ==> [[log(-1+1+1)], [log(1+1+1)]]

  du.reduce_weighted_logsumexp(x, w, axis=[0, 1])
  # ==> log(-1+5)
  ```

  Args:
    logx: The tensor to reduce. Should have numeric type.
    w: The weight tensor. Should have numeric type identical to `logx`.
    axis: The dimensions to reduce. If `None` (the default), reduces all
      dimensions. Must be in the range `[-rank(input_tensor),
      rank(input_tensor))`.
    keep_dims: If true, retains reduced dimensions with length 1.
    return_sign: If `True`, returns the sign of the result.
    name: A name for the operation (optional).

  Returns:
    lswe: The `log(abs(sum(weight * exp(x))))` reduced tensor.
    sign: (Optional) The sign of `sum(weight * exp(x))`.
  reduce_weighted_logsumexplogxr   N)rq   keepdimswr   r   T)r   r   r   r   Zreduce_logsumexpr   	ones_liker   rN   rz   Z
reduce_maxr{   Zis_infZ
zeros_likery   exprL   Zsqueeze)r   r   rq   Z	keep_dimsZreturn_signr   ZlsweZsgnZ
log_absw_xZmax_log_absw_xZwx_over_max_absw_xZsum_wx_over_max_absw_xr*   r*   r+   r     s>   @

$r   c              
   C   s   t j|d| gdY t j| dd} tt| jjjd }t	
| t|}t	| | }t	| }| }tt	||t| | } | t	t	|    }t||t|||W  d   S 1 sew   Y  dS )ac  Computes the inverse softplus, i.e., x = softplus_inverse(softplus(x)).

  Mathematically this op is equivalent to:

  ```none
  softplus_inverse = log(exp(x) - 1.)
  ```

  Args:
    x: `Tensor`. Non-negative (not enforced), floating-point.
    name: A name for the operation (optional).

  Returns:
    `Tensor`. Has the same type/shape as input `x`.
  softplus_inverser   r   r   r   N)r   r   r   rA   rN   r^   r   r_   Zepsr   r|   r   Zgreaterr   r{   
logical_orr   expm1)r   r   	thresholdZis_too_smallZis_too_largeZtoo_small_valueZtoo_large_valuer   r*   r*   r+   r   {  s"   
$r   c                 C   s6   t | jt|| }|dur|S t| | S )z)Returns the size of a specific dimension.N)r   rg   r8   rf   rA   rz   r   )r   rq   r   r*   r*   r+   dimension_size  s   r   c           
   	   C   s  t |d| g | du rItjjjdd\}}||j}||j}|tjj	|ddd }t j
|d|d	}t j
|d
|d	}||fW  d   S t| \}}t j
|d|d	}t j
|d|d	}|tj	|dddd
d }dd }||||}}|dur|dur||krtd||n2|rtjt|ddt|ddddg}	t |	 t|}t|}W d   n1 sw   Y  ||fW  d   S 1 sw   Y  dS )a  Validates quadrature grid, probs or computes them as necessary.

  Args:
    quadrature_grid_and_probs: Python pair of `float`-like `Tensor`s
      representing the sample points and the corresponding (possibly
      normalized) weight.  When `None`, defaults to:
        `np.polynomial.hermite.hermgauss(deg=8)`.
    dtype: The expected `dtype` of `grid` and `probs`.
    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.

  Returns:
     quadrature_grid_and_probs: Python pair of `float`-like `Tensor`s
      representing the sample points and the corresponding (possibly
      normalized) weight.

  Raises:
    ValueError: if `quadrature_grid_and_probs is not None` and
      `len(quadrature_grid_and_probs[0]) != len(quadrature_grid_and_probs[1])`
  !process_quadrature_grid_and_probsNr   )degr\   T)ordr   gridrF   rG   Zunnormalized_probsrH   )r   rq   r   r   c                 S   s   t | jdd S )z:Returns the static size of a specific dimension or `None`.r\   rH   )r   rg   r8   rf   r   r*   r*   r+   _static_event_size  s   z=process_quadrature_grid_and_probs.<locals>._static_event_sizezm`quadrature_grid_and_probs` must be a `tuple` of same-length zero-th-dimension `Tensor`s (saw lengths {}, {})rp   zX`quadrature_grid_and_probs` must be a `tuple` of same-length zero-th-dimension `Tensor`sr1   )r   r   rA   Z
polynomialZhermiteZ	hermgaussZastyper_   ZlinalgZnormr   tupler   rI   r   r	   r'   r   Zcontrol_dependenciesr   identity)
Zquadrature_grid_and_probsr   rP   r   r   rG   r   r   rn   r3   r*   r*   r+   r     sJ   


$r   r\   c              
   C   s  t |d| ||g t j| dd} t j|| jdd}t j|dd}|jjs/td|jj|s7|s7td| j	j
d	urA| j	j
ntj| d
d}t j|dd}t|}|d	ur|}|dk rb|| }t|}	|dksq| j	j
d	ur| j	d	| }
t|	d	u rd	nt| j	||	||   }| j	|d d	 }|
||}qd	}nt|dk || |}d	}tj| tjt|r|nd|r|ndg|d|tjd|d} |d	ur| | | W  d	   S 1 sw   Y  d	S )aZ  Pads `value` to the front and/or back of a `Tensor` dim, `count` times.

  Args:
    x: `Tensor` input.
    axis: Scalar `int`-like `Tensor` representing the single dimension to pad.
      (Negative indexing is supported.)
    front: Python `bool`; if `True` the beginning of the `axis` dimension is
      padded with `value`, `count` times. If `False` no front padding is made.
    back: Python `bool`; if `True` the end of the `axis` dimension is padded
      with `value`, `count` times. If `False` no end padding is made.
    value: Scalar `int`-like `Tensor` representing the actual value added to the
      front and/or back of the `axis` dimension of `x`.
    count: Scalar `int`-like `Tensor` representing number of elements added to
      the front and/or back of the `axis` dimension of `x`. E.g., if `front =
      back = True` then `2 * count` elements are added.
    name: Python `str` name prefixed to Ops created by this function.

  Returns:
    pad: The padded version of input `x`.

  Raises:
    ValueError: if both `front` and `back` are `False`.
    TypeError: if `count` is not `int`-like.
  padr   r   ri   r   countz(`count.dtype` (`{}`) must be `int`-like.z/At least one of `front`, `back` must be `True`.Nrx   rq   r   r\   rH   )indicesdepthrq   Zon_valuer   )ZpaddingsZconstant_values)r   r   r   r   r   r&   r   r   rI   r8   rx   r   r>   r   r@   r   r   Zdimension_at_indexr   r{   r   Zone_hotr   stackr   r!   r   )r   rq   Zfrontbackri   r   r   rx   Zaxis_Zcount_headmiddletailZfinal_shaper*   r*   r+   r     sd   



$r   c                  C   sd   t jt j d d \} }}}||i  ||i }i }| D ]	}||||< q!|| |S )aL  Returns parent frame arguments.

  When called inside a function, returns a dictionary with the caller's function
  arguments. These are positional arguments and keyword arguments (**kwargs),
  while variable arguments (*varargs) are excluded.

  When called at global scope, this will return an empty dictionary, since there
  are no arguments.

  WARNING: If caller function argument names are overloaded before invoking
  this method, then values will reflect the overloaded value. For this reason,
  we recommend calling `parent_frame_arguments` at the beginning of the
  function.
  r\   r   )r   _inspectgetargvaluesr   popupdate)	arg_namesZvariable_arg_nameZkeyword_arg_name
local_varsZkeyword_argsZ
final_argsZarg_namer*   r*   r+   parent_frame_argumentsI  s   

r   c                   @   s"   e Zd ZdZdddZdd ZdS )	AppendDocstringaL  Helper class to promote private subclass docstring to public counterpart.

  Example:

  ```python
  class TransformedDistribution(Distribution):
    @distribution_util.AppendDocstring(
      additional_note="A special note!",
      kwargs_dict={"foo": "An extra arg."})
    def _prob(self, y, foo=None):
      pass
  ```

  In this case, the `AppendDocstring` decorator appends the `additional_note` to
  the docstring of `prob` (not `_prob`) and adds a new `kwargs`
  section with each dictionary item as a bullet-point.

  For a more detailed example, see `TransformedDistribution`.
   Nc                 C   s   || _ |rHg }t| D ],}|| }tdd |D r"td| | }d|v r0td| |d||f  q|  j dd| 7  _ dS dS )	a  Initializes the AppendDocstring object.

    Args:
      additional_note: Python string added as additional docstring to public
        version of function.
      kwargs_dict: Python string/string dictionary representing specific kwargs
        expanded from the **kwargs input.

    Raises:
      ValueError: if kwargs_dict.key contains whitespace.
      ValueError: if kwargs_dict.value contains newlines.
    c                 s   s    | ]}|  V  qd S r,   )isspace).0r   r*   r*   r+   	<genexpr>  s    z+AppendDocstring.__init__.<locals>.<genexpr>z(Parameter name "%s" contains whitespace.
z1Parameter description for "%s" contains newlines.z*  `%s`: %sz

##### `kwargs`:

N)_additional_notesortedkeysanyrI   lstripappendjoin)selfZadditional_noteZkwargs_dictZbulletskeyri   r*   r*   r+   __init__  s   zAppendDocstring.__init__c                    sD   t   fdd}|jd u r| j|_|S | jd| j 7  _|S )Nc                     s    | i |S r,   r*   )argskwargsfnr*   r+   _fn  s   z%AppendDocstring.__call__.<locals>._fnz
%s)	functoolswraps__doc__r   )r   r   r   r*   r   r+   __call__  s   
zAppendDocstring.__call__)r   N)__name__
__module____qualname__r   r   r   r*   r*   r*   r+   r   n  s    
r   )NNNNr   )r0   r,   )NNFFrD   N)rK   )Trk   )rm   )NN)ru   )r   )r   )FN)NNNN)NNFFN)FFr   r\   N)8r   r   r   numpyrA   Ztensorflow.python.frameworkr   r   r   r   r   Ztensorflow.python.opsr   r   r	   r
   r=   r   r   r   r   Ztensorflow.python.utilr   r   r/   r0   r?   rC   rD   rW   rX   rY   ra   rb   rc   rK   rl   rm   rs   ru   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r*   r*   r*   r+   <module>   s   
,


Q		
a

[
"
>
M0
-

s
EE

b9

CG%