a
    Sico                     @   s2  d Z ddlm  mZ ddlmZ ddlmZ dZ	G dd dZ
e
ej G dd	 d	e
ZG d
d de
Zeejd eejd eejd eejd eejd G dd dejZG dd de
ZG dd dZeje
fejefejefee
fgZdd Zdd Zdd Zd!ddZdd  ZdS )"z9Keras Input Tensor used to track functional API Topology.    N)object_identity)	structure   c                   @   s   e Zd ZdZd0ddZedd Zedd Zed	d
 Z	ed1ddZ
dd Zdd Zdd Zedd Zdd ZdZd2ddZedd Zdd Zdd Zd d! Zed"d# Zd$d% Zed&d' Zd(d) Zed*d+ Zed,d- Zed.d/ ZdS )3KerasTensora#  A representation of a Keras in/output during Functional API construction.

    `KerasTensor`s are tensor-like objects that represent the symbolic inputs
    and outputs of Keras layers during Functional model construction. They are
    comprised of the `tf.TypeSpec` of the (Composite)Tensor that will be
    consumed/produced in the corresponding location of the Functional model.

    KerasTensors are intended as a private API, so users should never need to
    directly instantiate `KerasTensor`s.

    **Building Functional Models with KerasTensors**
    `tf.keras.Input` produces `KerasTensor`s that represent the symbolic inputs
    to your model.

    Passing a `KerasTensor` to a `tf.keras.Layer` `__call__` lets the layer know
    that you are building a Functional model. The layer __call__ will
    infer the output signature and return `KerasTensor`s with `tf.TypeSpec`s
    corresponding to the symbolic outputs of that layer call. These output
    `KerasTensor`s will have all of the internal KerasHistory metadata attached
    to them that Keras needs to construct a Functional Model.

    Currently, layers infer the output signature by:
      * creating a scratch `FuncGraph`
      * making placeholders in the scratch graph that match the input typespecs
      * Calling `layer.call` on these placeholders
      * extracting the signatures of the outputs before clearing the scratch
        graph

    (Note: names assigned to KerasTensors by this process are not guaranteed to
    be unique, and are subject to implementation details).

    `tf.nest` methods are used to insure all of the inputs/output data
    structures get maintained, with elements swapped between KerasTensors and
    placeholders.

    In rare cases (such as when directly manipulating shapes using Keras
    layers), the layer may be able to partially infer the value of the output in
    addition to just inferring the signature.
    When this happens, the returned KerasTensor will also contain the inferred
    value information. Follow-on layers can use this information.
    during their own output signature inference.
    E.g. if one layer produces a symbolic `KerasTensor` that the next layer uses
    as the shape of its outputs, partially knowing the value helps infer the
    output shape.

    **Automatically converting TF APIs to layers**:
    If you passing a `KerasTensor` to a TF API that supports dispatching,
    Keras will automatically turn that API call into a lambda
    layer in the Functional model, and return KerasTensors representing the
    symbolic outputs.

    Most TF APIs that take only tensors as input and produce output tensors
    will support dispatching.

    Calling a `tf.function` does not support dispatching, so you cannot pass
    `KerasTensor`s as inputs to a `tf.function`.

    Higher-order APIs that take methods which produce tensors (e.g. `tf.while`,
    `tf.map_fn`, `tf.cond`) also do not currently support dispatching. So, you
    cannot directly pass KerasTensors as inputs to these APIs either. If you
    want to use these APIs inside of a Functional model, you must put them
    inside of a custom layer.

    Args:
      type_spec: The `tf.TypeSpec` for the symbolic input created by
        `tf.keras.Input`, or symbolically inferred for the output
        during a symbolic layer `__call__`.
      inferred_value: (Optional) a non-symbolic static value, possibly partially
        specified, that could be symbolically inferred for the outputs during
        a symbolic layer `__call__`. This will generally only happen when
        grabbing and manipulating `tf.int32` shapes directly as tensors.
        Statically inferring values in this way and storing them in the
        KerasTensor allows follow-on layers to infer output signatures
        more effectively. (e.g. when using a symbolic shape tensor to later
        construct a tensor with that shape).
      name: (optional) string name for this KerasTensor. Names automatically
        generated by symbolic layer `__call__`s are not guaranteed to be unique,
        and are subject to implementation details.
    Nc                 C   s   t |tjstd|| _|| _|| _t |tjst	|dsRtdt
