
    BVh:              
          d Z ddlmZm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 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j\                  dd      Z/d  Z0d@d!Z1dd"d#Z2 G d$ d%e3      Z4 e-d&d'd&g(       G d) d&e'jj                  e&jl                               Z7 e-d*g(      d+        Z8 e-d,g(      d-        Z9d.e:d/e:fd0Z;d1 Z< G d2 d3ejz                        Z> e-d4       ej~                  d5       G d6 d4e>ej                  e	j                  e'j                                      ZB e	j                  eB        e	j                  eB        G d7 d8      ZE e#j                   eE               ej~                  d9       G d: d;eBe	j                               ZG G d< d=      ZH e#j                   eH               e	j                  eG        ej                  e7d>         ej                  ej                  d?        y)AzTensor and TensorSpec classes.    )OptionalTypeN)attr_value_pb2)
trace_type)
struct_pb2)tf2)context)
monitoring)record)common_shapes)dtypes)errors)op_callbacks)stack)tensor_conversion_registry)tensor_shape)tensor_util)	type_spec)type_spec_registry)handle_data_util)
tf_logging)nested_structure_coder)core)internal)compat)deprecation)object_identity)	tf_exportz&/tensorflow/api/enable_tensor_equalityz/Whether ops.enable_tensor_equality() is called.c                     |t         j                  vr t        d| dt         j                   d      t        | ||       y)aN  Overrides (string) operator on Tensors to call func.

  Args:
    clazz_object: the class to override for; either Tensor or SparseTensor.
    operator: the string name of the operator to override.
    func: the function that replaces the overridden operator.

  Raises:
    ValueError: If operator is not allowed to be overwritten.
  zOverriding z& is disallowed. Allowed operators are .N)TensorOVERLOADABLE_OPERATORS
ValueErrorsetattr)clazz_objectoperatorfuncs      R/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/framework/tensor.py_override_helperr)   6   sL     V222
{8* -..4.K.K-LAO P P	,$'    c                     |:t        j                         }|t        d      |j                  |ur$t        d      |j                  |urt        d      |j	                  | |      S )a  Uses the default session to evaluate one or more tensors.

  Args:
    tensors: A single Tensor, or a list of Tensor objects.
    feed_dict: A dictionary that maps Tensor objects (or tensor names) to lists,
      numpy ndarrays, TensorProtos, or strings.
    graph: The graph in which the tensors are defined.
    session: (Optional) A different session to use to evaluate "tensors".

  Returns:
    Either a single numpy ndarray if "tensors" is a single tensor; or a list
    of numpy ndarrays that each correspond to the respective element in
    "tensors".

  Raises:
    ValueError: If no default session is available; the default session
      does not have "graph" as its graph; or if "session" is specified,
      and it does not have "graph" as its graph.
  zCannot evaluate tensor using `eval()`: No default session is registered. Use `with sess.as_default()` or pass an explicit session to `eval(session=sess)`zCannot use the default session to evaluate tensor: the tensor's graph is different from the session's graph. Pass an explicit session to `eval(session=sess)`.zjCannot use the given session to evaluate tensor: the tensor's graph is different from the session's graph.)r   get_default_sessionr#   graphrun)tensors	feed_dictr-   sessions       r(   _eval_using_default_sessionr2   G   s    ( _'')G . / / }}E! / 0 0
 }}E!   ! ! 
Wi	((r*   namec                    || S | d|  S )N:  )msgr4   s     r(   _add_error_prefixr9   o   s    2TF"SE"22r*   c                   .    e Zd ZdZg dZd Zd Zd ZeZy)_TensorIteratorzDIterates over the leading dim of a Tensor. Performs no error checks._tensor_index_limitc                 .    || _         d| _        || _        y )Nr   r<   )selftensordim0s      r(   __init__z_TensorIterator.__init__x   s    DLDKDKr*   c                     | S Nr7   rA   s    r(   __iter__z_TensorIterator.__iter__}   s    Kr*   c                     | j                   | j                  k(  rt        | j                  | j                      }| xj                   dz  c_         |S )N   )r>   r?   StopIterationr=   )rA   results     r(   __next__z_TensorIterator.__next__   s=    {{dkk!\\$++&FKK1KMr*   N)	__name__
__module____qualname____doc__	__slots__rD   rH   rM   nextr7   r*   r(   r;   r;   s   s     L-)
 
$r*   r;   r!   zexperimental.numpy.ndarray)v1c                      e Zd ZdZh dZ ej                         Zd Ze	d        Z
e	d        Ze	dej                  fd       Ze	d        Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zdej                  fdZd Zd Zd Zd Zd ZdZd&dZd Z e!d        Z"d Z#d Z$d'dZ% e&jN                  dd      d         Z(d! Z)d" Z*	 d'd#e+e,jZ                     d$e+e.   dd fd%Z/y)(r!   a  A `tf.Tensor` represents a multidimensional array of elements.

  All elements are of a single known data type.

  When writing a TensorFlow program, the main object that is
  manipulated and passed around is the `tf.Tensor`.

  A `tf.Tensor` has the following properties:

  * a single data type (float32, int32, or string, for example)
  * a shape

  TensorFlow supports eager execution and graph execution.  In eager
  execution, operations are evaluated immediately.  In graph
  execution, a computational graph is constructed for later
  evaluation.

  TensorFlow defaults to eager execution.  In the example below, the
  matrix multiplication results are calculated immediately.

  >>> # Compute some values using a Tensor
  >>> c = tf.constant([[1.0, 2.0], [3.0, 4.0]])
  >>> d = tf.constant([[1.0, 1.0], [0.0, 1.0]])
  >>> e = tf.matmul(c, d)
  >>> print(e)
  tf.Tensor(
  [[1. 3.]
   [3. 7.]], shape=(2, 2), dtype=float32)

  Note that during eager execution, you may discover your `Tensors` are actually
  of type `EagerTensor`.  This is an internal detail, but it does give you
  access to a useful function, `numpy`:

  >>> type(e)
  <class '...ops.EagerTensor'>
  >>> print(e.numpy())
    [[1. 3.]
     [3. 7.]]

  In TensorFlow, `tf.function`s are a common way to define graph execution.

  A Tensor's shape (that is, the rank of the Tensor and the size of
  each dimension) may not always be fully known.  In `tf.function`
  definitions, the shape may only be partially known.

  Most operations produce tensors of fully-known shapes if the shapes of their
  inputs are also fully known, but in some cases it's only possible to find the
  shape of a tensor at execution time.

  A number of specialized tensors are available: see `tf.Variable`,
  `tf.constant`, `tf.placeholder`, `tf.sparse.SparseTensor`, and
  `tf.RaggedTensor`.

  Caution: when constructing a tensor from a numpy array or pandas dataframe
  the underlying buffer may be re-used:

  ```python
  a = np.array([1, 2, 3])
  b = tf.constant(a)
  a[0] = 4
  print(b)  # tf.Tensor([4 2 3], shape=(3,), dtype=int64)
  ```

  Note: this is an implementation detail that is subject to change and users
  should not rely on this behaviour.

  For more on Tensors, see the [guide](https://tensorflow.org/guide/tensor).
  >"   __eq____ge____gt____le____lt____ne____or____abs____add____and____div____mod____mul____neg____pow____ror____sub____xor____radd____rand____rdiv____rmod____rmul____rpow____rsub____rxor__
__invert__
__matmul____getitem____rmatmul____truediv____floordiv____rtruediv____rfloordiv__c                 |    |dv r't        t        |       j                   d| ddz         | j                  |       y )N>	   Tclipdatasizeravelastypetolistreshape	transposez object has no attribute 'z'. z
        If you are looking for numpy-related methods, please run the following:
        tf.experimental.numpy.experimental_enable_numpy_behavior()
      )AttributeErrortyperN   __getattribute__)rA   r4   s     r(   __getattr__zTensor.__getattr__   sU     " " $Z  !!;D6
E I
 
 
 	$r*   c                     | j                   S )z'The `DType` of elements in this tensor._dtyperG   s    r(   dtypezTensor.dtype       ;;r*   c                     | j                   S rF   _namerG   s    r(   r4   zTensor.name  s    ::r*   returnc                     | j                   P| j                  \  }}|r%t        j                         | _         | j                   S t        j                  |      | _         | j                   S )aC  Returns a `tf.TensorShape` that represents the shape of this tensor.

    >>> t = tf.constant([1,2,3,4,5])
    >>> t.shape
    TensorShape([5])

    `tf.Tensor.shape` is equivalent to `tf.Tensor.get_shape()`.

    In a `tf.function` or when building a model using
    `tf.keras.Input`, they return the build-time shape of the
    tensor, which may be partially unknown.

    A `tf.TensorShape` is not a tensor. Use `tf.shape(t)` to get a tensor
    containing the shape, calculated at runtime.

    See `tf.Tensor.get_shape()`, and `tf.TensorShape` for details and examples.
    )
