o
    ?eDM                    @   s  d 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 ddlmZ ddlmZ ddlmZ eejejejejej ej!ej"ej#ej$ej%ej&ej'ej(ej)ej*ej+ej,ej-ej.gZ/g dZ0dd Z1dd Z2dd Z3dd Z4dd Z5dd  Z6d!d" Z7d#d$ Z8d%d& Z9ed'd'd(gd)ej:e;d(d*d( Z<ed+g d)ej:dd,d-Z=ed+d.gd)ej:e;d.e4d/d0dd1d.Z>ed2g d)ej:dd3d4Z?ed2d5gd)ej:e;d5e4d6d7dd8d5Z@ed9g d)ej:dd:d;ZAed9d<gd)ej:e;d<e4d=d>dd?d<ZBed@g d)ej:ddAdBZCed@dCgd)ej:e;dCe4dDdEddFdCZDedGdHg d)ejEej:e6dIdHdJddKdLZFedGdHgd)ejEej:e5dIdMddNdHZGedOg d)ejEej:e6dPdQdRddSdTZHedOdQgd)ejEej:e;dQe5dPdU	ddVdQZIedWg d)ejEej:		ddXdYZJedWdZgd)ejEej:e;dZ		dd[dZZKed\d]g d)ejEej:e6d^d]dJdd_d`ZLed\d]gd)ejEej:e5d^daddbd]ZMedcg d)ejEej:e6dddedJddfdgZNedcdegd)ejEej:e;dee5dddhddideZOedjdkg d)ejEej:e6dldkdmddndoZPedjdkgd)ejEej:e5dldpddqdkZQedrg d)ejEej:e6dsdtdmddudvZRedrdtgd)ejEej:e;dte5dsdw		ddxdtZSdydz ZTed{d|g d)ej:dd}d~ZUed{d|gd)ej:ddd|ZVedg d)ej:dddZWeddgd)ej:e;d	dddZXdd ZYdd ZZdd Z[edg d)ej:dddZ\eddgd)ej:e;d	dddZ]edg d)ej:dddZ^eddgd)ej:e;ddddZ_edg d)ej:dddZ`eddgd)ej:e;ddddZadd Zbdd Zcdd Zddd Zeefdg dZgedg d)ej:		dddZhedgd)ej:dddZidd Zjedddgd)e;ddd Zkedg dd)ej:e;dddddZledg dd)ej:e;dddddZmdddZnedddgd)ej:e;ddddZoedg d)ej:dddZpeddgd)ej:e;ddddZqddÄ Zredăej:dddĄZse	tdơddȄ ZudS )zAsserts and Boolean Checks.    N)context)dtypes)errors)ops)sparse_tensortensor)tensor_shape)tensor_util)	array_ops)cond)control_flow_assert)control_flow_ops)math_ops)compat)deprecation)dispatch)	tf_export)assert_negativeassert_positiveassert_proper_iterableassert_non_negativeassert_non_positiveassert_equalassert_none_equalassert_nearassert_integerassert_lessassert_less_equalassert_greaterassert_greater_equalassert_rankassert_rank_at_leastassert_rank_inassert_same_float_dtypeassert_scalarassert_typeassert_shapesis_non_decreasingis_numeric_tensoris_strictly_increasingc                 C   s2   t | tjs
t| S t| }|d urt|S | S N)
isinstance
tensor_libTensorstrr
   constant_value)tZconst_t r2   `/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/check_ops.py_maybe_constant_value_stringJ   s   
r4   c                 C   s,   | sdd |D }t jddd|ddS )zCRaises a InvalidArgumentError with as much information as possible.c                 S      g | ]}t |qS r2   )r4   .0xr2   r2   r3   
<listcomp>V       z"_assert_static.<locals>.<listcomp>N
Znode_defopmessage)r   InvalidArgumentErrorjoin)	conditiondataZdata_staticr2   r2   r3   _assert_staticS   s   rC   c                 C   s   d| j | jjf S )z5Returns a string containing tensor's shape and dtype.zshape=%s dtype=%s)shapedtypenamer   r2   r2   r3   _shape_and_dtype_str[   s   rG   c                        fdd}|S )ab  Common docstring for assert_* ops that evaluate a unary predicate over every element of a tensor.

  Args:
    sym: Mathematical symbol for the check performed on each element, i.e. "> 0"
    sym_name: English-language name for the op described by sym

  Returns:
    Decorator that adds the appropriate docstring to the function for symbol
    `sym`.
  c                    s$   | j } }dj ||d| _| S )zGenerated decorator that adds the appropriate docstring to the function for symbol `sym`.

    Args:
      func: Function for a TensorFlow op

    Returns:
      Version of `func` with documentation attached.
    a  
    Assert the condition `x {sym}` holds element-wise.

    When running in graph mode, you should add a dependency on this operation
    to ensure that it runs. Example of adding a dependency to an operation:

    ```python
    with tf.control_dependencies([tf.debugging.{opname}(x, y)]):
      output = tf.reduce_sum(x)
    ```

    {sym_name} means, for every element `x[i]` of `x`, we have `x[i] {sym}`.
    If `x` is empty this is trivially satisfied.

    Args:
      x:  Numeric `Tensor`.
      data:  The tensors to print out if the condition is False.  Defaults to
        error message and first few entries of `x`.
      summarize: Print this many entries of each tensor.
      message: A string to prefix to the default message.
      name: A name for this operation (optional).  Defaults to "{opname}".

    Returns:
      Op that raises `InvalidArgumentError` if `x {sym}` is False.
      @compatibility(eager)
        returns None
      @end_compatibility

    Raises:
      InvalidArgumentError: if the check can be performed immediately and
        `x {sym}` is False. The check can be performed immediately during
        eager execution or if `x` is statically known.
    )symsym_nameopname)__name__
capitalizeformat__doc__)funcrK   Zcap_sym_namerI   rJ   r2   r3   
_decoratorl   s   	 "z%_unary_assert_doc.<locals>._decoratorr2   )rI   rJ   rR   r2   rQ   r3   _unary_assert_doc`   s   0rS   c                    rH   )af  Common docstring for most of the v1 assert_* ops that compare two tensors element-wise.

  Args:
    sym: Binary operation symbol, i.e. "=="
    test_var: a string that represents the variable in the right-hand side of
      binary operator of the test case

  Returns:
    Decorator that adds the appropriate docstring to the function for
  symbol `sym`.
  c                    s   | j }dj |d| _| S )zGenerated decorator that adds the appropriate docstring to the function for symbol `sym`.

    Args:
      func: Function for a TensorFlow op

    Returns:
      A version of `func` with documentation attached.
    a  
    Assert the condition `x {sym} y` holds element-wise.

    This condition holds if for every pair of (possibly broadcast) elements
    `x[i]`, `y[i]`, we have `x[i] {sym} y[i]`.
    If both `x` and `y` are empty, this is trivially satisfied.

    When running in graph mode, you should add a dependency on this operation
    to ensure that it runs. Example of adding a dependency to an operation:

    ```python
    with tf.control_dependencies([tf.compat.v1.{opname}(x, y)]):
      output = tf.reduce_sum(x)
    ```

    Args:
      x:  Numeric `Tensor`.
      y:  Numeric `Tensor`, same dtype as and broadcastable to `x`.
      data:  The tensors to print out if the condition is False.  Defaults to
        error message and first few entries of `x`, `y`.
      summarize: Print this many entries of each tensor.
      message: A string to prefix to the default message.
      name: A name for this operation (optional).  Defaults to "{opname}".

    Returns:
      Op that raises `InvalidArgumentError` if `x {sym} y` is False.

    Raises:
      InvalidArgumentError: if the check can be performed immediately and
        `x {sym} y` is False. The check can be performed immediately during
        eager execution or if `x` and `y` are statically known.

    @compatibility(TF2)
    `tf.compat.v1.{opname}` is compatible with eager execution and
    `tf.function`.
    Please use `tf.debugging.{opname}` instead when migrating to TF2. Apart
    from `data`, all arguments are supported with the same argument name.

    If you want to ensure the assert statements run before the
    potentially-invalid computation, please use `tf.control_dependencies`,
    as tf.function auto-control dependencies are insufficient for assert
    statements.

    #### Structural Mapping to Native TF2

    Before:

    ```python
    tf.compat.v1.{opname}(
      x=x, y=y, data=data, summarize=summarize,
      message=message, name=name)
    ```

    After:

    ```python
    tf.debugging.{opname}(
      x=x, y=y, message=message,
      summarize=summarize, name=name)
    ```

    #### TF1 & TF2 Usage Example

    TF1:

    >>> g = tf.Graph()
    >>> with g.as_default():
    ...   a = tf.compat.v1.placeholder(tf.float32, [2])
    ...   b = tf.compat.v1.placeholder(tf.float32, [2])
    ...   result = tf.compat.v1.{opname}(a, b,
    ...     message='"a {sym} b" does not hold for the given inputs')
    ...   with tf.compat.v1.control_dependencies([result]):
    ...     sum_node = a + b
    >>> sess = tf.compat.v1.Session(graph=g)
    >>> val = sess.run(sum_node, feed_dict={{a: [1, 2], b:{test_var}}})


    TF2:

    >>> a = tf.Variable([1, 2], dtype=tf.float32)
    >>> b = tf.Variable({test_var}, dtype=tf.float32)
    >>> assert_op = tf.debugging.{opname}(a, b, message=
    ...   '"a {sym} b" does not hold for the given inputs')
    >>> # When working with tf.control_dependencies
    >>> with tf.control_dependencies([assert_op]):
    ...   val = a + b

    @end_compatibility
    rI   rK   test_var)rL   rN   rO   )rP   rK   rI   rU   r2   r3   rR      s   	XZz&_binary_assert_doc.<locals>._decoratorr2   )rI   rU   rR   r2   rV   r3   _binary_assert_doc   s   grW   c                    s    fdd}|S )aO  Common docstring for v2 assert_* ops that compare two tensors element-wise.

  Args:
    sym: Binary operation symbol, i.e. "=="
    opname: Name for the symbol, i.e. "assert_equal"
    test_var: A number used in the docstring example

  Returns:
    Decorator that adds the appropriate docstring to the function for
  symbol `sym`.
  c                    s   dj  d| _| S )zDecorator that adds docstring to the function for symbol `sym`.

    Args:
      func: Function for a TensorFlow op

    Returns:
      A version of `func` with documentation attached.
    a  
    Assert the condition `x {sym} y` holds element-wise.

    This Op checks that `x[i] {sym} y[i]` holds for every pair of (possibly
    broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is
    trivially satisfied.

    If `x` {sym} `y` does not hold, `message`, as well as the first `summarize`
    entries of `x` and `y` are printed, and `InvalidArgumentError` is raised.

    When using inside `tf.function`, this API takes effects during execution.
    It's recommended to use this API with `tf.control_dependencies` to
    ensure the correct execution order.

    In the following example, without `tf.control_dependencies`, errors may
    not be raised at all.
    Check `tf.control_dependencies` for more details.

    >>> def check_size(x):
    ...   with tf.control_dependencies([
    ...       tf.debugging.{opname}(tf.size(x), {test_var},
    ...                       message='Bad tensor size')]):
    ...     return x

    >>> check_size(tf.ones([2, 3], tf.float32))
    Traceback (most recent call last):
       ...
    InvalidArgumentError: ...

    Args:
      x:  Numeric `Tensor`.
      y:  Numeric `Tensor`, same dtype as and broadcastable to `x`.
      message: A string to prefix to the default message. (optional)
      summarize: Print this many entries of each tensor. (optional)
      name: A name for this operation (optional).  Defaults to "{opname}".

    Returns:
      Op that raises `InvalidArgumentError` if `x {sym} y` is False. This can
        be used with `tf.control_dependencies` inside of `tf.function`s to
        block followup computation until the check has executed.
      @compatibility(eager)
      returns None
      @end_compatibility

    Raises:
      InvalidArgumentError: if the check can be performed immediately and
        `x == y` is False. The check can be performed immediately during eager
        execution or if `x` and `y` are statically known.
    rT   )rN   rO   )rP   rK   rI   rU   r2   r3   rR   #  s
   