|j dt |jtjstdt
|j dt
|jj ddS )	zConstructs a KerasTensor.z6KerasTensors must be constructed with a `tf.TypeSpec`.shapezAKerasTensor only supports TypeSpecs that have a shape field; got z, which does not have a shape.zRKerasTensor requires that wrapped TypeSpec's shape is a TensorShape; got TypeSpec z(, whose shape field has unexpected type .N)
isinstancetfTypeSpec
ValueError
_type_spec_inferred_value_namer   NoneTensorSpechasattrtype__qualname__r   TensorShape	TypeErrordtype)self	type_specinferred_valuename r   U/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/engine/keras_tensor.py__init__q   s,    

zKerasTensor.__init__c                 C   s   | j S )zAReturns the `tf.TypeSpec` symbolically inferred for Keras output.)r   r   r   r   r   r      s    zKerasTensor.type_specc                 C   s   | j jS )zAReturns the `TensorShape` symbolically inferred for Keras output.)r   r   r   r   r   r   r      s    zKerasTensor.shapec                 C   s   t |tjrt|dd}t|}d}|jtjkr||jjdur||jjdk r|tj	|dj}|j
rx| }t|tkr|d}nd}t|||dS t|dd}t|}| ||dS dS )zKConvert a traced (composite)tensor to a representative
        KerasTensor.r   N   r   )r   r   r   )r   r	   Tensorgetattrtype_spec_from_valuer   int32r   rankonesdimsas_listlen_MAX_TENSOR_RANKr   )clstensorr   r   r   r   r   r   from_tensor   s,    




zKerasTensor.from_tensorc                 C   s   | ||dS )N)r   r   r   r+   r   r   r   r   r   from_type_spec   s    zKerasTensor.from_type_specc                 C   s\   | j dur@ttjjj| j tjd}| jjjdkr<|d }|S dd }tj	j
|| jddS )z5Convert this KerasTensor to a placeholder in a graph.N)r   r   r   c                 S   s   t jj| j| jS N)r	   compatv1placeholderr   r   )	componentr   r   r   component_to_placeholder   s    z=KerasTensor._to_placeholder.<locals>.component_to_placeholderT)expand_composites)r   r	   r   r1   r2   r3   r$   r   r%   nestmap_structure)r   r   r5   r   r   r   _to_placeholder   s    
zKerasTensor._to_placeholderc                 C   s   | j S r0   r   r   r   r   r   	get_shape   s    zKerasTensor.get_shapec                 C   s   t dd S )Na_  Keras symbolic inputs/outputs do not implement `__len__`. You may be trying to pass Keras symbolic inputs/outputs to a TF API that does not register dispatching, preventing Keras from automatically converting the API call to a lambda layer in the Functional Model. This error will also get raised if you try asserting a symbolic input/output directly.r   r   r   r   r   __len__   s    zKerasTensor.__len__c                 C   s   t dd S )Na  Keras symbolic inputs/outputs do not implement `op`. You may be trying to pass Keras symbolic inputs/outputs to a TF API that does not register dispatching, preventing Keras from automatically converting the API call to a lambda layer in the Functional Model.r;   r   r   r   r   op   s    zKerasTensor.opc                 C   s   t d|  dd S )Nz%Tensors are unhashable (this tensor: z(). Instead, use tensor.ref() as the key.r;   r   r   r   r   __hash__  s    
zKerasTensor.__hash__d   c                 C   s   t d|  dd S )NzYou are passing a  , an intermediate Keras symbolic input/output, to a TF API that does not allow registering custom dispatchers, such as `tf.cond`, `tf.function`, gradient tapes, or `tf.map_fn`. Keras Functional model construction only supports TF API calls that *do* support dispatching, such as `tf.math.add` or `tf.reshape`. Other APIs cannot be called directly on symbolic Kerasinputs/outputs. You can work around this limitation by putting the operation in a custom Keras layer `call` and calling that layer on this symbolic input/output.r;   )r   r   r   r   r   	__array__  s    
zKerasTensor.__array__c                 C   s   dS )NTr   r   r   r   r   is_tensor_like)  s    zKerasTensor.is_tensor_likec                 C   sZ   t |tjst|}| j|s<td| j d| dn| j|}t| j|| _dS )zNUpdates the shape of this KerasTensor. Mimics
        `tf.Tensor.set_shape()`.z$Keras symbolic input/output's shape z' is not compatible with supplied shape r   N)	r   r	   r   r   is_compatible_withr   