_shape_val_shaper   unknown_shapeTensorShape)rA   dimsr   s      r(   shapezTensor.shape  sY    &  KKdM	&446 ?? '2248??r*   c                 .    | j                   j                  S rF   )r   rankrG   s    r(   ndimzTensor.ndim*  s    ::??r*   c                 2    t        j                  | d      )Na   is not allowed. You can attempt the following resolutions to the problem: If you are running in Graph mode, use Eager execution mode or decorate this function with @tf.function. If you are using AutoGraph, you can try decorating this function with @tf.function. If that does not work, then you may be using an unsupported feature or your source code may not be visible to AutoGraph. See https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/limitations.md#access-to-source-code for more information.)r   OperatorNotAllowedInGraphError)rA   tasks     r(   	_disallowzTensor._disallow.  s$    

/
/& 	! 		!
" 
"r*   c                 &    | j                  d       y )Nz/Using a symbolic `tf.Tensor` as a Python `bool`r   rG   s    r(   _disallow_bool_castingzTensor._disallow_bool_casting;  s    NNDEr*   c                 &    | j                  d       y )Nz%Iterating over a symbolic `tf.Tensor`r   rG   s    r(   _disallow_iterationzTensor._disallow_iteration>  s    NN:;r*   c                     t        j                         s| j                          | j                         }t	        | |      S rF   )r	   executing_eagerlyr   _get_first_dimr;   )rA   	first_dims     r(   rH   zTensor.__iter__A  s5    $$&
 ##%I4++r*   c                     | j                         }|t        d      |st        d      |d   t        d      |d   S )Nz0Cannot iterate over a tensor with unknown shape.z$Cannot iterate over a scalar tensor.r   z:Cannot iterate over a tensor with unknown first dimension.)_shape_tuple	TypeErrorrA   r   s     r(   r   zTensor._get_first_dimH  sU    E}HII<==Qx
FH H8Or*   c                     | j                   j                  .| j                   j                  D cg c]  }|j                   c}S y c c}w rF   )r   ndimsr   value)rA   dims     r(   _shape_as_listzTensor._shape_as_listS  s7    zz##'::??3Ccii33 4s   Ac                 >    | j                         }|y t        |      S rF   )r   tupler   s     r(   r   zTensor._shape_tupleY  s"    !E}<r*   c                 @    t        j                  d| g|gd d        y)zAConnect this graph tensor with capture for gradients calculation.captured_valuec                     | gS rF   r7   xs    r(   <lambda>z%Tensor._record_tape.<locals>.<lambda>d  s    QC r*   c                     | gS rF   r7   r   s    r(   r   z%Tensor._record_tape.<locals>.<lambda>e  s    A3 r*   )backward_functionforward_functionN)r   record_operation)rA   captures     r(   _record_tapezTensor._record_tape_  s"    
		'&	(r*   c                     | j                   S )a
  Returns a `tf.TensorShape` that represents the shape of this tensor.

    In eager execution the shape is always fully-known.

    >>> a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
    >>> print(a.shape)
    (2, 3)

    `tf.Tensor.get_shape()` is equivalent to `tf.Tensor.shape`.


    When executing in a `tf.function` or building a model using
    `tf.keras.Input`, `Tensor.shape` may return a partial shape (including
    `None` for unknown dimensions). See `tf.TensorShape` for more details.

    >>> inputs = tf.keras.Input(shape = [10])
    >>> # Unknown batch size
    >>> print(inputs.shape)
    (None, 10)

    The shape is computed using shape inference functions that are
    registered for each `tf.Operation`.

    The returned `tf.TensorShape` is determined at *build* time, without
    executing the underlying kernel. It is not a `tf.Tensor`. If you need a
    shape *tensor*, either convert the `tf.TensorShape` to a `tf.constant`, or
    use the `tf.shape(tensor)` function, which returns the tensor's shape at
    *execution* time.

    This is useful for debugging and providing early errors. For
    example, when tracing a `tf.function`, no ops are being executed, shapes
    may be unknown (See the [Concrete Functions
    Guide](https://www.tensorflow.org/guide/concrete_function) for details).

    >>> @tf.function
    ... def my_matmul(a, b):
    ...   result = a@b
    ...   # the `print` executes during tracing.
    ...   print("Result shape: ", result.shape)
    ...   return result

    The shape inference functions propagate shapes to the extent possible:

    >>> f = my_matmul.get_concrete_function(
    ...   tf.TensorSpec([None,3]),
    ...   tf.TensorSpec([3,5]))
    Result shape: (None, 5)

    Tracing may fail if a shape missmatch can be detected:

    >>> cf = my_matmul.get_concrete_function(
    ...   tf.TensorSpec([None,3]),
    ...   tf.TensorSpec([4,5]))
    Traceback (most recent call last):
    ...
    ValueError: Dimensions must be equal, but are 3 and 4 for 'matmul' (op:
    'MatMul') with input shapes: [?,3], [4,5].

    In some cases, the inferred shape may have unknown dimensions. If
    the caller has additional information about the values of these
    dimensions, `tf.ensure_shape` or `Tensor.set_shape()` can be used to augment
    the inferred shape.

    >>> @tf.function
    ... def my_fun(a):
    ...   a = tf.ensure_shape(a, [5, 5])
    ...   # the `print` executes during tracing.
    ...   print("Result shape: ", a.shape)
    ...   return a

    >>> cf = my_fun.get_concrete_function(
    ...   tf.TensorSpec([None, None]))
    Result shape: (5, 5)

    Returns:
      A `tf.TensorShape` representing the shape of this tensor.

    r   rG   s    r(   	get_shapezTensor.get_shapeg  s    ^ ::r*   c                 N   d| _         t        |t        j                        st        j                  |      }g }|j                  d}nLd}|j                  D ];  }|j
                  |j                  d       !|j                  |j
                         = | j                  ||       y)a  Updates the shape of this tensor.

    Note: It is recommended to use `tf.ensure_shape` instead of
    `Tensor.set_shape`, because `tf.ensure_shape` provides better checking for
    programming errors and can create guarantees for compiler
    optimization.

    With eager execution this operates as a shape assertion.
    Here the shapes match:

    >>> t = tf.constant([[1,2,3]])
    >>> t.set_shape([1, 3])

    Passing a `None` in the new shape allows any value for that axis:

    >>> t.set_shape([1,None])

    An error is raised if an incompatible shape is passed.

    >>> t.set_shape([1,5])
    Traceback (most recent call last):
    ...
    ValueError: Tensor's shape (1, 3) is not compatible with supplied
    shape [1, 5]

    When executing in a `tf.function`, or building a model using
    `tf.keras.Input`, `Tensor.set_shape` will *merge* the given `shape` with
    the current shape of this tensor, and set the tensor's shape to the
    merged value (see `tf.TensorShape.merge_with` for details):

    >>> t = tf.keras.Input(shape=[None, None, 3])
    >>> print(t.shape)
    (None, None, None, 3)

    Dimensions set to `None` are not updated:

    >>> t.set_shape([None, 224, 224, None])
    >>> print(t.shape)
    (None, 224, 224, 3)

    The main use case for this is to provide additional shape information
    that cannot be inferred from the graph alone.

    For example if you know all the images in a dataset have shape [28,28,3] you
    can set it with `tf.set_shape`:

    >>> @tf.function
    ... def load_image(filename):
    ...   raw = tf.io.read_file(filename)
    ...   image = tf.image.decode_png(raw, channels=3)
    ...   # the `print` executes during tracing.
    ...   print("Initial shape: ", image.shape)
    ...   image.set_shape([28, 28, 3])
    ...   print("Final shape: ", image.shape)
    ...   return image

    Trace the function, see the [Concrete Functions
    Guide](https://www.tensorflow.org/guide/concrete_function) for details.

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

    Similarly the `tf.io.parse_tensor` function could return a tensor with
    any shape, even the `tf.rank` is unknown. If you know that all your
    serialized tensors will be 2d, set it with `set_shape`:

    >>> @tf.function
    ... def my_parse(string_tensor):
    ...   result = tf.io.parse_tensor(string_tensor, out_type=tf.float32)
    ...   # the `print` executes during tracing.
    ...   print("Initial shape: ", result.shape)
    ...   result.set_shape([None, None])
    ...   print("Final shape: ", result.shape)
    ...   return result

    Trace the function

    >>> concrete_parse = my_parse.get_concrete_function(
    ...     tf.TensorSpec([], dtype=tf.string))
    Initial shape:  <unknown>
    Final shape:  (None, None)

    Make sure it works:

    >>> t = tf.ones([5,3], dtype=tf.float32)
    >>> serialized = tf.io.serialize_tensor(t)
    >>> print(serialized.dtype)
    <dtype: 'string'>
    >>> print(serialized.shape)
    ()
    >>> t2 = concrete_parse(serialized)
    >>> print(t2.shape)
    (5, 3)

    Caution: `set_shape` ensures that the applied shape is compatible with
    the existing shape, but it does not check at runtime. Setting
    incorrect shapes can result in inconsistencies between the
    statically-known graph and the runtime value of tensors. For runtime
    validation of the shape, use `tf.ensure_shape` instead. It also modifies
    the `shape` of the tensor.

    >>> # Serialize a rank-3 tensor
    >>> t = tf.ones([5,5,5], dtype=tf.float32)
    >>> serialized = tf.io.serialize_tensor(t)
    >>> # The function still runs, even though it `set_shape([None,None])`
    >>> t2 = concrete_parse(serialized)
    >>> print(t2.shape)
    (5, 5, 5)

    Args:
      shape: A `TensorShape` representing the shape of this tensor, a
        `TensorShapeProto`, a list, a tuple, or None.

    Raises:
      ValueError: If `shape` is not compatible with the current shape of
        this tensor.
    NTF)r   