02z)_binary_assert_doc_v2.<locals>._decoratorr2   )rI   rK   rU   rR   r2   rX   r3   _binary_assert_doc_v2  s   >rY   c                 C   sX  g }| d|   |dkr|j|jkrp|j rpt|}t|}| }t||}	t||}
t	||jd }| d|  | |d|  | d | |	 
dd|  | d | |
 
dd|  | 
d}| 
d}t	|j|}t	|j|}| d|  | |d|  | d	|  | |d|  |S )
a  Subroutine of _binary_assert that generates the components of the default error message when running in eager mode.

  Args:
    sym: Mathematical symbol for the test to apply to pairs of tensor elements,
      i.e. "=="
    x: First input to the assertion after applying `convert_to_tensor()`
    y: Second input to the assertion
    summarize: Value of the "summarize" parameter to the original assert_* call;
      tells how many elements of each tensor to print.
    test_op: TensorFlow op that returns a Boolean tensor with True in each
      position where the assertion is satisfied.

  Returns:
    List of tensors and scalars that, when stringified and concatenated,
    will produce the error message string.
  zCondition x %s y did not hold.r   z%Indices of first %d different values:NzCorresponding x values:zCorresponding y values:zFirst %d elements of x:zFirst %d elements of y:)appendrD   as_listr   Zlogical_notr   wherenumpyZboolean_maskminreshapesize)rI   r8   y	summarizetest_oprB   maskindicesZ
indices_npZx_valsZy_valsZnum_valsZx_npZy_npZx_sumZy_sumr2   r2   r3   _make_assert_msg_datad  s2   



rh   c                 C   sn   t | tjr3|  }t|rt|S |d}dd |d| D }t||j	k r/|
d t|S t| S )aT  Format a data item for use in an error message in eager mode.

  Args:
    data_item: One of the items in the "data" argument to an assert_* function.
      Can be a Tensor or a scalar value.
    summarize: How many elements to retain of each tensor-valued entry in data.

  Returns:
    An appropriate string representation of data_item
  rZ   c                 S   r5   r2   )r/   r6   r2   r2   r3   r9     r:   z!_pretty_print.<locals>.<listcomp>Nz...)r,   r-   r.   r_   npZisscalarr/   ra   lenrb   r\   )Z	data_itemrd   ZarrZflatlstr2   r2   r3   _pretty_print  s   


rl   c
              	      s  t |	||||g t j|dd}t j|dd}t rh|||}
