
    AVh                     *   d Z ddlZddlZddl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  edddg      ej:                   ej<                  d      dMd                     Z ed      ej@                  ej:                  dMd                     Z! ed      ej@                  ej:                  dMd                     Z" ed      ej@                  ej:                  dMd                     Z# ed      ej@                  ej:                  dMd                     Z$ ed      ej@                  ej:                  dMd                     Z% edd      ej@                  ej:                  dMd                      Z& ed!d"      ej@                  ej:                  dMd#                     Z' ed$d%      ej@                  ej:                  dMd&                     Z( ed'd(      ej@                  ej:                  dMd)                     Z) ed*      ej@                  ej:                  dMd+                     Z* ed,      ej@                  ej:                  dMd-                     Z+ ed.      ej@                  ej:                  dMd/                     Z, ed0      ej@                  ej:                  dMd1                     Z- ed2      ej@                  ej:                  dMd3                     Z. ed4      ej@                  ej:                  dMd5                     Z/ ed6      ej@                  ej:                  dMd7                     Z0 ed8      ej@                  ej:                  dMd9                     Z1 ejd                  d:      d;        Z3d< Z4 ed=d>      ej:                  d?               Z5d@ Z6dA Z7dB Z8dC Z9dD Z:dE Z;dF Z<dG Z=dH Z>dI Z?  ej                  dJK      e?      Z?dL ZAy)NzArithmetic Operations that don't fit into math_ops due to dependencies.

To avoid circular dependencies, some math_ops should go here.
    N)gen_xla_ops)ops)tensor)tensor_shape)	array_ops)control_flow_ops)gen_linalg_ops)gen_special_math_ops)math_ops)
tf_logging)deprecation)dispatch)	tf_exportz
math.lbetalbeta)v1c                 J   t        j                  |d| g      5  t        j                  | d      } t        j                  t        j
                  |       dg      }t        j                  | dg      }t        j
                  |      }||z
  }|cddd       S # 1 sw Y   yxY w)a  Computes \\(ln(|Beta(x)|)\\), reducing along the last dimension.

  Given one-dimensional $z = [z_1,...,z_K]$, we define

  $$Beta(z) = \frac{\prod_j \Gamma(z_j)}{\Gamma(\sum_j z_j)},$$

  where $\Gamma$ is the gamma function.

  And for $n + 1$ dimensional $x$ with shape $[N_1, ..., N_n, K]$, we define

  $$lbeta(x)[i_1, ..., i_n] = \log{|Beta(x[i_1, ..., i_n, :])|}.$$

  In other words, the last dimension is treated as the $z$ vector.

  Note that if $z = [u, v]$, then

  $$Beta(z) = \frac{\Gamma(u)\Gamma(v)}{\Gamma(u + v)}
    = \int_0^1 t^{u-1} (1 - t)^{v-1} \mathrm{d}t,$$

  which defines the traditional bivariate beta function.

  If the last dimension is empty, we follow the convention that the sum over
  the empty set is zero, and the product is one.

  Args:
    x: A rank `n + 1` `Tensor`, `n >= 0` with type `float`, or `double`.
    name: A name for the operation (optional).

  Returns:
    The logarithm of \\(|Beta(x)|\\) reducing along the last dimension.
  r   x)nameaxisN)r   