isinstancer   r   r   r   append
_set_shape)rA   r   dim_listr   r   s        r(   	set_shapezTensor.set_shape  s    r DO e\556&&u-eHzzmm %#99
//"

//#))
$	%
 	OOHm,r*   c                     | j                   j                  sJ | j                  dk(  r| j                   j                  S d| j                   j                  | j                  fz  S )a+  Return a value to use for the NodeDef "input" attribute.

    The returned string can be used in a NodeDef "input" attribute
    to indicate that the NodeDef uses this Tensor as input.

    Raises:
      ValueError: if this Tensor's Operation does not have a name.

    Returns:
      a string.
    r   z%s:%d)_opr4   value_indexrG   s    r(   _as_node_def_inputzTensor._as_node_def_inputB  sN     88===1XX]]t'7'7888r*   c                    d| j                   d| j                         j                  d| j                         z  nd| j                  rd| j                  j                   z  nd| j                  rd| j                  z  dS ddS )NzTensor(""z
, shape=%s z
, dtype=%sz, device=%s))r4   r   r   r   devicerG   s    r(   __str__zTensor.__str__T  s    		"nn.44@ 
		
FH	I-1[[((	(b@)-	$<> >
 ;=<> >r*   c                 r    d| j                   d| j                         d| j                  j                   dS )Nz<tf.Tensor 'z' shape=z dtype=>)r4   r   r   rG   s    r(   __repr__zTensor.__repr__\  s+    3799dnn>N37;;3C3CE Er*   c                     t        | dd       }t        j                  r||j                  rt	        d      t        |       S )Nr-   z;Tensor is unhashable. Instead, use tensor.ref() as the key.)getattrr!   _USE_EQUALITYbuilding_functionr   id)rA   gs     r(   __hash__zTensor.__hash__`  sB    gt$A!)q/B/B > ? ? Xor*   d   Nc                 6    ~t        d| j                   d      )Nz%Cannot convert a symbolic tf.Tensor (zx) to a numpy array. This error may indicate that you're trying to pass a Tensor to a NumPy call, which is not supported.)NotImplementedErrorr4   )rA   r   s     r(   	__array__zTensor.__array__q  s'    

/		{ ;1 	23 3r*   c                 4    t        d| j                   d      )Nz/len is not well defined for a symbolic Tensor (zD). Please call `x.shape` rather than `len(x)` for shape information.)r   r4   rG   s    r(   __len__zTensor.__len__x  s'    
 		{ #67 8 8r*   c                 &    t        t        | |       y rF   )r)   r!   )r&   r'   s     r(   _override_operatorzTensor._override_operator~  s    VXt,r*   c                 $    | j                          y)a  Dummy method to prevent a tensor from being used as a Python `bool`.

    This overload raises a `TypeError` when the user inadvertently
    treats a `Tensor` as a boolean (most commonly in an `if` or `while`
    statement), in code that was not converted by AutoGraph. For example:

    ```python
    if tf.constant(True):  # Will raise.
      # ...

    if tf.constant(5) < tf.constant(7):  # Will raise.
      # ...
    ```

    Raises:
      `TypeError`.
    Nr   rG   s    r(   __bool__zTensor.__bool__  s    $ 	!r*   c                 $    | j                          y)zDummy method to prevent a tensor from being used as a Python `bool`.

    This is the Python 2.x counterpart to `__bool__()` above.

    Raises:
      `TypeError`.
    Nr   rG   s    r(   __nonzero__zTensor.__nonzero__  s     	!r*   c                 2    t        | || j                  |      S )a  Evaluates this tensor in a `Session`.

    Note: If you are not using `compat.v1` libraries, you should not need this,
    (or `feed_dict` or `Session`).  In eager execution (or within `tf.function`)
    you do not need to call `eval`.

    Calling this method will execute all preceding operations that
    produce the inputs needed for the operation that produces this
    tensor.

    *N.B.* Before invoking `Tensor.eval()`, its graph must have been
    launched in a session, and either a default session must be
    available, or `session` must be specified explicitly.

    Args:
      feed_dict: A dictionary that maps `Tensor` objects to feed values. See
        `tf.Session.run` for a description of the valid feed values.
      session: (Optional.) The `Session` to be used to evaluate this tensor. If
        none, the default session will be used.

    Returns:
      A numpy array corresponding to the value of this tensor.
    )r2   r-   )rA   r0   r1   s      r(   evalzTensor.eval  s    0 'tY

GLLr*   zUse ref() instead.c                 "    | j                         S rF   )refrG   s    r(   experimental_refzTensor.experimental_ref  s    88:r*   c                 ,    t        j                  |       S )a  Returns a hashable reference object to this Tensor.

    The primary use case for this API is to put tensors in a set/dictionary.
    We can't put tensors in a set/dictionary as `tensor.__hash__()` is no longer
    available starting Tensorflow 2.0.

    The following will raise an exception starting 2.0

    >>> x = tf.constant(5)
    >>> y = tf.constant(10)
    >>> z = tf.constant(10)
    >>> tensor_set = {x, y, z}
    Traceback (most recent call last):
      ...
    TypeError: Tensor is unhashable. Instead, use tensor.ref() as the key.
    >>> tensor_dict = {x: 'five', y: 'ten'}
    Traceback (most recent call last):
      ...
    TypeError: Tensor is unhashable. Instead, use tensor.ref() as the key.

    Instead, we can use `tensor.ref()`.

    >>> tensor_set = {x.ref(), y.ref(), z.ref()}
    >>> x.ref() in tensor_set
    True
    >>> tensor_dict = {x.ref(): 'five', y.ref(): 'ten', z.ref(): 'ten'}
    >>> tensor_dict[y.ref()]
    'ten'

    Also, the reference object provides `.deref()` function that returns the
    original Tensor.

    >>> x = tf.constant(5)
    >>> x.ref().deref()
    <tf.Tensor: shape=(), dtype=int32, numpy=5>
    )r   	ReferencerG   s    r(   r   z
Tensor.ref  s    N $$T**r*   c                 p   | j                   t        j                  k(  s| j                   t        j                  k(  rYt	        j
                  |       }|rt        j                  |      nd }t        j                  | j                   j                  |      }n| j                   }t        | j                  |      }|S rF   )r   r   resourcevariantr   get_handle_data
HandleDataDType
_type_enum
TensorSpecr   )rA   signature_contextshape_inference_handle_datahandle_datar   specs         r(   __tf_tracing_type__zTensor.__tf_tracing_type__  s    zzV__$

fnn(D$4$D$DT$J! ) 

7
8 
 ll4::00+>ejjedjj%(DKr*   r   r4   c           
          |X|j                  | j                        s=t        t        d|j                   d| j                  j                   d| |            | S )Nz"Tensor conversion requested dtype z for Tensor with dtype r6   r3   )is_compatible_withr   r#   r9   r4   )rA   r   r4   s      r(   __tf_tensor__zTensor.__tf_tensor__  sd     !9!9$**!E
25::, ?''+zz&7r$C 
 Kr*   rF   )NN)0rN   rO   rP   rQ   r"   r   enabledr   r   propertyr   r4   r   r   r   r   r   r   r   rH   r   r   r   r   r   r   r   r   r   r   __array_priority__r   r   staticmethodr   r   r   r   r   
deprecatedr   r   r   r   r   r   strr   r7   r*   r(   r!   r!      ss   CJ%P #++--	      \--  4  "F<,	(O11 ObH-T9$>E 38 - -"("M4 ;$ 45 6'+R IM	FLL)	8@		r*   enable_tensor_equalityc                      t        j                  dd       t        j                         j	                  d       dt
        _        y)a4  Compare Tensors with element-wise comparison and thus be unhashable.

  Comparing tensors with element-wise allows comparisons such as
  tf.Variable(1.0) == 1.0. Element-wise equality implies that tensors are
  unhashable. Thus tensors can no longer be directly used in sets or as a key in
  a dictionary.
  rJ   zEnabling tensor equalityTNloggingvlog _tensor_equality_api_usage_gaugeget_cellsetr!   r   r7   r*   r(   r  r    s2     
,,q,-"++-11$7&r*   disable_tensor_equalityc                      t        j                  dd       t        j                         j	                  d       dt
        _        y)zvCompare Tensors by their id and be hashable.

  This is a legacy behaviour of TensorFlow and is highly discouraged.
  rJ   zDisabling tensor equalityFNr  r7   r*   r(   r  r    s2     
,,q-."++-11%8&r*   r4   r   c                     | sydj                  | j                         D cg c]  }|j                         r|nd c}      }|d   j                         r|S d|z   S c c}w )ah  Sanitizes Spec names. Matches Graph Node and Python naming conventions.

  Without sanitization, names that are not legal Python parameter names can be
  set which makes it challenging to represent callables supporting the named
  calling capability.

  Args:
    name: The name to sanitize.

  Returns:
    A string that meets Python parameter conventions.
  unknownr   _r   tensor_)joinlowerisalnumisalpha)r4   cswappeds      r(   sanitize_spec_namer    s^     
 GG

E1!))+Q3.EF'QZNw Fs   Ac                     | st        d|  d      | j                  d      r| dd } d| v r| j                  d      \  }}|S | S )af  Extract the Op name from a Tensor name.

  The Op name is everything before a colon, if present,
  not including any ^ prefix denoting a control dependency.

  Args:
    tensor_name: the full name of a Tensor in the graph.
  Returns:
    The name of the Op of which the given Tensor is an output.
  Raises:
    ValueError: if tensor_name is None or empty.
  z/Tensor name cannot be empty or None. Received: r    ^rJ   N:)r#   
startswithsplit)tensor_nameop_namer  s      r(   get_op_namer!  4  sd     


9+aHJ J C ab/KK""3'JGQN	r*   c                       e Zd ZdZg dZ ed       Zej                  dfdZ	ed        Z
ed        Zed        Zd	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zy)	DenseSpecz5Describes a dense object with shape, dtype, and name.r   r   r   c                     | S rF   r7   rG   s    r(   r   zDenseSpec.<lambda>S  s    4 r*   Nc                 z    t        j                  |      | _        t        j                  |      | _        || _        y)ao  Creates a TensorSpec.

    Args:
      shape: Value convertible to `tf.TensorShape`. The shape of the tensor.
      dtype: Value convertible to `tf.DType`. The type of the tensor values.
      name: Optional name for the Tensor.

    Raises:
      TypeError: If shape is not convertible to a `tf.TensorShape`, or dtype is
        not convertible to a `tf.DType`.
    N)r   r   r   r   as_dtyper   r   )rA   r   r   r4   s       r(   rD   zDenseSpec.__init__U  s-     **51DK//%(DKDJr*   c                     | j                   S )zBReturns the `TensorShape` that represents the shape of the tensor.r   rG   s    r(   r   zDenseSpec.shapee  r   r*   c                     | j                   S )z.Returns the `dtype` of elements in the tensor.r   rG   s    r(   r   zDenseSpec.dtypej  r   r*   c                     | j                   S )z?Returns the (optionally provided) name of the described tensor.r   rG   s    r(   r4   zDenseSpec.nameo  s     ::r*   c                     t        |t        | j                  f      xrL | j                  j	                  |j
                        xr% | j                  j	                  |j                        S rF   )r   r#  
value_typer   r   r   r   r   )rA   spec_or_values     r(   r   zDenseSpec.is_compatible_witht  sW    }y$//&BC @KK**=+>+>?@KK**=+>+>?Ar*   c                     dj                  t        |       j                  | j                  t	        | j
                        t	        | j                              S )Nz{}(shape={}, dtype={}, name={}))formatr   rN   r   reprr   r4   rG   s    r(   r   zDenseSpec.__repr__y  s?    ,33T
TZZdjj)94		?L Lr*   c                 D    t        | j                  | j                  f      S rF   hashr   r   rG   s    r(   r   zDenseSpec.__hash__}      djj)**r*   c                     t        |       t        |      u xrO | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j                  |j                  k(  S rF   )r   r   r   r   rA   others     r(   rV   zDenseSpec.__eq__  sY    J$u+% F$++*E FKK5<<'F,0JJ%++,EGr*   c                     | |k(   S rF   r7   r7  s     r(   r[   zDenseSpec.__ne__  s    u}r*   c                 H    | j                   | j                  | j                  fS rF   r$  rG   s    r(   
_serializezDenseSpec._serialize  s    KKdjj11r*   c                     | j                   S rF   r   rG   s    r(   _to_legacy_output_typesz!DenseSpec._to_legacy_output_types      ;;r*   c                     | j                   S rF   r)  rG   s    r(   _to_legacy_output_shapesz"DenseSpec._to_legacy_output_shapes  r>  r*   c                     | j                   S rF   )r-  rG   s    r(   _to_legacy_output_classesz#DenseSpec._to_legacy_output_classes  s    ??r*   )rN   rO   rP   rQ   rR   r   _component_specsr   float32rD   r   r   r4   r   r   r   rV   r[   r;  r=  r@  rB  r7   r*   r(   r#  r#  N  s    =+)/0"(..t        A
L+G
2r*   r#  r   ztf.TensorSpecc                   T    e Zd ZdZg Zedeej                     fd       Z	edej                  dd fd       Z
dej                  fdZ fdZd Zd	 Zdd
Zd Zd Zd Zd Zd Zedd       Zedd       Zed        Zd Zd Zd ZddZd Zd Zed        Zd Z d Z!ddZ" xZ#S ) r   am  Describes the type of a tf.Tensor.

  >>> t = tf.constant([[1,2,3],[4,5,6]])
  >>> tf.TensorSpec.from_tensor(t)
  TensorSpec(shape=(2, 3), dtype=tf.int32, name=None)

  Contains metadata for describing the nature of `tf.Tensor` objects
  accepted or returned by some TensorFlow APIs.

  For example, it can be used to constrain the type of inputs accepted by
  a tf.function:

  >>> @tf.function(input_signature=[tf.TensorSpec([1, None])])
  ... def constrained_foo(t):
  ...   print("tracing...")
  ...   return t

  Now the `tf.function` is able to assume that `t` is always of the type
  `tf.TensorSpec([1, None])` which will avoid retracing as well as enforce the
  type restriction on inputs.

  As a result, the following call with tensor of type `tf.TensorSpec([1, 2])`
  triggers a trace and succeeds:
  >>> constrained_foo(tf.constant([[1., 2]])).numpy()
  tracing...
  array([[1., 2.]], dtype=float32)

  The following subsequent call with tensor of type `tf.TensorSpec([1, 4])`
  does not trigger a trace and succeeds:
  >>> constrained_foo(tf.constant([[1., 2, 3, 4]])).numpy()
  array([[1., 2., 3., 4.], dtype=float32)

  But the following call with tensor of type `tf.TensorSpec([2, 2])` fails:
  >>> constrained_foo(tf.constant([[1., 2], [3, 4]])).numpy()
  Traceback (most recent call last):
  ...
  TypeError: Binding inputs to tf.function `constrained_foo` failed ...

  r   c                 "    t         j                  S )zCReturns the type of proto associated with TensorSpec serialization.)r   TensorSpecProtoclss    r(   experimental_type_protoz"TensorSpec.experimental_type_proto  s     %%%r*   protoc                     t        t        j                  j                  |j                        |j
                  |j                  r|j                        S d      S )z<Returns a TensorSpec instance based on the serialized proto.Nr   r   r4   )r   r   r   experimental_from_protor   r   r4   rI  rK  s     r(   rN  z"TensorSpec.experimental_from_proto  sL     &&>>u{{Kkk ::UZZ1 1 ,01 1r*   c                     t        j                  | j                  j                         | j                  j                         j
                  | j                        S )z:Returns a proto representation of the TensorSpec instance.rM  )r   rG  r   experimental_as_protor   datatyper4   rG   s    r(   rQ  z TensorSpec.experimental_as_proto  sB    %%jj..0jj..099YY r*   c                 *    t         t        |   |      S )aa  Returns True if spec_or_tensor is compatible with this TensorSpec.

    Two tensors are considered compatible if they have the same dtype
    and their shapes are compatible (see `tf.TensorShape.is_compatible_with`).

    Args:
      spec_or_tensor: A tf.TensorSpec or a tf.Tensor

    Returns:
      True if spec_or_tensor is compatible with self.
    )superr   r   )rA   spec_or_tensor	__class__s     r(   r   zTensorSpec.is_compatible_with  s     T5nEEr*   c                    t        |t              sy| j                   xs | j                  |j                  k(  xrL | j                  j	                  |j                        xr% | j
                  j	                  |j
                        S )NF)r   r   r4   r   is_subtype_ofr   r7  s     r(   rX  zTensorSpec.is_subtype_of  sg    eZ( YY	1$))uzz1 	2JJ$$U[[1	2JJ$$U[[1r*   c                 &   |j                   r| S | j                  xs |j                  }|j                  }|j                  r.|j                  d      5  | j                  ||      }ddd       n| j                  ||      }|Cj                  j                  dt        j                  t        j                  |                   | j                  j                  }|L|j                  j                   r6|j                  j"                  r t%        j&                  |j                         |j(                  Mj                  j                  dt        j                  t        j                  |j(                                     S # 1 sw Y   xY w)zCGenerates a graph placholder with the given TensorSpec information.Nr3   _user_specified_name)s_composite_device)unnest_onlyr4   naming_scopecontext_graphwith_none_control_dependenciescontrol_dependencies_graph_placeholderop	_set_attrr   	AttrValuer   as_bytesr   _handle_datashape_inferenceis_setshape_and_typer   set_handle_datacomposite_device_name)rA   placeholder_contextr4   r_  placeholderr   s         r(   placeholder_valuezTensorSpec.placeholder_value  s`   &&k998+88D'55M99 --d3 H--m$-GH H ++M+Ek nn
 

"
"V__T%:
;= **))K''..''66&&{K4O4OP
 00<nn


"
"V__!77&9 :;
 ;H Hs   FFc                    | j                   j                  }| j                  }t        j                  |j
                        }t        |t        t        f      rt        j                  |      }t        j                  |j                               }||d}	 |j                  dg |gg ||      }|j                   \  }	t#        j$                         r<t#        j&                  dt               |t        |j                         ||      }