t|
}|r2	 W d   dS  du r9d n dk r?d |du rKt| || |
}|durV|gt| }t	j
ddd fd	d
|D d|du r{d|  d|j |d|j |g}|dur|gt| }t|||}t|}t|}|dur|durt|||}t|| tj|| dW  d   S 1 sw   Y  dS )a  Generic binary elementwise assertion.

  Implements the behavior described in _binary_assert_doc() above.
  Args:
    sym: Mathematical symbol for the test to apply to pairs of tensor elements,
      i.e. "=="
    opname: Name of the assert op in the public API, i.e. "assert_equal"
    op_func: Function that, if passed the two Tensor inputs to the assertion (x
      and y), will return the test to be passed to reduce_all() i.e.
    static_func: Function that, if passed numpy ndarray versions of the two
      inputs to the assertion, will return a Boolean ndarray with containing
      True in all positions where the assertion PASSES.
      i.e. np.equal for assert_equal()
    x:  Numeric `Tensor`.
    y:  Numeric `Tensor`, same dtype as and broadcastable to `x`.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`, `y`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to the value of
      `opname`.

  Returns:
    See docstring template in _binary_assert_doc().
  r8   rF   rc   N   r   g    eAr;   c                 3   s    | ]}t | V  qd S r+   )rl   )r7   drd   r2   r3   	<genexpr>  s    z!_binary_assert.<locals>.<genexpr>r<   z+Condition x %s y did not hold element-wise:	x (%s) = 	y (%s) = rp   )r   
name_scopeconvert_to_tensorr   executing_eagerlyr   
reduce_allrh   listr   r?   r@   rF   r
   r0   ri   allrC   r   Assert)rI   rK   Zop_funcZstatic_funcr8   rc   rB   rd   r>   rF   re   rA   Zx_staticZy_staticZcondition_staticr2   rp   r3   _binary_assert  sJ   






$r{   z debugging.assert_proper_iterabler   )v1c                 C   sN   t jtjtjftj }t| |rt	dt
|  t| ds%t	dt
|  dS )a  Static assert that values is a "proper" iterable.

  `Ops` that expect iterables of `Tensor` can call this to validate input.
  Useful since `Tensor`, `ndarray`, byte/text type are all iterables themselves.

  Args:
    values:  Object to be checked.

  Raises:
    TypeError:  If `values` is not iterable or is one of
      `Tensor`, `SparseTensor`, `np.array`, `tf.compat.bytes_or_text_types`.
  z@Expected argument "values" to be a "proper" iterable.  Found: %s__iter__z5Expected argument "values" to be iterable.  Found: %sN)r-   r.   r   SparseTensorri   Zndarrayr   Zbytes_or_text_typesr,   	TypeErrortypehasattr)valuesZunintentional_iterablesr2   r2   r3   r     s   


zdebugging.assert_negativec                 C      t | |||dS )a  Assert the condition `x < 0` holds element-wise.

  This Op checks that `x[i] < 0` holds for every element of `x`. If `x` is
  empty, this is trivially satisfied.

  If `x` is not negative everywhere, `message`, as well as the first `summarize`
  entries of `x` are printed, and `InvalidArgumentError` is raised.

  Args:
    x:  Numeric `Tensor`.
    message: A string to prefix to the default message.
    summarize: Print this many entries of each tensor.
    name: A name for this operation (optional).  Defaults to "assert_negative".

  Returns:
    Op raising `InvalidArgumentError` unless `x` is all negative. This can be
      used with `tf.control_dependencies` inside of `tf.function`s to block
      followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: if the check can be performed immediately and
      `x[i] < 0` is False. The check can be performed immediately during eager
      execution or if `x` is statically known.
  r8   r>   rd   rF   )r   r   r2   r2   r3   assert_negative_v2     r   r   z< 0negativec                 C   s   t |}t|d| |g7 tj| dd} |d u r-t r"t| }n| j}|dd| | g}tjd| jd}t	| |||dW  d    S 1 sGw   Y  d S )	Nr   r8   rm   z*Condition x < 0 did not hold element-wise:rr   r   rE   rB   rd   
_message_prefixr   rt   ru   r   rv   rG   rF   rE   r   r8   rB   rd   r>   rF   zeror2   r2   r3   r   @     
$zdebugging.assert_positivec                 C      t | |||dS )a  Assert the condition `x > 0` holds element-wise.

  This Op checks that `x[i] > 0` holds for every element of `x`. If `x` is
  empty, this is trivially satisfied.

  If `x` is not positive everywhere, `message`, as well as the first `summarize`
  entries of `x` are printed, and `InvalidArgumentError` is raised.

  Args:
    x:  Numeric `Tensor`.
    message: A string to prefix to the default message.
    summarize: Print this many entries of each tensor.
    name: A name for this operation (optional). Defaults to "assert_positive".

  Returns:
    Op raising `InvalidArgumentError` unless `x` is all positive. This can be
      used with `tf.control_dependencies` inside of `tf.function`s to block
      followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: if the check can be performed immediately and
      `x[i] > 0` is False. The check can be performed immediately during eager
      execution or if `x` is statically known.
  r8   rd   r>   rF   )r   r   r2   r2   r3   assert_positive_v2U  r   r   r   z> 0Zpositivec                 C      t |}t|d| |g7 tj| dd} |d u r-t r"t| }n| j}|dd| | g}tjd| jd}t	|| ||dW  d    S 1 sGw   Y  d S )	Nr   r8   rm   z*Condition x > 0 did not hold element-wise:rr   r   r   r   r   r   r2   r2   r3   r   v  s   
$zdebugging.assert_non_negativec                 C   r   )a  Assert the condition `x >= 0` holds element-wise.

  This Op checks that `x[i] >= 0` holds for every element of `x`. If `x` is
  empty, this is trivially satisfied.

  If `x` is not >= 0 everywhere, `message`, as well as the first `summarize`
  entries of `x` are printed, and `InvalidArgumentError` is raised.

  Args:
    x:  Numeric `Tensor`.
    message: A string to prefix to the default message.
    summarize: Print this many entries of each tensor.
    name: A name for this operation (optional).  Defaults to
      "assert_non_negative".

  Returns:
    Op raising `InvalidArgumentError` unless `x` is all non-negative. This can
      be used with `tf.control_dependencies` inside of `tf.function`s to block
      followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: if the check can be performed immediately and
      `x[i] >= 0` is False. The check can be performed immediately during eager
      execution or if `x` is statically known.
  r   )r   r   r2   r2   r3   assert_non_negative_v2     r   r   z>= 0znon-negativec                 C   r   )	Nr   r8   rm   z+Condition x >= 0 did not hold element-wise:rr   r   r   r   
r   r   rt   ru   r   rv   rG   rF   rE   r   r   r2   r2   r3   r     r   zdebugging.assert_non_positivec                 C   r   )a  Assert the condition `x <= 0` holds element-wise.

  This Op checks that `x[i] <= 0` holds for every element of `x`. If `x` is
  empty, this is trivially satisfied.

  If `x` is not <= 0 everywhere, `message`, as well as the first `summarize`
  entries of `x` are printed, and `InvalidArgumentError` is raised.

  Args:
    x:  Numeric `Tensor`.
    message: A string to prefix to the default message.
    summarize: Print this many entries of each tensor.
    name: A name for this operation (optional).  Defaults to
      "assert_non_positive".

  Returns:
    Op raising `InvalidArgumentError` unless `x` is all non-positive. This can
      be used with `tf.control_dependencies` inside of `tf.function`s to block
      followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: if the check can be performed immediately and
      `x[i] <= 0` is False. The check can be performed immediately during eager
      execution or if `x` is statically known.
  r   )r   r   r2   r2   r3   assert_non_positive_v2  r   r   r   z<= 0znon-positivec                 C   s   t |}t|d| |g6 tj| dd} |d u r,t r"t| }n| j}|d| | g}tjd| jd}t	| |||dW  d    S 1 sFw   Y  d S )Nr   r8   rm   z4Condition x <= 0 did not hold element-wise:x (%s) = r   r   r   r   r   r2   r2   r3   r     s    
$zdebugging.assert_equalr   ==rn   c                 C      t | ||||dS Nr8   rc   rd   r>   rF   )r   r8   rc   r>   rd   rF   r2   r2   r3   assert_equal_v2     r   z[1, 2]c                 C   s|   t |d| ||g | |u r t rd nt W  d    S W d    n1 s*w   Y  tddtjt	j| |||||
S )Nr   r   )
r   rt   r   rv   r   no_opr{   r   equalri   r8   rc   rB   rd   r>   rF   r2   r2   r3   r     s   zdebugging.assert_none_equal!=r      c                 C   s   t | ||||dS r   )r   r   r2   r2   r3   assert_none_equal_v2     
r   z[2, 1]c                 C      t ddtjtj| |||||
S )Nr   r   )r{   r   	not_equalri   r   r2   r2   r3   r        
zdebugging.assert_nearc              	   C   s   t | ||||||dS )a  Assert the condition `x` and `y` are close element-wise.

  This Op checks that `x[i] - y[i] < atol + rtol * tf.abs(y[i])` holds for every
  pair of (possibly broadcast) elements of `x` and `y`. If both `x` and `y` are
  empty, this is trivially satisfied.

  If any elements of `x` and `y` are not close, `message`, as well as the first
  `summarize` entries of `x` and `y` are printed, and `InvalidArgumentError`
  is raised.

  The default `atol` and `rtol` is `10 * eps`, where `eps` is the smallest
  representable positive number such that `1 + eps != 1`.  This is about
  `1.2e-6` in `32bit`, `2.22e-15` in `64bit`, and `0.00977` in `16bit`.
  See `numpy.finfo`.

  Args:
    x: Float or complex `Tensor`.
    y: Float or complex `Tensor`, same dtype as and broadcastable to `x`.
    rtol:  `Tensor`.  Same `dtype` as, and broadcastable to, `x`.
      The relative tolerance.  Default is `10 * eps`.
    atol:  `Tensor`.  Same `dtype` as, and broadcastable to, `x`.
      The absolute tolerance.  Default is `10 * eps`.
    message: A string to prefix to the default message.
    summarize: Print this many entries of each tensor.
    name: A name for this operation (optional).  Defaults to "assert_near".

  Returns:
    Op that raises `InvalidArgumentError` if `x` and `y` are not close enough.
      This can be used with `tf.control_dependencies` inside of `tf.function`s
      to block followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: if the check can be performed immediately and
      `x != y` is False for any pair of elements in `x` and `y`. The check can
      be performed immediately during eager execution or if `x` and `y` are
      statically known.

  @compatibility(numpy)
  Similar to `numpy.testing.assert_allclose`, except tolerance depends on data
  type. This is due to the fact that `TensorFlow` is often used with `32bit`,
  `64bit`, and even `16bit` data.
  @end_compatibility
  )r8   rc   rtolatolrd   r>   rF   )r   )r8   rc   r   r   r>   rd   rF   r2   r2   r3   assert_near_v2#  s   3r   r   c              	   C   s\  t |}t|d| ||||g tj| dd} tj|d| jd}| j}|jr*|j}t|j	j
}	|du r9d|	 n|}|du rCd|	 n|}tj|d|d}tj|d	|d}t rbt| }
t|}n| j}
|j}|du r||d
||f d|
 | d| |g}||t|  }t| | }tt||}tj|||dW  d   S 1 sw   Y  dS )a  Assert the condition `x` and `y` are close element-wise.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.compat.v1.assert_near(x, y)]):
    output = tf.reduce_sum(x)
  ```

  This condition holds if for every pair of (possibly broadcast) elements
  `x[i]`, `y[i]`, we have

  ```tf.abs(x[i] - y[i]) <= atol + rtol * tf.abs(y[i])```.

  If both `x` and `y` are empty, this is trivially satisfied.

  The default `atol` and `rtol` is `10 * eps`, where `eps` is the smallest
  representable positive number such that `1 + eps != 1`.  This is about
  `1.2e-6` in `32bit`, `2.22e-15` in `64bit`, and `0.00977` in `16bit`.
  See `numpy.finfo`.

  Args:
    x:  Float or complex `Tensor`.
    y:  Float or complex `Tensor`, same `dtype` as, and broadcastable to, `x`.
    rtol:  `Tensor`.  Same `dtype` as, and broadcastable to, `x`.
      The relative tolerance.  Default is `10 * eps`.
    atol:  `Tensor`.  Same `dtype` as, and broadcastable to, `x`.
      The absolute tolerance.  Default is `10 * eps`.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`, `y`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_near".

  Returns:
    Op that raises `InvalidArgumentError` if `x` and `y` are not close enough.

  @compatibility(numpy)
  Similar to `numpy.testing.assert_allclose`, except tolerance depends on data
  type. This is due to the fact that `TensorFlow` is often used with `32bit`,
  `64bit`, and even `16bit` data.
  @end_compatibility
  r   r8   rm   rc   )rF   rE   N
   r   r   z3x and y not equal to tolerance rtol = %s, atol = %srr   rs   rp   )r   r   rt   ru   rE   Z
is_complexZ
real_dtyperi   ZfinfoZas_numpy_dtypeepsr   rv   rG   rF   r   absrw   lessr   rz   )r8   rc   r   r   rB   rd   r>   rF   rE   r   Zx_nameZy_nameZtoldiffrA   r2   r2   r3   r   Z  s6   2

$zdebugging.assert_lessr   <c                 C   r   r   )r   r   r2   r2   r3   assert_less_v2  r   r   z[2, 3]c                 C   r   )Nr   r   )r{   r   r   ri   r   r2   r2   r3   r     s   zdebugging.assert_less_equal<=r   c                 C   r   r   )r   r   r2   r2   r3   assert_less_equal_v2  s   r   z[1, 3]c                 C   r   )Nr   r   )r{   r   
less_equalri   r   r2   r2   r3   r     s   
zdebugging.assert_greaterr   >	   c                 C   r   r   )r   r   r2   r2   r3   assert_greater_v2  r   r   z[0, 1]c                 C   r   )Nr   r   )r{   r   Zgreaterri   r   r2   r2   r3   r     s   
zdebugging.assert_greater_equal>=r    c                 C   r   r   )r    r   r2   r2   r3   assert_greater_equal_v2  r   r   z[1, 0]c                 C   r   )Nr   r    )r{   r   greater_equalri   r   r2   r2   r3   r      r   c                 C   s   t |tj t|}|dur2|jdkrtd|  j}|dur2|||s,td||t	j
ddS |t| |}|du rPd|g}	t|d|	d}
t	|
g|}tj|||d	S )
a  Assert `x` has a rank that satisfies a given condition.

  Args:
    x:  Numeric `Tensor`.
    rank:  Scalar `Tensor`.
    static_condition:   A python function that takes `[actual_rank, given_rank]`
      and returns `True` if the condition is satisfied, `False` otherwise.
    dynamic_condition:  An `op` that takes [actual_rank, given_rank] and return
      `True` if the condition is satisfied, `False` otherwise.
    data:  The tensors to print out if the condition is false.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.

  Returns:
    Op raising `InvalidArgumentError` if `x` fails dynamic_condition.

  Raises:
    ValueError:  If static checks determine `x` fails static_condition.
  Nr   Rank must be a scalar.Static rank condition failedstatic_checks_determined_all_okrm   &Rank must be a scalar. Received rank: rB   rp   )r&   r   int32r
   r0   ndim
ValueError	get_shapendimsr   r   r   rankr!   with_dependenciesr   rz   )r8   r   static_conditiondynamic_conditionrB   rd   rank_staticx_rank_staticrA   	this_data
rank_checkr2   r2   r3   _assert_rank_condition  s$   



r   zdebugging.assert_rankr!   c                 C   r   )a  Assert that `x` has rank equal to `rank`.

  This Op checks that the rank of `x` is equal to `rank`.

  If `x` has a different rank, `message`, as well as the shape of `x` are
  printed, and `InvalidArgumentError` is raised.

  Args:
    x: `Tensor`.
    rank: Scalar integer `Tensor`.
    message: A string to prefix to the default message.
    name: A name for this operation (optional). Defaults to
      "assert_rank".

  Returns:
    Op raising `InvalidArgumentError` unless `x` has specified rank.
    If static checks determine `x` has correct rank, a `no_op` is returned.
    This can be used with `tf.control_dependencies` inside of `tf.function`s
    to block followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: if the check can be performed immediately and
      `x` does not have rank `rank`. The check can be performed immediately
      during eager execution or if the shape of `x` is statically known.
  r8   r   r>   rF   )r!   r   r2   r2   r3   assert_rank_v2(     r   c           
      C   s4  t |d| |ft|pg   t| tjst j| dd} t j|dd}t|}dd }tj	}t
 s9t| tjr<d}n| j}|du rO|d	| |d
t| g}zt| |||||}W n- ty }	 z!|	jd dkr|td|||	jd |	jd |  f t|	jd d}	~	ww W d   |S 1 sw   Y  |S )a-  Assert `x` has rank equal to `rank`.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.compat.v1.assert_rank(x, 2)]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x:  Numeric `Tensor`.
    rank:  Scalar integer `Tensor`.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and the shape of `x`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_rank".

  Returns:
    Op raising `InvalidArgumentError` unless `x` has specified rank.
    If static checks determine `x` has correct rank, a `no_op` is returned.

  Raises:
    ValueError:  If static checks determine `x` has wrong rank.
  r!   r8   rm   r   c                 S   s   | |kS r+   r2   actual_rank
given_rankr2   r2   r3   <lambda>l      zassert_rank.<locals>.<lambda> NzTensor %s must have rankReceived shape: r   r   z:%sTensor %s must have rank %d.  Received rank %d, shape %s      )r   rt   tupler,   r   r~   ru   r   r   r   r   rv   rF   r   rD   r   r   argsr   
r8   r   rB   rd   r>   rF   r   r   	assert_oper2   r2   r3   r!   J  sD    

!!zdebugging.assert_rank_at_leastc                 C   r   )a  Assert that `x` has rank of at least `rank`.

  This Op checks that the rank of `x` is greater or equal to `rank`.

  If `x` has a rank lower than `rank`, `message`, as well as the shape of `x`
  are printed, and `InvalidArgumentError` is raised.

  Args:
    x: `Tensor`.
    rank: Scalar integer `Tensor`.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to
      "assert_rank_at_least".

  Returns:
    Op raising `InvalidArgumentError` unless `x` has specified rank or higher.
    If static checks determine `x` has correct rank, a `no_op` is returned.
    This can be used with `tf.control_dependencies` inside of `tf.function`s
    to block followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: `x` does not have rank at least `rank`, but the rank
      cannot be statically determined.
    ValueError: If static checks determine `x` has mismatched rank.
  r   )r"   r   r2   r2   r3   assert_rank_at_least_v2  r   r   r"   c           
      C   s  t |d| |ft|pg  o t j| dd} t j|dd}t|}dd }tj}t r0d}n| j	}|du rC|d	| |d
t
| g}zt| |||||}W n' tyu }	 z|	jd dkrptd|||	jd |	jd |  f  d}	~	ww W d   |S 1 sw   Y  |S )aX  Assert `x` has rank equal to `rank` or higher.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.compat.v1.assert_rank_at_least(x, 2)]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x:  Numeric `Tensor`.
    rank:  Scalar `Tensor`.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).
      Defaults to "assert_rank_at_least".

  Returns:
    Op raising `InvalidArgumentError` unless `x` has specified rank or higher.
    If static checks determine `x` has correct rank, a `no_op` is returned.

  Raises:
    ValueError:  If static checks determine `x` has wrong rank.
  r"   r8   rm   r   c                 S   s   | |kS r+   r2   r   r2   r2   r3   r     r   z&assert_rank_at_least.<locals>.<lambda>r   Nz!Tensor %s must have rank at leastr   r   r   zC%sTensor %s must have rank at least %d.  Received rank %d, shape %sr   r   )r   rt   r   ru   r   r   r   r   rv   rF   r   rD   r   r   r   r   r   r2   r2   r3   r"     sF   

!!c                 C   s   | |v S r+   r2   )r   given_ranksr2   r2   r3   _static_rank_in     r   c                 C   sP   t |dk rtdS t|d | }|dd  D ]}t|t|| }q|S )Nr   Fr   )rj   r   ru   r   r   
logical_or)r   r   resultr   r2   r2   r3   _dynamic_rank_in  s   
r   c                 C   s   |D ]}t |tj qtdd |D }tdd |D sE|D ]}|jdkr*tdq|  j}	|	durE||	|s?td|	|t	j
d	d
S |t| |}
t||D ]\}}|du rld|g}t|d|d}t	|g|
}
qRtj|
||dS )a  Assert `x` has a rank that satisfies a given condition.

  Args:
    x:  Numeric `Tensor`.
    ranks:  Scalar `Tensor`.
    static_condition:   A python function that takes
      `[actual_rank, given_ranks]` and returns `True` if the condition is
      satisfied, `False` otherwise.
    dynamic_condition:  An `op` that takes [actual_rank, given_ranks]
      and return `True` if the condition is satisfied, `False` otherwise.
    data:  The tensors to print out if the condition is false.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.

  Returns:
    Op raising `InvalidArgumentError` if `x` fails dynamic_condition.

  Raises:
    ValueError:  If static checks determine `x` fails static_condition.
  c                 S   s   g | ]}t |qS r2   )r
   r0   r7   r   r2   r2   r3   r9     s    z+_assert_ranks_condition.<locals>.<listcomp>c                 s   s    | ]}|d u V  qd S r+   r2   )r7   rr2   r2   r3   rq     s    z*_assert_ranks_condition.<locals>.<genexpr>r   r   Nr   r   rm   r   r   rp   )r&   r   r   r   anyr   r   r   r   r   r   r   r   zipr!   r   r   rz   )r8   ranksr   r   rB   rd   r   Zranks_staticr   r   rA   r   r   r2   r2   r3   _assert_ranks_condition  s.   


r   zdebugging.assert_rank_inc                 C   r   )a  Assert that `x` has a rank in `ranks`.

  This Op checks that the rank of `x` is in `ranks`.

  If `x` has a different rank, `message`, as well as the shape of `x` are
  printed, and `InvalidArgumentError` is raised.

  Args:
    x: `Tensor`.
    ranks: `Iterable` of scalar `Tensor` objects.
    message: A string to prefix to the default message.
    name: A name for this operation (optional). Defaults to "assert_rank_in".

  Returns:
    Op raising `InvalidArgumentError` unless rank of `x` is in `ranks`.
    If static checks determine `x` has matching rank, a `no_op` is returned.
    This can be used with `tf.control_dependencies` inside of `tf.function`s
    to block followup computation until the check has executed.
    @compatibility(eager)
    returns None
    @end_compatibility

  Raises:
    InvalidArgumentError: `x` does not have rank in `ranks`, but the rank cannot
      be statically determined.
    ValueError: If static checks determine `x` has mismatched rank.
  r8   r   r>   rF   )r#   r   r2   r2   r3   assert_rank_in_v21  r   r   r#   c                 C   s.  t |d| ft| t|pg  { t| tjs t j| dd} tdd |D }t|}t	 s7t| tjr:d}n| j
}|du rR|d| gt| d	t| g }zt| |tt||}W n' ty } z|jd
 dkrtd|||jd |jd |  f  d}~ww W d   |S 1 sw   Y  |S )aV  Assert `x` has rank in `ranks`.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.compat.v1.assert_rank_in(x, (2, 4))]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x:  Numeric `Tensor`.
    ranks:  Iterable of scalar `Tensor` objects.
    data:  The tensors to print out if the condition is False.  Defaults to
      error message and first few entries of `x`.
    summarize: Print this many entries of each tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).
      Defaults to "assert_rank_in".

  Returns:
    Op raising `InvalidArgumentError` unless rank of `x` is in `ranks`.
    If static checks determine `x` has matching rank, a `no_op` is returned.

  Raises:
    ValueError:  If static checks determine `x` has mismatched rank.
  r#   r8   rm   c                 S   s   g | ]	}t j|d dqS )r   rm   )r   ru   r   r2   r2   r3   r9   u  s    z"assert_rank_in.<locals>.<listcomp>r   NzTensor %s must have rank inr   r   r   z=%sTensor %s must have rank in %s.  Received rank %d, shape %sr   r   )r   rt   r   r,   r   r~   ru   r   r   rv   rF   rx   r   rD   r   r   r   r   r   r   )r8   r   rB   rd   r>   rF   r   r   r2   r2   r3   r#   R  sJ   

zdebugging.assert_integerc                 C      t | ||d dS )a  Assert that `x` is of integer dtype.

  If `x` has a non-integer type, `message`, as well as the dtype of `x` are
  printed, and `InvalidArgumentError` is raised.

  This can always be checked statically, so this method returns nothing.

  Args:
    x: A `Tensor`.
    message: A string to prefix to the default message.
    name: A name for this operation (optional). Defaults to "assert_integer".

  Raises:
    TypeError:  If `x.dtype` is not a non-quantized integer type.
  r8   r>   rF   N)r   r   r2   r2   r3   assert_integer_v2  s   r   r   c                 C   s   t |d| g0 t j| dd} | jjs,t rd}n| j}dt||| jf }t	|t
dW  d   S 1 s;w   Y  dS )aD  Assert that `x` is of integer dtype.

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.compat.v1.assert_integer(x)]):
    output = tf.reduce_sum(x)
  ```

  Args:
    x: `Tensor` whose basetype is integer and is not quantized.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_integer".

  Raises:
    TypeError:  If `x.dtype` is anything other than non-quantized integer.

  Returns:
    A `no_op` that does nothing.  Type can be determined statically.
  r   r8   rm   r   z9%sExpected "x" to be integer type.  Found: %s of dtype %sZ!statically_determined_was_integerN)r   rt   ru   rE   