name_scopeconvert_to_tensorr   
reduce_sumlgamma)r   r   log_prod_gamma_xsum_xlog_gamma_sum_xresults         V/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/special_math_ops.pyr   r   -   s    N ~~dGaS) ac*A  **8??1+=RDI -Eooe,O/F  s   A6BB"zmath.special.dawsnc                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes Dawson's integral of `x` element-wise.

  Dawson's integral is defined as `exp(-x**2)` times the integral of
  `exp(t**2)` from `0` to `x`, with the domain of definition all real numbers.

  Dawson's function is odd.
  >>> tf.math.special.dawsn([-1., -0.5, 0.5, 1.]).numpy()
  array([-0.5380795, -0.4244364, 0.4244364,  0.5380795], dtype=float32)

  This implementation is based off of the Cephes math library.

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types:
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.dawsn
  @end_compatibility
  dawsnN)r   r   r
   r"   r   r   s     r    r"   r"   e   s9    6 ~~dGaS) )%%a() ) )	   8Azmath.special.expintc                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes the Exponential integral of `x` element-wise.

  The Exponential integral is defined as the integral of `exp(t) / t` from
  `-inf` to `x`, with the domain of definition all positive real numbers.

  >>> tf.math.special.expint([1., 1.1, 2.1, 4.1]).numpy()
  array([ 1.8951179,  2.1673784,  5.3332353, 21.048464], dtype=float32)

  This implementation is based off of the Cephes math library.

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types:
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.expi
  @end_compatibility
  expintN)r   r   r
   r&   r#   s     r    r&   r&      9    4 ~~dHqc* *&&q)* * *r$   zmath.special.fresnel_cosc                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes Fresnel's cosine integral of `x` element-wise.

  The Fresnel cosine integral is defined as the integral of `cos(t^2)` from
  `0` to `x`, with the domain of definition all real numbers.

  The Fresnel cosine integral is odd.
  >>> tf.math.special.fresnel_cos([-1., -0.1, 0.1, 1.]).numpy()
  array([-0.7798934 , -0.09999753,  0.09999753,  0.7798934 ], dtype=float32)

  This implementation is based off of the Cephes math library.

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types:
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.fresnel second output.
  @end_compatibility
  fresnel_cosN)r   r   r
   r)   r#   s     r    r)   r)      s9    6 ~~dMA3/ /++A./ / /r$   zmath.special.fresnel_sinc                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes Fresnel's sine integral of `x` element-wise.

  The Fresnel sine integral is defined as the integral of `sin(t^2)` from
  `0` to `x`, with the domain of definition all real numbers.

  >>> tf.math.special.fresnel_sin([-1., -0.1, 0.1, 1.]).numpy()
  array([-0.43825912, -0.00052359,  0.00052359,  0.43825912], dtype=float32)

  This implementation is based off of the Cephes math library.

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types:
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.fresnel first output.
  @end_compatibility
  fresnel_sinN)r   r   r
   r+   r#   s     r    r+   r+      s9    4 ~~dMA3/ /++A./ / /r$   zmath.special.spencec                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes Spence's integral of `x` element-wise.

  Spence's integral is defined as the integral of `log(t) / (1 - t)` from
  `1` to `x`, with the domain of definition all non-negative real numbers.

  >>> tf.math.special.spence([0.5, 1., 2., 3.]).numpy()
  array([ 0.58224034,  0.        , -0.82246685, -1.4367464], dtype=float32)

  This implementation is based off of the Cephes math library.

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types:
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.spence
  @end_compatibility
  spenceN)r   r   r
   r-   r#   s     r    r-   r-      r'   r$   zmath.bessel_i0zmath.special.bessel_i0c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes the Bessel i0 function of `x` element-wise.

  Modified Bessel function of order 0.

  It is preferable to use the numerically stabler function `i0e(x)` instead.

  >>> tf.math.special.bessel_i0([-1., -0.5, 0.5, 1.]).numpy()
  array([1.26606588, 1.06348337, 1.06348337, 1.26606588], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.i0
  @end_compatibility
  	bessel_i0N)r   r   r
   r/   r#   s     r    r/   r/      9    2 ~~dK!- -))!,- - -r$   zmath.bessel_i0ezmath.special.bessel_i0ec                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a4  Computes the Bessel i0e function of `x` element-wise.

  Modified Bessel function of order 0.

  >>> tf.math.special.bessel_i0e([-1., -0.5, 0.5, 1.]).numpy()
  array([0.46575961, 0.64503527, 0.64503527, 0.46575961], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.i0e
  @end_compatibility
  
bessel_i0eN)r   r   r
   r2   r#   s     r    r2   r2     9    . ~~dL1#. .**1-. . .r$   zmath.bessel_i1zmath.special.bessel_i1c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a  Computes the Bessel i1 function of `x` element-wise.

  Modified Bessel function of order 1.

  It is preferable to use the numerically stabler function `i1e(x)` instead.

  >>> tf.math.special.bessel_i1([-1., -0.5, 0.5, 1.]).numpy()
  array([-0.5651591 , -0.25789431,  0.25789431,  0.5651591 ], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.i1
  @end_compatibility
  	bessel_i1N)r   r   r
   r5   r#   s     r    r5   r5   5  r0   r$   zmath.bessel_i1ezmath.special.bessel_i1ec                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a8  Computes the Bessel i1e function of `x` element-wise.

  Modified Bessel function of order 1.

  >>> tf.math.special.bessel_i1e([-1., -0.5, 0.5, 1.]).numpy()
  array([-0.20791042, -0.15642083,  0.15642083,  0.20791042], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.i1e
  @end_compatibility
  
bessel_i1eN)r   r   r
   r7   r#   s     r    r7   r7   R  r3   r$   zmath.special.bessel_k0c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a|  Computes the Bessel k0 function of `x` element-wise.

  Modified Bessel function of order 0.

  It is preferable to use the numerically stabler function `k0e(x)` instead.

  >>> tf.math.special.bessel_k0([0.5, 1., 2., 4.]).numpy()
  array([0.92441907, 0.42102444, 0.11389387, 0.01115968], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.k0
  @end_compatibility
  	bessel_k0N)r   r   r
   r9   r#   s     r    r9   r9   m  r0   r$   zmath.special.bessel_k0ec                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a1  Computes the Bessel k0e function of `x` element-wise.

  Modified Bessel function of order 0.

  >>> tf.math.special.bessel_k0e([0.5, 1., 2., 4.]).numpy()
  array([1.52410939, 1.14446308, 0.84156822, 0.60929767], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.k0e
  @end_compatibility
  
bessel_k0eN)r   r   r
   r;   r#   s     r    r;   r;     r3   r$   zmath.special.bessel_k1c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a|  Computes the Bessel k1 function of `x` element-wise.

  Modified Bessel function of order 1.

  It is preferable to use the numerically stabler function `k1e(x)` instead.

  >>> tf.math.special.bessel_k1([0.5, 1., 2., 4.]).numpy()
  array([1.65644112, 0.60190723, 0.13986588, 0.0124835 ], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.k1
  @end_compatibility
  	bessel_k1N)r   r   r
   r=   r#   s     r    r=   r=     r0   r$   zmath.special.bessel_k1ec                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a1  Computes the Bessel k1e function of `x` element-wise.

  Modified Bessel function of order 1.

  >>> tf.math.special.bessel_k1e([0.5, 1., 2., 4.]).numpy()
  array([2.73100971, 1.63615349, 1.03347685, 0.68157595], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.k1e
  @end_compatibility
  
bessel_k1eN)r   r   r
   r?   r#   s     r    r?   r?     r3   r$   zmath.special.bessel_j0c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a2  Computes the Bessel j0 function of `x` element-wise.

  Modified Bessel function of order 0.

  >>> tf.math.special.bessel_j0([0.5, 1., 2., 4.]).numpy()
  array([ 0.93846981,  0.76519769,  0.22389078, -0.39714981], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.j0
  @end_compatibility
  	bessel_j0N)r   r   r
   rA   r#   s     r    rA   rA     9    . ~~dK!- -))!,- - -r$   zmath.special.bessel_j1c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a2  Computes the Bessel j1 function of `x` element-wise.

  Modified Bessel function of order 1.

  >>> tf.math.special.bessel_j1([0.5, 1., 2., 4.]).numpy()
  array([ 0.24226846,  0.44005059,  0.57672481, -0.06604333], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.j1
  @end_compatibility
  	bessel_j1N)r   r   r
   rD   r#   s     r    rD   rD     rB   r$   zmath.special.bessel_y0c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a2  Computes the Bessel y0 function of `x` element-wise.

  Modified Bessel function of order 0.

  >>> tf.math.special.bessel_y0([0.5, 1., 2., 4.]).numpy()
  array([-0.44451873,  0.08825696,  0.51037567, -0.01694074], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.y0
  @end_compatibility
  	bessel_y0N)r   r   r
   rF   r#   s     r    rF   rF     rB   r$   zmath.special.bessel_y1c                     t        j                  |d| g      5  t        j                  |       cddd       S # 1 sw Y   yxY w)a2  Computes the Bessel y1 function of `x` element-wise.

  Modified Bessel function of order 1.

  >>> tf.math.special.bessel_y1([0.5, 1., 2., 4.]).numpy()
  array([-1.47147239, -0.78121282, -0.10703243,  0.39792571], dtype=float32)

  Args:
    x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`.

  @compatibility(scipy)
  Equivalent to scipy.special.y1
  @end_compatibility
  	bessel_y1N)r   r   r
   rH   r#   s     r    rH   rH   .  rB   r$   	XlaEinsumc           
         | j                  d      }t        |t              r|j                         }|j	                  d      \  }}|j	                  d      \  }}t        j                  || j                  d   dj                  |||      d       t        j                  || j                  d   dj                  |||      d       gS )Nequation->,   z	{},{}->{})rK   r   r   )	get_attr
isinstancebytesdecodesplitr   
xla_einsuminputsformat)opgradrK   rU   outputleftrights          r    _einsum_gradr\   I  s    [[$(%  H>>$'.&&S!+$ 

))A,%%feT:	
 

))A,%%fdE:	
     c                      t        j                         j                         } | Ct        | t        j
                        s)| j                  } | t        | t        j
                        s)| S N)r   get_default_graph_get_control_flow_contextrP   r   XLAControlFlowContextouter_context)contexts    r    _enclosing_tpu_contextre   `  s_    !!#==?'J55%7##G 	J55%7 