|
|
\  }	|	S # t        $ r6}t        j                  |       |j                  dg |gg |      }Y d}~d}~ww xY w)	zHGraph-only version of tf.compat.v1.placeholder(), for internal use only.)r   r   )r   r   Placeholder)input_typesattrsr4   )rr  rs  N)r   r-   )r   
base_dtyper   r   re  as_datatype_enumr   listr   r   r   as_proto_create_op_internalr#   r  warningoutputsr   should_invoke_op_callbacksinvoke_op_callbacks)rA   r-   r4   r   r   dtype_valuers  rc  erL   callback_outputss              r(   rb  zTensorSpec._graph_placeholder  s8   JJ!!EJJE **0F0FGK%$'&&u-e$$5>>+;<E!E2E
C$$
eW"D % "b 

IV..0 &99
%rzz):e% 
	%$	M!  C ooa$$
eW"E % CbCs   D 	E,E

Ec                     | j                  |t        j                               }|j                  j	                  | j                        s%t        d|j                   d| j                         |gS )NzReceived tensor of shape z instead of )castr   InternalCastContextr   rX  r   rA   r   s     r(   
to_tensorszTensorSpec.to_tensors8  s_    IIeZ;;=>E;;$$TZZ0%ekk],tzzl
K  7Nr*   c                     t        |      }| j                  j                  }|r t        j                  ||j
                         |S rF   )rS   r   rg  r   rk  rh  )rA   r/   rB   r   s       r(   from_tensorszTensorSpec.from_tensors@  s8    ']F**))K&&v{/J/JKMr*   c                     | gS rF   r7   rG   s    r(   flattenzTensorSpec.flattenG  s	    6Mr*   c                    |j                   r0t        |t              r |j                  |       sJ d|d|        | S t        |t              s t        j                  || j                        }t        |j                  |j                  | j                        }|j                  |       s?| j                  |      r|j                  | j                         |S t        d|d|       |S )z<Cast value to a tensor that is a subtype of this TensorSpec.Can not cast  to )allow_specsr   r   rX  r!   r   convertr   r   r4   r   r   )rA   r   casting_context
value_specs       r(   r  zTensorSpec.castJ  s    
 ""z%'D  &M-yTH(MM&keV$(00

CeEKKdii@J##D)			J	'

# L -
~T$BCCLr*   c                 v    d}| j                   j                  r | j                   j                  j                  }|S )z@Returns an id specifying identical tensors to avoid duplication.N)r   rg  alias_id)rA   r  s     r(   	_alias_idzTensorSpec._alias_id_  s.    Hzz((11hOr*   c                 Z     | |j                   |j                  |xs |j                        S )a  Returns a `TensorSpec` with the same shape and dtype as `spec`.

    >>> spec = tf.TensorSpec(shape=[8, 3], dtype=tf.int32, name="OriginalName")
    >>> tf.TensorSpec.from_spec(spec, "NewName")
    TensorSpec(shape=(8, 3), dtype=tf.int32, name='NewName')

    Args:
      spec: The `TypeSpec` used to create the new `TensorSpec`.
      name: The name for the new `TensorSpec`.  Defaults to `spec.name`.
    rM  )rI  r   r4   s      r(   	from_speczTensorSpec.from_specf  s$     tzz4::t'8tyy99r*   c                 N   t        |t        j                        r!t        |j                  |j
                  |      S t        |t        j                        r9t        |j                  |j
                  |xs |j                  j                        S t        dt        |       d      )al  Returns a `TensorSpec` that describes `tensor`.

    >>> tf.TensorSpec.from_tensor(tf.constant([1, 2, 3]))
    TensorSpec(shape=(3,), dtype=tf.int32, name=None)

    Args:
      tensor: The `tf.Tensor` that should be described.
      name: A name for the `TensorSpec`.  Defaults to `tensor.op.name`.

    Returns:
      A `TensorSpec` that describes `tensor`.
    z-`tensor` should be a tf.Tensor, but got type r    )r   core_tf_typesValuer   r   r   Symbolrc  r4   r#   r   )rI  rB   r4   s      r(   from_tensorzTensorSpec.from_tensort  s~     &---.fllD99	FM00	1fllD4JFIINNKK9$v,q