is_integerr   rv   rF   r   r   r   r   )r8   r>   rF   err_msgr2   r2   r3   r     s   $zdebugging.assert_typec                 C   s   t | |||d dS )ad  Asserts that the given `Tensor` is of the specified type.

  This can always be checked statically, so this method returns nothing.

  Example:

  >>> a = tf.Variable(1.0)
  >>> tf.debugging.assert_type(a, tf_type= tf.float32)

  >>> b = tf.constant(21)
  >>> tf.debugging.assert_type(b, tf_type=tf.bool)
  Traceback (most recent call last):
  ...
  TypeError: ...

  >>> c = tf.SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2],
  ...  dense_shape=[3, 4])
  >>> tf.debugging.assert_type(c, tf_type= tf.int32)

  Args:
    tensor: A `Tensor`, `SparseTensor` or `tf.Variable` .
    tf_type: A tensorflow type (`dtypes.float32`, `tf.int64`, `dtypes.bool`,
      etc).
    message: A string to prefix to the default message.
    name:  A name for this operation. Defaults to "assert_type"

  Raises:
    TypeError: If the tensor's data type doesn't match `tf_type`.
  r   Ztf_typer>   rF   N)r&   r   r2   r2   r3   assert_type_v2  s    r   r&   c                 C   s   t |}t|d| g4 t| tjstj| dd} | j|kr5t	t