.r]   einsumzlinalg.einsumc                      t        | g|i |S )a  Tensor contraction over specified indices and outer product.

  Einsum allows defining Tensors by defining their element-wise computation.
  This computation is defined by `equation`, a shorthand form based on Einstein
  summation. As an example, consider multiplying two matrices A and B to form a
  matrix C.  The elements of C are given by:

  $$ C_{i,k} = \sum_j A_{i,j} B_{j,k} $$

  or

  ```
  C[i,k] = sum_j A[i,j] * B[j,k]
  ```

  The corresponding einsum `equation` is:

  ```
  ij,jk->ik
  ```

  In general, to convert the element-wise equation into the `equation` string,
  use the following procedure (intermediate strings for matrix multiplication
  example provided in parentheses):

  1. remove variable names, brackets, and commas, (`ik = sum_j ij * jk`)
  2. replace "*" with ",", (`ik = sum_j ij , jk`)
  3. drop summation signs, and (`ik = ij, jk`)
  4. move the output to the right, while replacing "=" with "->". (`ij,jk->ik`)

  Note: If the output indices are not specified repeated indices are summed.
  So `ij,jk->ik` can be simplified to `ij,jk`.

  Many common operations can be expressed in this way.  For example:

  **Matrix multiplication**

  >>> m0 = tf.random.normal(shape=[2, 3])
  >>> m1 = tf.random.normal(shape=[3, 5])
  >>> e = tf.einsum('ij,jk->ik', m0, m1)
  >>> # output[i,k] = sum_j m0[i,j] * m1[j, k]
  >>> print(e.shape)
  (2, 5)

  Repeated indices are summed if the output indices are not specified.

  >>> e = tf.einsum('ij,jk', m0, m1)  # output[i,k] = sum_j m0[i,j] * m1[j, k]
  >>> print(e.shape)
  (2, 5)


  **Dot product**

  >>> u = tf.random.normal(shape=[5])
  >>> v = tf.random.normal(shape=[5])
  >>> e = tf.einsum('i,i->', u, v)  # output = sum_i u[i]*v[i]
  >>> print(e.shape)
  ()

  **Outer product**

  >>> u = tf.random.normal(shape=[3])
  >>> v = tf.random.normal(shape=[5])
  >>> e = tf.einsum('i,j->ij', u, v)  # output[i,j] = u[i]*v[j]
  >>> print(e.shape)
  (3, 5)

  **Transpose**

  >>> m = tf.ones(2,3)
  >>> e = tf.einsum('ij->ji', m0)  # output[j,i] = m0[i,j]
  >>> print(e.shape)
  (3, 2)

  **Diag**

  >>> m = tf.reshape(tf.range(9), [3,3])
  >>> diag = tf.einsum('ii->i', m)
  >>> print(diag.shape)
  (3,)

  **Trace**

  >>> # Repeated indices are summed.
  >>> trace = tf.einsum('ii', m)  # output[j,i] = trace(m) = sum_i m[i, i]
  >>> assert trace == sum(diag)
  >>> print(trace.shape)
  ()

  **Batch matrix multiplication**

  >>> s = tf.random.normal(shape=[7,5,3])
  >>> t = tf.random.normal(shape=[7,3,2])
  >>> e = tf.einsum('bij,bjk->bik', s, t)
  >>> # output[a,i,k] = sum_j s[a,i,j] * t[a, j, k]
  >>> print(e.shape)
  (7, 5, 2)

  This method does not support broadcasting on named-axes. All axes with
  matching labels should have the same length. If you have length-1 axes,
  use `tf.squeeze` or `tf.reshape` to eliminate them.

  To write code that is agnostic to the number of indices in the input
  use an ellipsis. The ellipsis is a placeholder for "whatever other indices
  fit here".

  For example, to perform a NumPy-style broadcasting-batch-matrix multiplication
  where the matrix multiply acts on the last two axes of the input, use:

  >>> s = tf.random.normal(shape=[11, 7, 5, 3])
  >>> t = tf.random.normal(shape=[11, 7, 3, 2])
  >>> e =  tf.einsum('...ij,...jk->...ik', s, t)
  >>> print(e.shape)
  (11, 7, 5, 2)

  Einsum **will** broadcast over axes covered by the ellipsis.

  >>> s = tf.random.normal(shape=[11, 1, 5, 3])
  >>> t = tf.random.normal(shape=[1, 7, 3, 2])
  >>> e =  tf.einsum('...ij,...jk->...ik', s, t)
  >>> print(e.shape)
  (11, 7, 5, 2)

  Args:
    equation: a `str` describing the contraction, in the same format as
      `numpy.einsum`.
    *inputs: the inputs to contract (each one a `Tensor`), whose shapes should
      be consistent with `equation`.
    **kwargs:
      - optimize: Optimization strategy to use to find contraction path using
        opt_einsum. Must be 'greedy', 'optimal', 'branch-2', 'branch-all' or
          'auto'. (optional, default: 'greedy').
      - name: A name for the operation (optional).

  Returns:
    The contracted `Tensor`, with shape determined by `equation`.

  Raises:
    ValueError: If
      - the format of `equation` is incorrect,
      - number of inputs or their shapes are inconsistent with `equation`.
  )