IK Kr*   c                     t         S )zBThe Python type for values that are compatible with this TypeSpec.)r!   rG   s    r(   r-  zTensorSpec.value_type  s	     Mr*   c                 >    t        |t        j                        sJ |S rF   )r   r  r!   r  s     r(   _to_componentszTensorSpec._to_components  s    e]11222Lr*   c                     |S rF   r7   )rA   
componentss     r(   _from_componentszTensorSpec._from_components  s    r*   c                 h    t        |      dk(  sJ |d   j                  | j                         |d   S )NrJ   r   )lenr   r   )rA   tensor_lists     r(   _from_compatible_tensor_listz'TensorSpec._from_compatible_tensor_list  s7     {q   NT[[)q>r*   c                     |r=| j                   j                  |j                        j                  dk(  rt	        d      | j                  |      S )Nr   3Unbatching a tensor is only supported for rank >= 1)r   
merge_withr   r   r#   r  )rA   r   batcheds      r(   _to_batchable_tensor_listz$TensorSpec._to_batchable_tensor_list  sB    4;;))%++6<<ALMMu%%r*   c                     t        t        j                  |g      j                  | j                        | j
                        S rF   )r   r   r   concatenater   r   )rA   
batch_sizes     r(   _batchzTensorSpec._batch  s5      *.::4;;G r*   c                     | j                   j                  dk(  rt        d      t        | j                   dd  | j                        S )Nr   r  rJ   )r   r   r#   r   r   rG   s    r(   _unbatchzTensorSpec._unbatch  s;    {{ALMMdkk!"ot{{33r*   c                     | gS rF   r7   rG   s    r(   _flat_tensor_specszTensorSpec._flat_tensor_specs  s	    6Mr*   c                 &    | j                  |      gS rF   )r  r  s     r(   _to_tensor_listzTensorSpec._to_tensor_list  s    &''r*   c                 $    | j                  |      S rF   )r  r  s     r(   _to_batched_tensor_listz"TensorSpec._to_batched_tensor_list  s    &&r*   c                 ^    | j                   | S t        | j                  | j                        S )z8Returns a version of `TensorSpec` with the name removed.)r4   r   r   r   rG   s    r(   _without_tensor_namesz TensorSpec._without_tensor_names  s&    yyk