| t| dd d|d| jtdW  d   S 1 sDw   Y  dS )	a  Statically asserts that the given `Tensor` is of the specified type.

  Args:
    tensor: A `Tensor` or `SparseTensor`.
    tf_type: A tensorflow type (`dtypes.float32`, `tf.int64`, `dtypes.bool`,
      etc).
    message: A string to prefix to the default message.
    name:  A name to give this `Op`.  Defaults to "assert_type"

  Raises:
    TypeError: If the tensors data type doesn't match `tf_type`.

  Returns:
    A `no_op` that does nothing.  Type can be determined statically.
  r&   r   rm   rF   z must be of type z; got Z"statically_determined_correct_typeN)r   Zas_dtyper   rt   r,   r   r~   ru   rE   r   r   getattrr   r   r   r2   r2   r3   r&     s   

$c                    s   t |  |  j}|du}|r|dkrdS |r/|dkr/|   } fddt|D }|S tt | d}t|dd  fddS )	a   Gets the dimension sizes of a tensor `x`.

  If a size can be determined statically it is returned as an integer,
  otherwise as a tensor.

  If `x` is a scalar it is treated as rank 1 size 1.

  Args:
    x: A `Tensor`.

  Returns:
    Dimension sizes.
  Nr   )r   c                    s(   g | ]\}}|d urt |n | qS r+   )int)r7   irb   Zdynamic_shaper2   r3   r9   &  s    z$_dimension_sizes.<locals>.<listcomp>c                   S   s   t dgS Nr   )r   Zconstantr2   r2   r2   r3   r   -  s    z"_dimension_sizes.<locals>.<lambda>c                      s    S r+   r2   r2   r   r2   r3   r   -  s    )	r   rD   r   r   r]   	enumerater   r   r   )r8   r   Zrank_is_knownZstatic_shapesizesZhas_rank_zeror2   r   r3   _dimension_sizes  s   