merge_withtype_spec_with_shaper   r   r   r   r   r   	set_shape-  s    

zKerasTensor.set_shapec                 C   sd   d}d}d}t | dr*| jj}d|jf }| jd ur>d| j }| jd urRd| j }d| j|||f S )N _keras_historyz%, description="created by layer '%s'"z, inferred_value=%sz, name='%s'zKerasTensor(type_spec=%s%s%s%s))r   rH   layerr   r   r   r   )r   symbolic_descriptioninferred_value_stringname_stringrI   r   r   r   __str__;  s$    




zKerasTensor.__str__c                 C   st   d}d}t | jtjr*d| j| jjf }n
d| j }t| drR| jj	}d|jf }| j
d urfd| j
 }d|||f S )NrG   zshape=%s dtype=%sztype_spec=%srH   z (created by layer '%s')z inferred_value=%sz<KerasTensor: %s%s%s>)r   r   r	   
TensorSpecr   r   r   r   rH   rI   r   )r   rJ   rK   type_spec_stringrI   r   r   r   __repr__P  s$    



zKerasTensor.__repr__c                 C   s^   | j }t|ds&tdt|j dt|jtjsXt	dt|j dt|jj d|jS )z@Returns the `dtype` symbolically inferred for this Keras output.r   zKerasTensor wraps TypeSpec z, which does not have a dtype.zLKerasTensor requires that wrapped TypeSpec's dtype is a DType; got TypeSpec z(, whose dtype field has unexpected type r   )
r   r   AttributeErrorr   r   r   r   r	   DTyper   )r   r   r   r   r   r   f  s    

zKerasTensor.dtypec                 C   s
   t | S )a  Returns a hashable reference object to this KerasTensor.

        The primary use case for this API is to put KerasTensors in a
        set/dictionary. We can't put tensors in a set/dictionary as
        `tensor.__hash__()` is not available and tensor equality (`==`) is
        supposed to produce a tensor representing if the two inputs are equal.

        See the documentation of `tf.Tensor.ref()` for more info.
        )r   	Referencer   r   r   r   refx  s    
zKerasTensor.refc                 C   s$   t | dr | j\}}}|j| S dS )a.  Find the corresponding `Node` that produce this keras_tensor.

        During functional model construction, Keras will attach `KerasHistory`
        to keras tensor to track the connectivity between calls of layers.
        Return None if there isn't any KerasHistory attached to this tensor.
        rH   N)r   rH   inbound_nodes)r   rI   
node_index_r   r   r   node  s    