_einsum_v2)rK   rU   kwargss      r    rf   rf   j  s    b 
H	0v	0	00r]   c                    |j                  dd      }|rUt        ddj                  t        t	        |j                                     D cg c]  }t        |       c}       d      t        j                  |d| |g      5 }t	        |      }|D cg c]  }|j                   }}t        | |      \  }t        dj                  |      z         }|D ]  |D ]~  }	t        |      dk(  rH|	j                        d	k(  r4|	|	ddd
   k(  r)d| vr%t        j                  |d         c c cddd       S |	j                        dkD  snt!        d d|	 d        |D ]P  t#        fd|D              }
|
d	kD  svs"t%        j&                  d d       t)        | g| c cddd       S  t+               Ft        |      d	k(  r8t-        j.                  |d   |d   |d   dz   |d   z   dz   z         cddd       S |d   }|d   }t1        t        |      dz
        D ]I  }t        |      t        ||dz            t              z
  z  }t3        ||||dz      ||dz      |      \  }}K t        |      t              z
  }|rRt5        |      D cg c]  \  }}|vr| }}}t        j6                  ||      }dj                  fd|D              }t        |      t              k7  rt!        d|  d| d d      D cg c]  }|j9                  |       }}t;        ||      cddd       S c c}w c c}w c c}}w c c}w # 1 sw Y   yxY w)z7Legacy implementation of einsum without using EinsumOp.r   Nz-Invalid keyword arguments for this function: , z. Expected: name.rf    rN      r   rL   r   z"Subscript not supported: the axis z appears more than once in .c              3   ,   K   | ]  }|v sd   ywrN   N ).0sas     r    	<genexpr>z_einsum_v1.<locals>.<genexpr>  s     ?aQ?   	zKFalling back to exponential-space implementation of einsum() because index z% is summed over more than two inputs.rM   r   c              3   ,   K   | ]  }|v s|  y wr_   rq   )rr   rt   output_axis_labelss     r    ru   z_einsum_v1.<locals>.<genexpr>7  s       !B.@)@!!Brv   zInvalid equation: z9. The computed and specified output labels do not match: z vs )pop	TypeErrorjoinsortedlistkeysrV   r   r   shape%_einsum_v1_parse_and_resolve_equationsetlencountr   trace