r   c                 C   s   | st dgS | S r   )r   )symbolic_shaper2   r2   r3   _symbolic_dimension_sizes0  s   
r   c              	   C   s<   | d u}zt |  d}W n ttfy   d}Y nw |o|S )NTF)r   r   r   )Zdimension_sizeZnot_noneZcan_be_parsed_as_intr2   r2   r3   _has_known_value8  s   r   c                 C   s   | dv S )N)N.r2   )symbolr2   r2   r3   _is_symbol_for_any_sizeB  r   r  _TensorDimSizes)r8   unspecified_dimactual_sizessymbolic_sizeszdebugging.assert_shapesc                 C   s   t | ||||d dS )a  Assert tensor shapes and dimension size relationships between tensors.

  This Op checks that a collection of tensors shape relationships
  satisfies given constraints.

  Example:

  >>> n = 10
  >>> q = 3
  >>> d = 7
  >>> x = tf.zeros([n,q])
  >>> y = tf.ones([n,d])
  >>> param = tf.Variable([1.0, 2.0, 3.0])
  >>> scalar = 1.0
  >>> tf.debugging.assert_shapes([
  ...  (x, ('N', 'Q')),
  ...  (y, ('N', 'D')),
  ...  (param, ('Q',)),
  ...  (scalar, ()),
  ... ])

  >>> tf.debugging.assert_shapes([
  ...   (x, ('N', 'D')),
  ...   (y, ('N', 'D'))
  ... ])
  Traceback (most recent call last):
  ...
  ValueError: ...

  If `x`, `y`, `param` or `scalar` does not have a shape that satisfies
  all specified constraints, `message`, as well as the first `summarize` entries
  of the first encountered violating tensor are printed, and
  `InvalidArgumentError` is raised.

  Size entries in the specified shapes are checked against other entries by
  their __hash__, except:
    - a size entry is interpreted as an explicit size if it can be parsed as an
      integer primitive.
    - a size entry is interpreted as *any* size if it is None or '.'.

  If the first entry of a shape is `...` (type `Ellipsis`) or '*' that indicates
  a variable number of outer dimensions of unspecified size, i.e. the constraint
  applies to the inner-most dimensions only.

  Scalar tensors and specified shapes of length zero (excluding the 'inner-most'
  prefix) are both treated as having a single dimension of size one.

  Args:
    shapes: dictionary with (`Tensor` to shape) items, or a list of
      (`Tensor`, shape) tuples. A shape must be an iterable.
    data: The tensors to print out if the condition is False.  Defaults to error
      message and first few entries of the violating tensor.
    summarize: Print this many entries of the tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_shapes".

  Raises:
    ValueError:  If static checks determine any shape constraint is violated.
  )rB   rd   r>   rF   N)r'   )shapesrB   rd   r>   rF   r2   r2   r3   assert_shapes_v2K  s   ?

r  c           "         s  t | tr	|  } t|}t|d| |g dd | D }t   fdd}g }|D ]X\}	}
t|
dp:t|
d}|sHt	d|||	|
f t
|
}d	}t|D ]\}}|td
fvr]qR|dkrlt	d|||	|f d}qR|t|	|t|	t|r|dd n| q-g }|D ]=}t|j}|dv }|jr|rqt|j|||||d}n|rt|jddg||||d}nt|j|||||d}|| qg }i }|D ]}t|jD ]\}}t|rq|jr|t|j }n|}||v st|rt|rt|}d}n|| \}}}d|||f }t| |j| }W d   n	1 s$w   Y  t|rPt|rPt|t|krOt	d||||j||||j f qtt |t |}|}|du rv||d||j |d|dt!"|jg}|t#j$|||d qt| |j| } W d   n	1 sw   Y  | |j|f||< qqW d   n	1 sw   Y  t| t%&|}!W d   |!S 1 sw   Y  |!S )a  Assert tensor shapes and dimension size relationships between tensors.

  This Op checks that a collection of tensors shape relationships
  satisfies given constraints.

  Example:

  >>> n = 10
  >>> q = 3
  >>> d = 7
  >>> x = tf.zeros([n,q])
  >>> y = tf.ones([n,d])
  >>> param = tf.Variable([1.0, 2.0, 3.0])
  >>> scalar = 1.0
  >>> tf.debugging.assert_shapes([
  ...  (x, ('N', 'Q')),
  ...  (y, ('N', 'D')),
  ...  (param, ('Q',)),
  ...  (scalar, ()),
  ... ])

  >>> tf.debugging.assert_shapes([
  ...   (x, ('N', 'D')),
  ...   (y, ('N', 'D'))
  ... ])
  Traceback (most recent call last):
  ...
  ValueError: ...

  Example of adding a dependency to an operation:

  ```python
  with tf.control_dependencies([tf.assert_shapes(shapes)]):
    output = tf.matmul(x, y, transpose_a=True)
  ```

  If `x`, `y`, `param` or `scalar` does not have a shape that satisfies
  all specified constraints, `message`, as well as the first `summarize` entries
  of the first encountered violating tensor are printed, and
  `InvalidArgumentError` is raised.

  Size entries in the specified shapes are checked against other entries by
  their __hash__, except:
    - a size entry is interpreted as an explicit size if it can be parsed as an
      integer primitive.
    - a size entry is interpreted as *any* size if it is None or '.'.

  If the first entry of a shape is `...` (type `Ellipsis`) or '*' that indicates
  a variable number of outer dimensions of unspecified size, i.e. the constraint
  applies to the inner-most dimensions only.

  Scalar tensors and specified shapes of length zero (excluding the 'inner-most'
  prefix) are both treated as having a single dimension of size one.

  Args:
    shapes: A list of (`Tensor`, `shape`) tuples, wherein `shape` is the
      expected shape of `Tensor`. See the example code above. The `shape` must
      be an iterable. Each element of the iterable can be either a concrete
      integer value or a string that abstractly represents the dimension.
      For example,
        - `('N', 'Q')` specifies a 2D shape wherein the first and second
          dimensions of shape may or may not be equal.
        - `('N', 'N', 'Q')` specifies a 3D shape wherein the first and second
          dimensions are equal.
        - `(1, 'N')` specifies a 2D shape wherein the first dimension is
          exactly 1 and the second dimension can be any value.
      Note that the abstract dimension letters take effect across different
      tuple elements of the list. For example,
      `tf.debugging.assert_shapes([(x, ('N', 'A')), (y, ('N', 'B'))]` asserts
      that both `x` and `y` are rank-2 tensors and their first dimensions are
      equal (`N`).
      `shape` can also be a `tf.TensorShape`.
    data: The tensors to print out if the condition is False.  Defaults to error
      message and first few entries of the violating tensor.
    summarize: Print this many entries of the tensor.
    message: A string to prefix to the default message.
    name: A name for this operation (optional).  Defaults to "assert_shapes".

  Returns:
    Op raising `InvalidArgumentError` unless all shape constraints are
    satisfied.
    If static checks determine all constraints are satisfied, a `no_op` is
    returned.

  Raises:
    ValueError:  If static checks determine any shape constraint is violated.
  r'   c                 S   s6   g | ]\}}|d urt |tjr|nt||fqS r+   )r,   r   r~   r   ru   )r7   r8   sr2   r2   r3   r9     s
    