DJJ//r*   rF   )F)r   r   )$rN   rO   rP   rQ   rR   classmethodr   r   rG  rJ  rN  rQ  r   rX  ro  rb  r  r  r  r  r  r  r  r   r-  r  r  r  r  r  r  r  r  r  r  __classcell__rV  s   @r(   r   r     s   &P )&d:+E+E&F & & 1,,11=1 1Z%?%? F'R>* : : K K,  	&

4
  ('0r*   c                   (    e Zd ZdZd Zd Zd Zd Zy)_TensorSpecCodeczCodec for `TensorSpec`.c                 H    t        |t              xr t        |t               S rF   )r   r   BoundedTensorSpecrA   pyobjs     r(   
can_encodez_TensorSpecCodec.can_encode  s$    uj) 55"3446r*   c                    t        j                         }|j                  j                  t        j                   ||j
                        j                   ||j                        j                  |j                               |S )NrM  )
r   StructuredValuetensor_spec_valueCopyFromrG  r   tensor_shape_valuer   tensor_dtype_valuer4   )rA   r  	encode_fnencoded_tensor_specs       r(   	do_encodez_TensorSpecCodec.do_encode  sn    $446))22""-334GG-334GG"''	)*
 r*   c                 $    |j                  d      S )Nr  HasFieldr  s     r(   
can_decodez_TensorSpecCodec.can_decode  s    >>-..r*   c                    |j                   j                  }t         |t        j                  |j                   j
                               |t        j                  |j                   j                              |r|      S d       S )Nr  r  rM  )r  r4   r   r   r  r   r   )rA   r   	decode_fnr4   s       r(   	do_decodez_TensorSpecCodec.do_decode  s    ""''D&&#(#:#:#@#@BC &&#(#:#:#@#@BC d' ' !%' 'r*   NrN   rO   rP   rQ   r  r  r  r  r7   r*   r(   r  r    s    6
/	'r*   r  ztf.BoundedTensorSpecc                        e Zd ZdZdZd fd	Zedeej                     fd       Z
edej                  dd fd       Zdej                  fdZed	        Zed
        Zed        Zd Zd Z fdZd Zd Zd Z xZS )r  a0  A `TensorSpec` that specifies minimum and maximum values.

  Example usage:
  ```python
  spec = tensor_spec.BoundedTensorSpec((1, 2, 3), tf.float32, 0, (5, 5, 5))
  tf_minimum = tf.convert_to_tensor(spec.minimum, dtype=spec.dtype)
  tf_maximum = tf.convert_to_tensor(spec.maximum, dtype=spec.dtype)
  ```

  Bounds are meant to be inclusive. This is especially important for
  integer types. The following spec will be satisfied by tensors
  with values in the set {0, 1, 2}:
  ```python
  spec = tensor_spec.BoundedTensorSpec((3, 5), tf.int32, 0, 2)
  ```
  )_minimum_maximumc                 p   t         t        |   |||       |t        d      |t        d      	 t	        j
                  |      }t        j                  t        j                  |      | j
                         	 t	        j
                  |      }t        j                  t        j                  |      | j
                         t	        j                  || j                  j                        | _        | j                  j                  d	
       t	        j                  || j                  j                        | _        | j                  j                  d	
       y# t        $ r"}t        d| d| j
                   d      |d}~ww xY w# t        $ r"}t        d| d| j
                   d      |d}~ww xY w)a  Initializes a new `BoundedTensorSpec`.

    Args:
      shape: Value convertible to `tf.TensorShape`. The shape of the tensor.
      dtype: Value convertible to `tf.DType`. The type of the tensor values.
      minimum: Number or sequence specifying the minimum element bounds
        (inclusive). Must be broadcastable to `shape`.
      maximum: Number or sequence specifying the maximum element bounds
        (inclusive). Must be broadcastable to `shape`.
      name: Optional string containing a semantic name for the corresponding
        array. Defaults to `None`.

    Raises:
      ValueError: If `minimum` or `maximum` are not provided or not
        broadcastable to `shape`.
      TypeError: If the shape is not an iterable or if the `dtype` is an invalid
        numpy dtype.
    Nz`minimum` can not be None.z`maximum` can not be None.z