ValueErrorsumloggingwarn_exponential_space_einsum_v1re   r   rT   range_einsum_v1_reduction	enumerater   index_transpose_if_necessary)rK   rU   ri   r   keyr   input_shapesinput_axis_labelsaxis_labelsinput_labelsinput_counttemptemp_axis_labelsiaxes_to_summissing_indicesrt   r   permrx   s                   `  @r    
_einsum_v1r     s   	FD	!$

799VD4G-HIcfSkIJ
K L	  ~~dHx&89 9/T&\F%+,AGG,L,-hE *) bgg/03EEFK &+ &,!"a'L,>,>q,AQ,FL2..4x3Gq	*
*9/ 9/ a 1$21# 6!N!%& &&&  ??#4??k	qQ&88S EG	H ,H>v>>/9/ 9/"? +Fq0@##
)VAY 1! 4s :
A
!!%!&(:!;<99/ 9/> !9D(+3v;?# A


A&
'#.@*A
AB   4D:J4:1q5M4Ea!e4L4? Ad	A *+c2D.EEO!"231(( d    D1d !B%!B B6*<#==xj )""2!348J7K1NO O 0BB!""1%BDB"4.s9/ 9/ J -T Cq9/ 9/sd   L<MM(BM6M3M?M&M4AMBMM)A$MM%MMMc           
         | j                  dd      } t        j                  d|       }|st        d|  d      |j	                  d      j                  d      |j	                  d      r|j	                  d      dd	 nd	}t        |      t              k7  r't        d
t        |       d|  dt               d      d}d| v rndj                  fdt        j                  D              }t              D ]  \  }}d|v s|j                  d      }t        |      dk7  rt        dt        |      dz
   d      ||   j                  t        d      ||   j                  t        dj                  |            z
  }	|	dk  rt        d      t        |      |	k  rt        d      |	dkD  r||	 d	 nd}
|   j                  d|
      |<   t        |
      t        |      kD  s|
} t        d D              rt        d d      |%|j                  d|      }d|v rt        d| d      |t        dj                              t        |      z
  }dj                  t        |            }|D ci c]  }|d c}D ]  }|D ]  }||vs|xx   dz  cc<     |dj                  t        fd|D                    z   }|fS c c}w )a  Helper for einsum() that splits/resolves inputs & outputs.

  Args:
    equation: Equation string given as argument to einsum().
    input_shapes: List of the shapes of all inputs given to einsum()

  Returns:
    input_axis_labels, output_axis_labels where:
      input_axis_labels: List of length len(input_shapes) of strings
      representing the character label for each dimension of each given input,
      resolving any broadcast (...) axes,
    output_axis_labels: A string of character labels for each axes of output
      tensor, filling in missing output subscripts and broadcast axes.

  Raises:
    ValueError: If equation is in the uncorrect format, incorrect number of
      inputs given or broadcast axes "..." or output axes could not be resolved.
   rl   z^([a-zA-Z,.]+)(->[a-zA-Z.]*)?$z)Indices have incorrect format. Received: rn   rN   rM   rm   NzGot z arguments for equation "z", expecting ...c              3   J   K   | ]  }|d j                        vs|  yw)rl   N)r{   )rr   cr   s     r    ru   z8_einsum_v1_parse_and_resolve_equation.<locals>.<genexpr>h  s)      P1BGG<M4N+NPs   ##z1Unable to resolve ellipsis. Excess number found: z vs 1.zXUnable to statically infer ellipsis axes. The input shapes has a dynamic dimensionality.r   zEllipses lengths do not match.z5Unable to resolve ellipsis, too many distinct labels.c              3   $   K   | ]  }d |v  
 yw)rn   Nrq   )rr   axs     r    ru   z8_einsum_v1_parse_and_resolve_equation.<locals>.<genexpr>  s     
13"9
1s   z.Period "." found outside of ellipsis in input z/Period "." found outside of ellipsis in output c              3   4   K   | ]  }|   d k(  s|  ywrp   rq   )rr   r   countss     r    ru   z8_einsum_v1_parse_and_resolve_equation.<locals>.<genexpr>  s     ;b6":?r;s   )replacerematchr   grouprS   r   r{   stringascii_lettersr   ndimsanyr   r|   )rK   r   r   rx   ellipsis_axesunusedr   r   partsnreplace_axesr   indicesaxes_r   r   s                 @@r    r   r   B  sH   & c2&(
((3X
>%	
@
!L
MMkk!n**3/-2[[^u{{1~ab)#/00

s< !!:8* E*+,A	/0 0 -
hWW P''P PF,- '2	"u:? 336u:a<.H I I?  ( H I IO!!C$77q5;<
<v;?EG G&'!evqbc{03;;E<H J!|s=11&-''* 
10
11:;L:MQ
OQ Q %-55e]K	"	"J./q2 3 	3  bgg/01C4FFKggf[)*G%&b!e&F"  "]"
*/*
 ';K;;*= = 
.	.. 's   <
Kc           	         t              t        | j                        k7  r.t        dt        | j                         dt               d      t              t        |j                        k7  r-t        dt        |j                         dt                     t        fdD              sJ t	              t	              z  z
  i t        g      D ]  \  }t	        |      z
  z
  <    fdg}t        |      D cg c]  \  }t        |fd       }}}| |g}	t        |      D ]8  \  }
|   D cg c]  }|
j                  |       }}t        |	   |      |	<   : |	\  } }sd	   D ]  }t        j                  | d
      }  d   D ]!  }t        j                  |t                    }# t        j                  | |      }|d   |d	   t              d z   }|dj                  |      fS t        |       }t        |t              t                      }t        |t               d       }|dt               ||gz   }t!        | |      } t        |      }t        |t              t              z   d       }|dt               ||gz   }t!        ||      }t        j"                  | |      }|dt              t        d         z    |t        |      t        d	         z
  d z   }t!        ||      }|d   dt              t        d         z    |d	   t        |d	         t        d	         z
  d z   }|dj                  |      fS c c}}w c c}w )a  Helper for einsum() that computes the result of a two-argument einsum().

  Args:
    t0: a `Tensor`
    t0_axis_labels: a string of axis labels.  This string's length must equal
      the rank of t0.
    t1: a `Tensor`
    t1_axis_labels: a string to axis labels.  This string's length must equal
      the rank of t1.
    axes_to_sum: set of labels of axes to be summed over

  Returns:
    A `Tensor` whose elements are obtained by summing, over all axes in
    `axes_to_sum`, the corresponding elements of `t0` and `t1`.

    For example, if t0_axis_labels == 'abijk', t1_axis_labels == 'acjkl', and
    axes_to_sum == {j,k}, this will return a tensor x where

      out[a,b,c,i,l] = sum_j sum_k t0[a,b,i,j,k] * t1[a,c,j,k,l]

  Raises:
    ValueError: if the rank of `t0` does not match the length of
      `t0_axis_labels`, or that of `t1` does not match the length of
      `t1_axis_labels`.
  zTensor `t0` of rank z+ does not match einsum reduction of length rn   zTensor `t1` of rank c              3   2   K   | ]  }|v xr |v   y wr_   rq   )rr   rt   t0_axis_labelst1_axis_labelss     r    ru   z'_einsum_v1_reduction.<locals>.<genexpr>  s#     NQQ. 8Q.%88Ns   c                 N    |v rd|fS | dk(  r|d   v s	| dk(  r|v rd|fS d|fS )Nr   r   rN   rq   )input_indexrt   r   broadcast_axespreserved_axess     r    sort_keyz&_einsum_v1_reduction.<locals>.sort_key  sI    N!Wn!^A%6 6![ 0VmVmr]   c                      |       S r_   rq   )rt   r   r   s    r    <lambda>z&_einsum_v1_reduction.<locals>.<lambda>  s    Xa^ r]   r   rN   r   r   Nrl   )r   r   r   allr   r   r|   findr   r   expand_dimsr   multiplyr{   
_get_shape_total_size_reshape_if_necessarymatmul)t0r   t1r   r   sym_listr   r   sorted_axesrU   axes_strrt   r   _productproduct_axest0_shapenum_broadcast_elements_t0num_summed_elements	new_shapet1_shapenum_broadcast_elements_t1uncompacted_shaper   r   r   s    ` ``  `               @@@r    r   r     s   4 	CM)

s288}o .()	,- - 	CM)

s288}o .()	+, ,$ 
N+N	NN	N'#n*==L..?@ EkaH6DN1E  0+ #;/ 
!X X34+  8&{+ 9ka&1!n5HMM!5D5'q	48F1I9 &"b	 A )  R(b)A :  S%89b:B'Gq>KN3~3F3G$HHLBGGL))) "~H +^$c+&6%67!9%hK0@/@/A&BC%#n%&	"$78	9  
r9	-B"~H +^$s;'7789!; 	%#n%&	78	9  
r9	-Boob"%G 	>#n%N1,=(>>?X^A%6!7789	:  $G->?G 	ADN+c.2C.DDEAs;q>*S1B-CCDE	F  BGGL)))q 6s   M7M=c                 t    |t        t        t        |                  k7  rt        j                  | |      S | S )z?Like transpose(), but avoids creating a new tensor if possible.)r   )r}   r   r   r   	transpose)r   r   s     r    r   r     s0    	T%D	"##vD11Mr]   c                    t        d |D              }t        d | j                  j                  D              }t        |      t        |      k(  rt	        d t        ||      D              r| S t        j                  | |      S )z=Like reshape(), but avoids creating a new tensor if possible.c              3   (   K   | ]
  }|dn|  y w)Nr   rq   rr   r   s     r    ru   z(_reshape_if_necessary.<locals>.<genexpr>%  s     >q!)B*>s   c              3   4   K   | ]  }|j                     y wr_   )valuer   s     r    ru   z(_reshape_if_necessary.<locals>.<genexpr>&  s     7AGG7s   c              3   t   K   | ]0  \  }}t        |t        j                         xr ||k(  xs |d k(   2 yw)r   N)rP   
tensor_libTensor)rr   d0d1s      r    ru   z(_reshape_if_necessary.<locals>.<genexpr>(  sA      
3b" Z../
/
JR2X5Ir
J 
3s   68)tupler   dimsr   r   zipr   reshape)r   r   	cur_shapes      r    r   r   "  sr     >I>>)7V\\%6%677)	)nI&	 
3Iy1
3 3MVY//r]   c                     | j                   j                         }t        |      D cg c]
  \  }}|	| }}}|r$t        j                   |       }|D ]
  }||   ||<    |S c c}}w )zLike get_shape().as_list(), but explicitly queries the shape of a tensor
  if necessary to ensure that the returned value contains no unknown value.)r   as_listr   r   )r   r   r   dnone_indicesshape_tensors         r    r   r   /  sm     ,,


 % )% 0>1AI!>,>??6*L !aeAh!	, ?s
   
A#A#c                 "    d}| D ]  }||z  }	 |S )zGiven list of tensor shape values, returns total size.
  If shape_values contains tensor values (which are results of
  array_ops.shape), then it returns a scalar tensor.
  If not, it returns an integer.rN   rq   )shape_valuesr   vals      r    r   r   =  s&     & c
cMF	-r]   c                    t        |      }|D cg c]  }|j                   }}t        | |      \  }}t        dj	                  |      |z         }dj	                  t        |            }t        |      j                  |      }|rt        d| d      i }	|D ]  }
|
|vst        |	      |	|
<    |D ]  }
t        |	      |	|
<    t        t        ||            D ]  \  }\  }}|j                  j                  t        |      k7  r5t        d| d| dt        |       d|j                  j                   d	      t        ||	j                  	      }t        t        |            t        |      k7  rt        d
| d      t        |      |k7  s|D 
cg c]  }
|j                  |
       }}
t        j                  ||      ||<   |||<    g }|D cg c].  }|j                  j!                         D cg c]  }|r|nd
 c}0 }}}t        t        ||	j                  	            D ]  \  }}
g }t        |      D ]O  \  }}|
|vr||   j#                  |d        ||   |   }t%        |t&              s9|dkD  s?|j)                  |       Q t        t        |            dkD  r$t        d|
 dt        t        |             d      |
|vs|j)                  |        t        ||      D cg c]  \  }}t        j*                  ||       }}}d}|D ]  }||z  }	 t-        j.                  ||      S c c}w c c}
w c c}w c c}}w c c}}w )zGFallback implementation that supports summing an index over > 2 inputs.rl   zUnknown output axes: rn   zInput z with axes z. has incorrect number of dimensions (expected z, got z).r   z9Subscript not supported: an axis appears more than once: r   rN   zDimension mismatch on axis: z. Found z, expected 1.)r}   r   r   r   r{   r|   
differencer   r   r   r   r   getr   r   r   r   insertrP   intappendr   r   r   )rK   rU   r   r   idx_inidx_outidx_allr   missing_idx
axis_orderr   r   input_r   
sorted_idxpermutedreduction_idxr   dimshapesjr   idxr   expanded_inputsexpanded_outputs                             r    r   r   I  s   <&#)*a!''*,*9/&' ')*'GGF7O$'G''0+
,[M;
<<* 'b	:jn'  %b_JrN% &c&&&9: a&%||SZ'1#[ (5zl&););(<B@A A :>>2J
3u:#e*$EeWA
NP P E{j +56R%**R.6h6%%fh7fQifQi" - !" ,,.0 SR 0 "& "
 Z^^<= eaDF# 3	3q	AQilc3C!G
++c
 3t9~5bT :  #CI/}> ? ? 
1& =@<O+865i&/  / fvO 
		_m	<<I +@ 7
0 ".s)   L:L?!M	7MM	3 MM	c                 "   |j                  dd      }|j                  dd      }|rt        ddj                  |       d      t        j                  |d| |g      5 }t        |      }g }|D ]  }t        |j                  t        j                        r8|j                  |j                  r|j                  j                         nd       _|j                  t        |j                                t        | |      \  }}}	t        |      d	k  r3|	r|j                  |	d
      }t        j                   ||      cddd       S t#        j$                  ddg      }
t'        |D cg c]  } |
t'        |             c}      }t)        |||      }|D ]]  \  }}|	r|j                  |	d
      }t        t+        |j                   |            }|j                  t        j                   ||             _ |d   cddd       S c c}w # 1 sw Y   yxY w)z;Implementation of einsum utilizing opt_einsum and EinsumOp.r   Noptimizegreedyz&Invalid keyword arguments for einsum: rk   z*. Valid arguments: name, optimize, greedy.rf   rm   r   shapedr   r   )ry   rz   r{   r   r   r}   rP   r   r   TensorShaper   r   %_einsum_v2_parse_and_resolve_equationr   r   r	   rf   collections
namedtupler   _get_opt_einsum_contract_pathmap)rK   rU   ri   r   r  r   operandresolved_equationresolved_input_shapesellipsis_labelr  r   shaped_inputsindices_and_equationsoperand_indicesbinary_equationoperandss                    r    rh   rh     s   	FD	!$ZZ
H-(

061B0C D3 	45 5 ~~dHx&89 (T&\FL 1	GMM<#;#;	<w}}GMM113$OD/0	1 	.hE =,n 6{a	-55neL""6+<=)( (4 ##Hwi8F+@A%e	ACM
 :=(4,A F(	)11.%Hc&**o67hmmN))(ODEF !9Q( (8 	B9( (s&   CH H$H 
<A:H HHc                     t        j                  | g||ddd\  }}t        |D cg c]  }|d   |d   f c}      }|S c c}w )z:Returns the (memoized) result of opt_einsum.contract_path.T)r  einsum_calluse_blasr   rm   )
opt_einsumcontract_pathr   )rK   shaped_inputs_tupler  r   contractionsexprr  s          r    r  r    sd    
 ,, /!\   M$q'47!3 MN	 !Ns   A   )maxsizec                     | j                  dd      }d}d| v r*d}||v rt        d| d|  d      |j                  d|      }d	}|r||z  }t        j                  d
j	                  |      |      }|st        dj	                  |            |j                  d      j                  d      }|j                  d      r|j                  d      dd nd}t        |      t        |      k7  r.t        dj	                  t        |      | t        |                  d|vrjt        j                  |j                  d            }dj                  t        t        |            D 	cg c]  }	|	dk7  r
||	   dk(  r|	 c}	      }|d|z   z  }|r:t        t        |            t        |      k7  rt        dj	                  |             t        |j                  d            }
|D ]&  }||k7  s	||
vst        dj	                  |             |r2|r0|j                  |      }|dkD  rt        dj	                  |             t        |      dk  r|d|fS t        j                  d       }t!        t#        ||            D ]H  \  }\  }}||r|j%                  |      nd}|dk7  r||j'                  |      k7  rt        d|j                  |d       d      t        |      t        |      dz   kD  rt        dj	                  || |            |t        |      z   dz   t        |      z
  }t)        j*                  t        t-        d|||             t(        j.                        g||| n3t        |      t        |      k7  rt        dj	                  || |            t#        ||      D ]  \  }}|	t1        ||   |      ||<    K g }|D ]$  }|j3                  |D cg c]  }||   	 c}       & |||fS c c}	w c c}w )zAHelper which validates einsum equation and resolves input shapes.r   rl   Nr   0zInvalid character "z" in equation: rn   za-zA-Zz^([{0},]*)(->[{0}]*)?$z$Subscripts have incorrect format: {}rN   rM   rm   z-Got {} inputs for equation "{}", expecting {}rL   z>Output subscripts contain a label appearing more than once: {}zKOutput subscripts contain the label {} not present in the input subscripts.z/Output subscripts contain multiple ellipsis: {}c                       y)NrN   rq   rq   r]   r    r   z7_einsum_v2_parse_and_resolve_equation.<locals>.<lambda>  s    r]   r   z!Too many ellipses in input label zQToo many named labels in {}th subscript string of equation {} for input shape {} )dtypezhNumber of named labels in input #{} of equation {} must be equal to the number of dimensions in shape {})r   r   r   r   rV   r   rS   r   r  Counterr{   r|   r}   r   r   defaultdictr   r   r   rfindnpprodfilterint64maxr   )rK   r   r  r  allowed_labelsr   r   output_labelslabel_countsr   input_label_setlabelnum_output_ellipseslabel_to_dimr   labelsr   ellipsis_startellipsis_endr   resolved_shapess                        r    r
  r
    se   &&sB/.
h N**/xj
JL L)11%H
 .n$N
((+22>B$&%	
.556GHJ JQ%%c*,(-A%++a.$D-#l++
DKKL8S%68 9 9
 
""&&u{{1~6LGG$|,-8Q1, 	
 M --s3}-.#m2DD
HOO	  A'/ Ae5#? 228&-A AA '--n=Q
;
B
B8
LN N 	!dN22 ((3,%c,&EF <a&%}4BV[[0N	6<<7	7<"NN>5AB!E F 	F	Vs5zA~	% <<BF%=12 	2 $c%j014s6{Bl
''6$n\ BCDHH-eN<( 
VE
	"DDJF8UE$% 	% %( <
U	!,u"5s;U<3<: / FfVDEL/DEF	O^	;;yv Es   "O6O;
r_   )B__doc__r  	functoolsr   r   numpyr)  r  tensorflow.compiler.tf2xla.opsr   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr   r   r	   r
   r   tensorflow.python.platformr   r   tensorflow.python.utilr   r    tensorflow.python.util.tf_exportr   add_dispatch_supportdeprecated_endpointsr   register_unary_elementwise_apir"   r&   r)   r+   r-   r/   r2   r5   r7   r9   r;   r=   r?   rA   rD   rF   rH   RegisterGradientr\   re   rf   r   r   r   r   r   r   r   r   rh   r  	lru_cacher
  rq   r]   r    <module>rG     s  
   	    7 + < 4 + 2 0 6 * < . + 6 <\734	!!!'*2 +  52j  	((	)  ) !)8  !	((	*  ) "*6 %&	((	/  ) '/8 %&	((	/  ) '/6  !	((	*  ) "*6 56	((	-  ) 7-4 78	((	.  ) 9.0 56	((	-  ) 7-4 78	((	.  ) 9.0 #$	((	-  ) %-4 $%	((	.  ) &.0 #$	((	-  ) %-4 $%	((	.  ) &.0 #$	((	-  ) %-0 #$	((	-  ) %-0 #$	((	-  ) %-0 #$	((	-  ) %-0 k" #, 8_%	O1  &O1dA/HU/p}*@
0	G=T1h$ !A 3	 3 3C @!!# `<r]   