z!assert_shapes.<locals>.<listcomp>c                    s    st | tjrt| S | jS r+   )r,   r   r~   rG   rF   r8   rv   r2   r3   tensor_name  s   z"assert_shapes.<locals>.tensor_namer}   __getitem__z%sTensor %s.  Specified shape must be an iterable.  An iterable has the attribute `__iter__` or `__getitem__`.  Received specified shape: %sF*r   z%sTensor %s specified shape index %d.  Symbol `...` or `*` for a variable number of unspecified dimensions is only allowed as the first entryTr   N)r   r   )r8   r   rB   rd   r>   rF   )r8   r   rB   rd   r>   rF   zSpecified explicitlyz#Specified by tensor %s dimension %dzL%s%s.  Tensor %s dimension %s must have size %d.  Received size %d, shape %szTensor %s dimensionzmust have sizer   rp   )'r,   dictitemsr   r   rt   r   rv   r   r   r   r   Ellipsisr\   r  r   r   rj   r  r  r"   r8   r#   r!   r  r   r   Zcontrol_dependenciesr  r   r   r   ru   r   rD   r   rz   r   group)"r  rB   rd   r>   rF   Zmessage_prefixZshape_constraintsr  Ztensor_dim_sizesr   r   is_iterableZsymbolic_shape_tupleZtensors_specified_innermostr   r  Zrank_assertionsr   r   Zrank_zero_or_oneZ	assertionZsize_assertionsZsize_specificationsZsize_symbolZ
tensor_dimZspecified_sizeZsize_check_messageZspecified_by_yZspecified_at_dimZactual_sizerA   Zdata_rb   Zshapes_assertionr2   r  r3   r'     s  
\





 
r'   c                    sj   t dgtstd tt d}fdd}t d   fdd}t|||S )z#Gets the difference x[1:] - x[:-1].r[   z+Expected x to be numeric, instead found: %sr   c                      s   t jg  jdS )Nr   )r   ru   rE   r2   r
  r2   r3   r     s    z4_get_diff_for_monotonic_comparison.<locals>.<lambda>r   c                      s&   t dgdg  t dg  S )Nr   r   )r   Zstrided_slicer2   Zs_lenr8   r2   r3   r     s   & )	r   ra   r)   r   r   r   rb   rD   r   )r8   Zis_shorter_than_twoZshort_resultr   r2   r  r3   "_get_diff_for_monotonic_comparison  s   r  zdebugging.is_numeric_tensorr)   c                 C   s   t | tjo
| jtv S )a)  Returns `True` if the elements of `tensor` are numbers.

  Specifically, returns `True` if the dtype of `tensor` is one of the following:

  * `tf.float16`
  * `tf.float32`
  * `tf.float64`
  * `tf.int8`
  * `tf.int16`
  * `tf.int32`
  * `tf.int64`
  * `tf.uint8`
  * `tf.uint16`
  * `tf.uint32`
  * `tf.uint64`
  * `tf.qint8`
  * `tf.qint16`
  * `tf.qint32`
  * `tf.quint8`
  * `tf.quint16`
  * `tf.complex64`
  * `tf.complex128`
  * `tf.bfloat16`

  Returns `False` if `tensor` is of a non-numeric type or if `tensor` is not
  a `tf.Tensor` object.
  )r,   r-   r.   rE   NUMERIC_TYPESr   r2   r2   r3   r)     s    math.is_non_decreasing)r  debugging.is_non_decreasingr(   r  r(   c                 C   ^   t |d| g t| }t jd|jd}tt||W  d   S 1 s(w   Y  dS )a!  Returns `True` if `x` is non-decreasing.

  Elements of `x` are compared in row-major order.  The tensor `[x[0],...]`
  is non-decreasing if for every adjacent pair we have `x[i] <= x[i+1]`.
  If `x` has less than two elements, it is trivially non-decreasing.

  See also:  `is_strictly_increasing`

  >>> x1 = tf.constant([1.0, 1.0, 3.0])
  >>> tf.math.is_non_decreasing(x1)
  <tf.Tensor: shape=(), dtype=bool, numpy=True>
  >>> x2 = tf.constant([3.0, 1.0, 2.0])
  >>> tf.math.is_non_decreasing(x2)
  <tf.Tensor: shape=(), dtype=bool, numpy=False>

  Args:
    x: Numeric `Tensor`.
    name: A name for this operation (optional).  Defaults to "is_non_decreasing"

  Returns:
    Boolean `Tensor`, equal to `True` iff `x` is non-decreasing.

  Raises:
    TypeError: if `x` is not a numeric tensor.
  r(   r   r   N)r   rt   r  ru   rE   r   rw   r   r8   rF   r   r   r2   r2   r3   r(     s
   #$math.is_strictly_increasing)r   debugging.is_strictly_increasingr*   r  r*   c                 C   r  )aC  Returns `True` if `x` is strictly increasing.

  Elements of `x` are compared in row-major order.  The tensor `[x[0],...]`
  is strictly increasing if for every adjacent pair we have `x[i] < x[i+1]`.
  If `x` has less than two elements, it is trivially strictly increasing.

  See also:  `is_non_decreasing`

  >>> x1 = tf.constant([1.0, 2.0, 3.0])
  >>> tf.math.is_strictly_increasing(x1)
  <tf.Tensor: shape=(), dtype=bool, numpy=True>
  >>> x2 = tf.constant([3.0, 1.0, 2.0])
  >>> tf.math.is_strictly_increasing(x2)
  <tf.Tensor: shape=(), dtype=bool, numpy=False>

  Args:
    x: Numeric `Tensor`.
    name: A name for this operation (optional).
      Defaults to "is_strictly_increasing"

  Returns:
    Boolean `Tensor`, equal to `True` iff `x` is strictly increasing.

  Raises:
    TypeError: if `x` is not a numeric tensor.
  r*   r   r   N)r   rt   r  ru   rE   r   rw   r   r  r2   r2   r3   r*     s
   $$c                 C   s   |}d}| D ]}|dur|j j}|s|}q||krd} qq|re|}d}| D ]<}|durb|j j}|sA|}t|dr<|jnt|}q&||krbtdt|drO|jnt||||r]d| f df q&|S |S )a  Asserts all items are of the same base type.

  Args:
    items: List of graph items (e.g., `Variable`, `Tensor`, `SparseTensor`,
        `Operation`, or `IndexedSlices`). Can include `None` elements, which
        will be ignored.
    expected_type: Expected type. If not specified, assert all items are
        of the same base type.

  Returns:
    Validated type, or none if neither expected_type nor items provided.

  Raises:
    ValueError: If any types do not match.
  FNTrF   z-%s, type=%s, must be of the same type (%s)%s.z as %sr   )rE   Z
base_dtyper   rF   r/   r   )r  expected_typeZoriginal_expected_typeZmismatchitemZ	item_typeZoriginal_item_strr2   r2   r3   _assert_same_base_type  s>   
r  z!debugging.assert_same_float_dtyper$   c                 C   s2   | rt | |}|stj}|S |jstd| |S )a  Validate and return float type based on `tensors` and `dtype`.

  For ops such as matrix multiplication, inputs and weights must be of the
  same float type. This function validates that all `tensors` are the same type,
  validates that type is `dtype` (if supplied), and returns the type. Type must
  be a floating point type. If neither `tensors` nor `dtype` is supplied,
  the function will return `dtypes.float32`.

  Args:
    tensors: Tensors of input values. Can include `None` elements, which will be
        ignored.
    dtype: Expected type.

  Returns:
    Validated type.

  Raises:
    ValueError: if neither `tensors` nor `dtype` is supplied, or result is not
        float, or the common type of the inputs is not a floating point type.
  z%Expected floating point type, got %s.)r  r   float32Zis_floatingr   )ZtensorsrE   r2   r2   r3   r$   F  s   