`minimum` z is not compatible with shape r    z
`maximum` )r   F)write)rT  r  rD   r#   npr   r   broadcast_shaper   r   arrayr   as_numpy_dtyper  setflagsr  )
rA   r   r   minimummaximumr4   minimum_shape	exceptionmaximum_shaperV  s
            r(   rD   zBoundedTensorSpec.__init__  sz   & 

T+E5$?344344hhw'm##

"
"=
14::?hhw'm##

"
"=
14::? HHWDJJ,E,EFDMMM'HHWDJJ,E,EFDMMM'%  wi=djj\
K  wi=djj\
Ks1   AE ;AF
 	F%FF
	F5F00F5r   c                 "    t         j                  S )zJReturns the type of proto associated with BoundedTensorSpec serialization.)r   BoundedTensorSpecProtorH  s    r(   rJ  z)BoundedTensorSpec.experimental_type_proto4  s     ,,,r*   rK  c                 2   t        t        j                  j                  |j                        |j
                  t        j                  |j                        t        j                  |j                        |j                  r|j                        S d      S )zCReturns a BoundedTensorSpec instance based on the serialized proto.Nr   r   r  r  r4   )r  r   r   rN  r   r   r   MakeNdarrayr  r  r4   rO  s     r(   rN  z)BoundedTensorSpec.experimental_from_proto9  sp     &&>>u{{Kkk''6''6 ::UZZ1 1
 ,01 1r*   c                 2   t        j                  | j                  j                         | j                  j                         j
                  t        j                  | j                        t        j                  | j                        | j                        S )zAReturns a proto representation of the BoundedTensorSpec instance.r  )r   r  r   rQ  r   rR  r   make_tensor_protor  r  r4   rG   s    r(   rQ  z'BoundedTensorSpec.experimental_as_protoD  sf    ,,jj..0jj..099--dmm<--dmm<YY r*   c                     t        j                  |j                        }t        |d|j                        }t        |d|j
                        }t        |j                  ||||j                        S )ag  Returns a `TensorSpec` with the same shape and dtype as `spec`.

    If `spec` is a `BoundedTensorSpec`, then the new spec's bounds are set to
    `spec.minimum` and `spec.maximum`; otherwise, the bounds are set to
    `spec.dtype.min` and `spec.dtype.max`.

    >>> spec = tf.TensorSpec(shape=[8, 3], dtype=tf.int32, name="x")
    >>> BoundedTensorSpec.from_spec(spec)
    BoundedTensorSpec(shape=(8, 3), dtype=tf.int32, name='x',
        minimum=array(-2147483648, dtype=int32),
        maximum=array(2147483647, dtype=int32))

    Args:
      spec: The `TypeSpec` used to create the new `BoundedTensorSpec`.
    r  r  )	r   r'  r   r   minmaxr  r   r4   )rI  r   r   r  r  s        r(   r  zBoundedTensorSpec.from_specM  sU    " OODJJ'EdIuyy1GdIuyy1GTZZ$))LLr*   c                     | j                   S )z@Returns a NumPy array specifying the minimum bounds (inclusive).)r  rG   s    r(   r  zBoundedTensorSpec.minimumc       ==r*   c                     | j                   S )z@Returns a NumPy array specifying the maximum bounds (inclusive).)r  rG   s    r(   r  zBoundedTensorSpec.maximumh  r  r*   c                     |j                   r0t        |t              r |j                  |       sJ d|d|        | S t	        | j
                  | j                  | j                        }|j                  ||      S )Nr  r  rM  )	r  r   r  rX  r   r   r   r4   r  )rA   r   r  actual_specs       r(   r  zBoundedTensorSpec.castm  sm    ""z%9J'K  &M-yTH(MM&k4::TZZdiiPKE?33r*   c           	          d}|j                  | j                  t        | j                        t        | j                        t        | j
                        t        | j                              S )NzFBoundedTensorSpec(shape={}, dtype={}, name={}, minimum={}, maximum={}))r0  r   r1  r   r4   r  r  )rA   r[  s     r(   r   zBoundedTensorSpec.__repr__u  sJ    PA88DJJTZZ 0$tyy/&T\\(:< <r*   c                     t         t        |   |      }|xrV t        j                  | j
                  |j
                        xr* t        j                  | j                  |j                        S rF   )rT  r  rV   r  allcloser  r  )rA   r8  tensor_spec_eqrV  s      r(   rV   zBoundedTensorSpec.__eq__z  sR    ,d:5AN 5r{{4<<G 5KKemm46r*   c                 D    t        | j                  | j                  f      S rF   r3  rG   s    r(   r   zBoundedTensorSpec.__hash__  r5  r*   c                     t         | j                  | j                  | j                  | j                  | j
                  ffS rF   )r  r   r   r  r  r   rG   s    r(   
__reduce__zBoundedTensorSpec.__reduce__  s3    t{{DKK#}}djj: : :r*   c                 t    | j                   | j                  | j                  | j                  | j                  fS rF   )r   r   r  r  r   rG   s    r(   r;  zBoundedTensorSpec._serialize  s'    KKdmmT]]DJJOOr*   rF   )rN   rO   rP   rQ   rR   rD   r  r   r   r  rJ  rN  rQ  r  r   r  r  r  r   rV   r   r  r;  r  r  s   @r(   r  r    s    " ')0(d -d:+L+L&M - - 13318K1 1Z%F%F  M M*    4<
6
+:Pr*   r  c                   (    e Zd ZdZd Zd Zd Zd Zy)_BoundedTensorSpecCodeczCodec for `BoundedTensorSpec`.c                 "    t        |t              S rF   )r   r  r  s     r(   r  z"_BoundedTensorSpecCodec.can_encode  s    e.//r*   c                    t        j                         }|j                  j                  t        j                   ||j
                        j                   ||j                        j                  |j                  t        j                  |j                        t        j                  |j                                     |S )z>Returns an encoded proto for the given `tf.BoundedTensorSpec`.)r   r   r4   r  r  )r   r  bounded_tensor_spec_valuer  r  r   r  r   r  r4   r   r  r  r  )rA   r  r  encoded_bounded_tensor_specs       r(   r  z!_BoundedTensorSpecCodec.do_encode  s    ","<"<">99BB))5;;<OO5;;<OO*//11)11311)113	45 '&r*   c                 $    |j                  d      S )Nr  r  r  s     r(   r  z"_BoundedTensorSpecCodec.can_decode  s    >>566r*   c                 h   |j                   }|j                  }t         |t        j                  |j
                               |t        j                  |j                              t        j                  |j                        t        j                  |j                        |r|      S d       S )Nr  r  r  )r  r4   r  r   r  r   r   r   r  r  r  )rA   r   r  btsvr4   s        r(   r  z!_BoundedTensorSpecCodec.do_decode  s    **D99D&&$**EG&&$**EG''5''5d' ' !%' 'r*   Nr  r7   r*   r(   r  r    s    &0'7
'r*   r  c                 B    t        | j                  | j                        S rF   r   r   r   )rB   s    r(   r   r     s    :fllFLLA r*   c                 B    t        | j                  | j                        S rF   r  )r  s    r(   r   r     s    jekkB r*   rF   )KrQ   typingr   r   numpyr  tensorflow.core.frameworkr   tensorflow.core.functionr   tensorflow.core.protobufr   tensorflow.pythonr   tensorflow.python.eagerr	   r
   r   tensorflow.python.frameworkr   r   r   r   r   r   r   r   r   r   tensorflow.python.opsr   tensorflow.python.platformr   r  tensorflow.python.saved_modelr   tensorflow.python.typesr   r  r   tensorflow.python.utilr   r   r    tensorflow.python.util.tf_exportr   	BoolGauger
  r)   r2   r9   objectr;   NativeObjectr  r!   r  r  r  r  r!  TypeSpecr#  registerBatchableTypeSpecSerializabler   register_serializableregister_tensor_typer  register_codecr  r  'register_type_spec_from_value_converterndarrayr7   r*   r(   <module>r      st   % !  4 / / ! + . * 5 . . 4 - B 4 3 1 : 2 < @ 9 , ) . 2 6 $8:#7#7,5$7  
("%)P $( 3f . 81xjAs	X""M$8$8 s	 Bs	l '()
 *
 ()* +S S 24D	"" DN <_-l0I77(((*=*=l0 . l0\	 !
     , 
  
 +' '@ &  % %&6&8 9 34YP
J$;$; YP 5YPx!' !'H &  % %&=&? @  
    !2 3 2	 1 1
AC 2	 1 1JJBDr*   