zKerasTensor.nodec                 C   s`   d }| j jd ur"dd | j jD }|d u r2td|s>td|d d u rRtdt| |d S )Nc                 S   s   g | ]
}|j qS r   )value).0dimr   r   r   
<listcomp>      z(KerasTensor.__iter__.<locals>.<listcomp>z0Cannot iterate over a Tensor with unknown shape.zCannot iterate over a scalar.r   z:Cannot iterate over a Tensor with unknown first dimension.)r   ndimsr'   r   _KerasTensorIteratorrE   r   r   r   __iter__  s    zKerasTensor.__iter__c                 C   s   | j S )zMReturns the (non-unique, optional) name of this symbolic Keras
        value.)r   r   r   r   r   r     s    zKerasTensor.namec                 C   s4   t jjD ]}| || qt|dr0| |d dS )z%Register overloads for all operators.experimental_refN)r	   r!   OVERLOADABLE_OPERATORS_overload_operatorr   )r+   tensor_classoperatorr   r   r   _overload_all_operators  s    
z#KerasTensor._overload_all_operatorsc                 C   s&   t ||}t |d|}t| || dS )a3  Overload an operator with the same implementation as a base Tensor class.

        We pull the operator out of the class dynamically to avoid ordering
        issues.

        Args:
          tensor_class: The (Composite)Tensor to get the method from.
          operator: string. The operator name.
        __func__N)r"   setattr)r+   rd   re   tensor_operr   r   r   rc     s    
zKerasTensor._overload_operator)NN)N)N)__name__
__module__r   __doc__r   propertyr   r   classmethodr-   r/   r9   r:   r<   r=   r>   __array_priority__r@   rA   rF   rM   rP   r   rT   rX   r`   r   rf   rc   r   r   r   r   r       sF   P



4"







r   c                   @   s   e Zd ZdZdd ZdS )SparseKerasTensorzA specialized KerasTensor representation for `tf.sparse.SparseTensor`s.

    Specifically, it specializes the conversion to a placeholder in order
    to maintain dense shape information.
    c                 C   s   | j }tjjj|j|jdS )N)r   r   )r   r	   r1   r2   sparse_placeholderr   r   )r   specr   r   r   r9     s    z!SparseKerasTensor._to_placeholderN)rj   rk   r   rl   r9   r   r   r   r   rp     s   rp   c                       s,   e Zd ZdZ fddZedd Z  ZS )RaggedKerasTensora  A specialized KerasTensor representation for `tf.RaggedTensor`s.

    Specifically, it:

    1. Specializes the conversion to a placeholder in order
    to maintain shape information for non-ragged dimensions.
    2. Overloads the KerasTensor's operators with the RaggedTensor versions
    when they don't match the `tf.Tensor` versions
    3. Exposes some of the instance method/attribute that are unique to
    the RaggedTensor API (such as ragged_rank).
    c                    s4  | j }|jdks|jjd u r&t  S |j|jd  }tjj	|j
|}g }d}|jD ]<}|d ur|d u szt|ddd u rd }n|| }|| qVt|jddD ]}|j| }|d u st|ddd u r||d  }|d ur|d }tjj	|j|g}	tjj||	dd}qt||j}
tjj||
dd}q|S )Nr      rY   TF)validate)r   ragged_rankr   r%   superr9   r	   r1   r2   r3   r   r"   appendrangerow_splits_dtypeRaggedTensorfrom_row_splitsconstantfrom_uniform_row_length)r   ragged_spec
flat_shaperesultknown_num_splitsprod	axis_sizeaxis
num_splitssplitsrowlen	__class__r   r   r9     s@    