zdebugging.assert_scalarc                 C   r   )a  Asserts that the given `tensor` is a scalar.

  This function raises `ValueError` unless it can be certain that the given
  `tensor` is a scalar. `ValueError` is also raised if the shape of `tensor` is
  unknown.

  This is always checked statically, so this method returns nothing.

  Args:
    tensor: A `Tensor`.
    message: A string to prefix to the default message.
    name:  A name for this operation. Defaults to "assert_scalar"

  Raises:
    ValueError: If the tensor is not scalar (rank 0), or if its shape is
      unknown.
  r   r>   rF   N)r%   r!  r2   r2   r3   assert_scalar_v2i  s   r"  r%   c                 C   s   t |d| g4}t j| |d} |  }t|}|jdkr3t r)td||f td|| j	|f | W  d   S 1 s?w   Y  dS )a5  Asserts that the given `tensor` is a scalar (i.e. zero-dimensional).

  This function raises `ValueError` unless it can be certain that the given
  `tensor` is a scalar. `ValueError` is also raised if the shape of `tensor` is
  unknown.

  Args:
    tensor: A `Tensor`.
    name:  A name for this operation. Defaults to "assert_scalar"
    message: A string to prefix to the default message.

  Returns:
    The input tensor (potentially converted to a `Tensor`).

  Raises:
    ValueError: If the tensor is not scalar (rank 0), or if its shape is
      unknown.
  r%   rm   r   z'%sExpected scalar shape, saw shape: %s.z.%sExpected scalar shape for %s, saw shape: %s.N)
r   rt   ru   r   r   r   r   rv   r   rF   )r   rF   r>   rt   rD   r2   r2   r3   r%     s   

$c                 C   s   | rd|  S dS )Nz%s.  r   r2   )r>   r2   r2   r3   r     s   r   ensure_shapec                 C   s&   t |tjst|}tj| ||dS )a  Updates the shape of a tensor and checks at runtime that the shape holds.

  When executed, this operation asserts that the input tensor `x`'s shape
  is compatible with the `shape` argument.
  See `tf.TensorShape.is_compatible_with` for details.

  >>> x = tf.constant([[1, 2, 3],
  ...                  [4, 5, 6]])
  >>> x = tf.ensure_shape(x, [2, 3])

  Use `None` for unknown dimensions:

  >>> x = tf.ensure_shape(x, [None, 3])
  >>> x = tf.ensure_shape(x, [2, None])

  If the tensor's shape is not compatible with the `shape` argument, an error
  is raised:

  >>> x = tf.ensure_shape(x, [5])
  Traceback (most recent call last):
  ...
  tf.errors.InvalidArgumentError: Shape of tensor dummy_input [3] is not
    compatible with expected shape [5]. [Op:EnsureShape]

  During graph construction (typically tracing a `tf.function`),
  `tf.ensure_shape` updates the static-shape of the **result** tensor by
  merging the two shapes. See `tf.TensorShape.merge_with` for details.

  This is most useful when **you** know a shape that can't be determined
  statically by TensorFlow.

  The following trivial `tf.function` prints the input tensor's
  static-shape before and after `ensure_shape` is applied.

  >>> @tf.function
  ... def f(tensor):
  ...   print("Static-shape before:", tensor.shape)
  ...   tensor = tf.ensure_shape(tensor, [None, 3])
  ...   print("Static-shape after:", tensor.shape)
  ...   return tensor

  This lets you see the effect of `tf.ensure_shape` when the function is traced:
  >>> cf = f.get_concrete_function(tf.TensorSpec([None, None]))
  Static-shape before: (None, None)
  Static-shape after: (None, 3)

  >>> cf(tf.zeros([3, 3])) # Passes
  >>> cf(tf.constant([1, 2, 3])) # fails
  Traceback (most recent call last):
  ...
  InvalidArgumentError:  Shape of tensor x [3] is not compatible with expected shape [3,3].

  The above example raises `tf.errors.InvalidArgumentError`, because `x`'s
  shape, `(3,)`, is not compatible with the `shape` argument, `(None, 3)`

  Inside a `tf.function` or `v1.Graph` context it checks both the buildtime and
  runtime shapes. This is stricter than `tf.Tensor.set_shape` which only
  checks the buildtime shape.

  Note: This differs from `tf.Tensor.set_shape` in that it sets the static shape
  of the resulting tensor and enforces it at runtime, raising an error if the
  tensor's runtime shape is incompatible with the specified shape.
  `tf.Tensor.set_shape` sets the static shape of the tensor without enforcing it
  at runtime, which may result in inconsistencies between the statically-known
  shape of tensors and the runtime value of tensors.

  For example, of loading images of a known size:

  >>> @tf.function
  ... def decode_image(png):
  ...   image = tf.image.decode_png(png, channels=3)
  ...   # the `print` executes during tracing.
  ...   print("Initial shape: ", image.shape)
  ...   image = tf.ensure_shape(image,[28, 28, 3])
  ...   print("Final shape: ", image.shape)
  ...   return image

  When tracing a function, no ops are being executed, shapes may be unknown.
  See the [Concrete Functions Guide](https://www.tensorflow.org/guide/concrete_function)
  for details.

  >>> concrete_decode = decode_image.get_concrete_function(
  ...     tf.TensorSpec([], dtype=tf.string))
  Initial shape:  (None, None, 3)
  Final shape:  (28, 28, 3)

  >>> image = tf.random.uniform(maxval=255, shape=[28, 28, 3], dtype=tf.int32)
  >>> image = tf.cast(image,tf.uint8)
  >>> png = tf.image.encode_png(image)
  >>> image2 = concrete_decode(png)
  >>> print(image2.shape)
  (28, 28, 3)

  >>> image = tf.concat([image,image], axis=0)
  >>> print(image.shape)
  (56, 28, 3)
  >>> png = tf.image.encode_png(image)
  >>> image2 = concrete_decode(png)
  Traceback (most recent call last):
  ...
  tf.errors.InvalidArgumentError:  Shape of tensor DecodePng [56,28,3] is not
    compatible with expected shape [28,28,3].

  Caution: if you don't use the result of `tf.ensure_shape` the check may not
  run.

  >>> @tf.function
  ... def bad_decode_image(png):
  ...   image = tf.image.decode_png(png, channels=3)
  ...   # the `print` executes during tracing.
  ...   print("Initial shape: ", image.shape)
  ...   # BAD: forgot to use the returned tensor.
  ...   tf.ensure_shape(image,[28, 28, 3])
  ...   print("Final shape: ", image.shape)
  ...   return image

  >>> image = bad_decode_image(png)
  Initial shape:  (None, None, 3)
  Final shape:  (None, None, 3)
  >>> print(image.shape)
  (56, 28, 3)

  Args:
    x: A `Tensor`.
    shape: A `TensorShape` representing the shape of this tensor, a
      `TensorShapeProto`, a list, a tuple, or None.
    name: A name for this operation (optional). Defaults to "EnsureShape".

  Returns:
    A `Tensor`. Has the same type and contents as `x`.

  Raises:
    tf.errors.InvalidArgumentError: If `shape` is incompatible with the shape
    of `x`.
  rm   )r,   r	   ZTensorShaper   r#  )r8   rD   rF   r2   r2   r3   r#    s    
ZEnsureShapec                 C   s   ~ |S r+   r2   )r=   Zgradr2   r2   r3   _ensure_shape_grad:	  s   r$  )NNN)NNNN)NNNNN)NNNNNN)NNr+   )vrO   collectionsr_   ri   Ztensorflow.python.eagerr   Ztensorflow.python.frameworkr   r   r   r   r   r-   r	   r
   Ztensorflow.python.opsr   r   r   r   r   Ztensorflow.python.utilr   r   r   Z tensorflow.python.util.tf_exportr   	frozensetZfloat16r   Zfloat64Zint8Zint16r   Zint64Zuint8Zuint16Zuint32Zuint64Zqint8Zqint16Zqint32Zquint8Zquint16Z	complex64Z
complex128Zbfloat16r  __all__r4   rC   rG   rS   rW   rY   rh   rl   r{   Zadd_dispatch_supportZdeprecated_endpointsr   r   r   r   r   r   r   r   r   Z&register_binary_elementwise_assert_apir   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r!   r   r"   r   r   r   r   r#   r   r   r   r&   r   r   r   r  
namedtupler  r  r'   r  r)   r(   r*   r  r$   r"  r%   r   r#  ZRegisterGradientr$  r2   r2   r2   r3   <module>   s  	?wN6K


!
!

	

4P





0 
> @

4
>
$!


A  !
"/
! 