z!RaggedKerasTensor._to_placeholderc                 C   s   | j jS r0   )r   rw   r   r   r   r   rw     s    zRaggedKerasTensor.ragged_rank)rj   rk   r   rl   r9   rm   rw   __classcell__r   r   r   r   rs     s   'rs   __getitem____add____radd____mul____rmul__c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )UserRegisteredSpecz7TypeSpec to represent user-registered symbolic objects.c                 C   s   || _ || _|| _d S r0   )r   _dtyper   )r   r   r   r   r   r   r   )  s    zUserRegisteredSpec.__init__c                 C   s   t d S r0   NotImplementedErrorr   r   r   r   _component_specs.  s    z#UserRegisteredSpec._component_specsc                 C   s   t d S r0   r   )r   
componentsr   r   r   _from_components1  s    z#UserRegisteredSpec._from_componentsc                 C   s   t d S r0   r   r   r   r   r   
_serialize4  s    zUserRegisteredSpec._serializec                 C   s   t d S r0   r   )r   rY   r   r   r   _to_components7  s    z!UserRegisteredSpec._to_componentsc                 C   s   t d S r0   r   r   r   r   r   
value_type:  s    zUserRegisteredSpec.value_typeN)
rj   rk   r   rl   r   r   r   r   r   r   r   r   r   r   r   &  s   r   c                       sB   e Zd ZdZ fddZedd ZedddZd	d
 Z  Z	S )UserRegisteredTypeKerasTensorzAKerasTensor that represents legacy register_symbolic_tensor_type.c                    s6   |}|| _ t|j|j}t|dd }t || d S )Nr   ) _user_registered_symbolic_objectr   r   r   r"   rx   r   )r   user_registered_symbolic_objectxr   r   r   r   r   r   G  s
    z&UserRegisteredTypeKerasTensor.__init__c                 C   s   | |S r0   r   )r+   r,   r   r   r   r-   O  s    z)UserRegisteredTypeKerasTensor.from_tensorNc                 C   s   t d| d S )Nz?You cannot instantiate a KerasTensor directly from TypeSpec: %sr   r.   r   r   r   r/   S  s
    z,UserRegisteredTypeKerasTensor.from_type_specc                 C   s   | j S r0   )r   r   r   r   r   r9   Z  s    z-UserRegisteredTypeKerasTensor._to_placeholder)N)
rj   rk   r   rl   r   rn   r-   r/   r9   r   r   r   r   r   r   D  s   
r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	r_   zLIterates over the leading dim of a KerasTensor. Performs 0 error
    checks.c                 C   s   || _ d| _|| _d S )Nr   )_tensor_index_limit)r   r,   dim0r   r   r   r   b  s    z_KerasTensorIterator.__init__c                 C   s   | S r0   r   r   r   r   r   r`   g  s    z_KerasTensorIterator.__iter__c                 C   s.   | j | jkrt| j| j  }|  j d7  _ |S )Nrt   )r   r   StopIterationr   )r   r   r   r   r   __next__j  s
    z_KerasTensorIterator.__next__N)rj   rk   r   rl   r   r`   r   r   r   r   r   r_   ^  s   r_   c                 C   s   t d| |f dS )z>Register a specialized KerasTensor subclass for a Tensor type.ru   N)keras_tensor_classesinsert)r+   keras_tensor_subclassr   r   r   $register_keras_tensor_specialization  s    r   c                 C   s   t | tr|  S | S dS )zFConstruct a graph placeholder to represent a KerasTensor when tracing.N)r   r   r9   )r   r   r   r   keras_tensor_to_placeholder  s    
r   c                 C   sN   d}t D ]\}}t| |r|} q$q|| }t| dddurJt| j|_|S )zCConvert a traced (composite)tensor to a representative KerasTensor.N_keras_mask)r   r   r-   r"   keras_tensor_from_tensorr   )r,   keras_tensor_clstensor_typer+   outr   r   r   r     s    

r   c                 C   s8   d}| j }tD ]\}}t||r|} q*q|j| |dS )z3Convert a TypeSpec to a representative KerasTensor.Nr    )r   r   
issubclassr/   )r   r   r   r   r   r+   r   r   r   keras_tensor_from_type_spec  s    
r   c                 C   s   t | tjr t|}|| _| S t | tjrFt|| j| j| j| j	S t | tj
r`t
|| jS t| drt| |S tddS )z@Returns a copy of TypeSpec `spec` with its shape set to `shape`.
with_shapezjKeras requires TypeSpec to have a `with_shape` method that returns a copy of `self` with an updated shape.N)r   r	   rN   r   _shapeRaggedTensorSpecr   rw   r{   flat_values_specSparseTensorSpecr   r   r   )rr   r   r   r   r   rD     s&    


rD   )N)rl   tensorflow.compat.v2r1   v2r	   keras.utilsr   tensorflow.python.data.utilr   r*   r   rf   r!   rp   rs   rc   r|   r
   r   r   r_   SparseTensorobjectr   r   r   r   r   rD   r   r   r   r   <module>   s:      ):	
