B
    )`WD                 @   s  d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlZddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  dDddZdd Z!dd Z"dEddZ#dd Z$d d! Z%dFd#d$Z&G d%d& d&e'Z(dGd(d)Z)d*d+ Z*d,d- Z+e, a-d.d/ Z.d0d1 Z/d2d3 Z0d4d5 Z1d6d7 Z2e j3d8d9 Z4e j3d:d; Z5d<d= Z6dHd>d?Z7d@dA Z8dBdC Z9dS )IzTensorFlow-related utilities.    )absolute_import)division)print_functionN)cardinality)context)composite_tensor)ops)
smart_cond)tensor_shape)tensor_spec)tensor_util)	type_spec)backend)control_flow_ops)math_ops)	variables)nest)object_identity)tf_contextlibc             C   s0   t | tjrtj| |||dS tj| |||dS )a  Return either `true_fn()` if predicate `pred` is true else `false_fn()`.

  If `pred` is a bool or has a constant value, we return either `true_fn()`
  or `false_fn()`, otherwise we use `tf.cond` to dynamically route to both.

  Arguments:
    pred: A scalar determining whether to return the result of `true_fn` or
      `false_fn`.
    true_fn: The callable to be performed if pred is true.
    false_fn: The callable to be performed if pred is false.
    name: Optional name prefix when using `tf.cond`.

  Returns:
    Tensors returned by the call to either `true_fn` or `false_fn`.

  Raises:
    TypeError: If `true_fn` or `false_fn` is not callable.
  )true_fnfalse_fnname)
isinstancer   Variabler   Zcondsmart_moduler	   )predr   r   r    r   U/home/dcms/DCMS/lib/python3.7/site-packages/tensorflow/python/keras/utils/tf_utils.pyr	   *   s
    r	   c             C   s>   t | tr$| dkrd} n| dkr$d} t | tjr4dS t| S )a  Return the bool value for `pred`, or None if `pred` had a dynamic value.

  Arguments:
    pred: A scalar, either a Python bool or a TensorFlow boolean variable
      or tensor, or the Python integer 1 or 0.

  Returns:
    True or False if `pred` has a constant boolean value, None otherwise.

  Raises:
    TypeError: If `pred` is not a Variable, Tensor or bool, or Python
      integer 1 or 0.
     Tr   FN)r   intr   r   r   Zsmart_constant_value)r   r   r   r   constant_valueD   s    
r    c             C   s*   t | } | r"t| d tjr"dS dS d S )Nr   TF)r   flattenr   r   Tensor)vr   r   r   is_tensor_or_tensor_list^   s    
r$   c             C   s*  t j| dd} t| }|r,tt |}| dd }x|r$| }t|ttrXq:t|tj	r|j
dd ptg }||j7 }nXt|tjry|jg}W q tk
r   g }Y qX n$t|r| }ntdt| x:|D ]2}||kr|| |r|| |d| qW |r:|s:|S q:W |S )aI  Returns the set of tensors/ops reachable from `inputs`.

  Stops if all targets have been found (target is optional).

  Only valid in Symbolic mode, not Eager mode.

  Args:
    inputs: List of tensors.
    targets: List of tensors.

  Returns:
    A set of tensors reachable from the inputs (includes the inputs themselves).
  T)expand_compositesNz-Expected Operation, Variable, or Tensor, got r   )r   r!   r   ZObjectIdentitySetpopr   tuple_user_convertible_tensor_typesr   Z	OperationoutputsZ_control_outputsr   r   opAttributeErrorr   	is_tensorZ	consumers	TypeErrorstradddiscardinsert)inputstargetsZ	reachableZremaining_targetsqueuexr)   yr   r   r   get_reachable_from_inputsf   s:    





r7   c                s    rS t s(tdt rLfddt D }nt r`t}n} fdd|D }t |S )a  Maps the atomic elements of a nested structure.

  Arguments:
    is_atomic_fn: A function that determines if an element of `nested` is
      atomic.
    map_fn: The function to apply to atomic elements of `nested`.
    nested: A nested structure.

  Returns:
    The nested structure, with atomic elements mapped according to `map_fn`.

  Raises:
    ValueError: If an element that is neither atomic nor a sequence is
      encountered.
  z0Received non-atomic and non-sequence element: {}c                s   g | ]} | qS r   r   ).0k)nestedr   r   
<listcomp>   s    z-map_structure_with_atomic.<locals>.<listcomp>c                s   g | ]}t  |qS r   )map_structure_with_atomic)r8   ele)is_atomic_fnmap_fnr   r   r;      s    )	r   is_sequence
ValueErrorformatZ_is_mappingZ_sortedZ	_is_attrs_astupleZ_sequence_like)r>   r?   r:   valuesZmapped_valuesr   )r>   r?   r:   r   r<      s    



r<   c             C   s   t dd | S )zGets shapes from tensors.c             S   s   | j S )N)shape)r5   r   r   r   <lambda>       zget_shapes.<locals>.<lambda>)r   map_structure)tensorsr   r   r   
get_shapes   s    rJ   Tc                s,   dd   fdd}fdd}t ||| S )a  Converts nested shape representations to desired format.

  Performs:

  TensorShapes -> tuples if `to_tuples=True`.
  tuples of int or None -> TensorShapes if `to_tuples=False`.

  Valid objects to be converted are:
  - TensorShapes
  - tuples with elements of type int or None.
  - ints
  - None

  Arguments:
    input_shape: A nested structure of objects to be converted to TensorShapes.
    to_tuples: If `True`, converts all TensorShape to tuples. Otherwise converts
      all tuples representing shapes to TensorShapes.

  Returns:
    Nested structure of shapes in desired format.

  Raises:
    ValueError: when the input tensor shape can't be converted to tuples, eg
      unknown tensor shape.
  c             S   s   | d kpt | ttjfS )N)r   r   r
   Z	Dimension)valuer   r   r   _is_shape_component   s    z+convert_shapes.<locals>._is_shape_componentc                sH    | rdS t | tjrdS t | ttfrDt fdd| D rDdS dS )NTc             3   s   | ]} |V  qd S )Nr   )r8   r=   )rL   r   r   	<genexpr>   s    z;convert_shapes.<locals>._is_atomic_shape.<locals>.<genexpr>F)r   r
   TensorShaper'   listall)input_shape)rL   r   r   _is_atomic_shape   s    z(convert_shapes.<locals>._is_atomic_shapec                s   t | }  rt|  } | S )N)r
   rN   r'   as_list)rQ   )	to_tuplesr   r   _convert_shape   s    
z&convert_shapes.<locals>._convert_shape)r<   )rQ   rT   rR   rU   r   )rL   rT   r   convert_shapes   s
    rV   c               @   s    e Zd ZdZdd Zdd ZdS )ListWrapperz9A wrapper for lists to be treated as elements for `nest`.c             C   s
   || _ d S )N)_list)selfZlist_to_wrapr   r   r   __init__   s    zListWrapper.__init__c             C   s   | j S )N)rX   )rY   r   r   r   rS     s    zListWrapper.as_listN)__name__
__module____qualname____doc__rZ   rS   r   r   r   r   rW      s   rW   Fc                s.   dd   fdd} fdd}t ||| S )aQ  Either wraps or unwraps innermost node data lists in `ListWrapper` objects.

  Arguments:
    nested: A nested data structure.
    wrap: If `True`, wrap innermost lists in `ListWrapper` objects. If `False`,
      unwraps `ListWrapper` objects into lists.

  Returns:
    Structure of same type as nested, with lists wrapped/unwrapped.
  c             S   s.   t | tr*t| dkr*t | d tjr*dS dS )N)      r   TF)r   rO   lensixstring_types)r:   r   r   r   _is_serialized_node_data  s    z9convert_inner_node_data.<locals>._is_serialized_node_datac                s&   t | trdS  | rdS t|  S )z<Returns `True` if `nested` is a list representing node data.T)r   rW   r   r@   )r:   )rd   r   r   _is_atomic_nested  s
    
z2convert_inner_node_data.<locals>._is_atomic_nestedc                s@   r&t | tr| S  | r"t| S | S t | tr8|  S | S dS )z:Convert b/t `ListWrapper` object and list representations.N)r   rW   rS   )r:   )rd   wrapr   r   _convert_object_or_list!  s    

z8convert_inner_node_data.<locals>._convert_object_or_list)r<   )r:   rf   re   rg   r   )rd   rf   r   convert_inner_node_data  s
    rh   c                s    fdd}|S )zDecorator that handles tuple/TensorShape conversion.

  Used in `compute_output_shape` and `build`.

  Arguments:
    fn: function to wrap.

  Returns:
    Wrapped function.
  c                s6   |d k	rt |dd} | |}|d k	r2t |dd}|S )NT)rT   F)rV   )instancerQ   Zoutput_shape)fnr   r   wrapper>  s    
z&shape_type_conversion.<locals>.wrapperr   )rj   rk   r   )rj   r   shape_type_conversion2  s    rl   c             C   s   t tt| S )N)rP   mapis_symbolic_tensor)rI   r   r   r   are_all_symbolic_tensorsL  s    ro   c             C   s   t | tjrt| dS t | tjrBtj| dd}tdd |D S t | t	j
rdt| ddpbt  S t | ttrt| } t| S dS dS )	aN  Returns whether a tensor is symbolic (from a TF graph) or an eager tensor.

  A Variable can be seen as either: it is considered symbolic
  when we are in a graph scope, and eager when we are in an eager scope.

  Arguments:
    tensor: A tensor instance to test.

  Returns:
    True for symbolic tensors, False for eager tensors.
  graphT)r%   c             s   s   | ]}t |d V  qdS )rp   N)hasattr)r8   tr   r   r   rM   c  s    z%is_symbolic_tensor.<locals>.<genexpr>_keras_historyFN)r   r   r"   rq   r   CompositeTensorr   r!   anyr   r   getattrr   Zexecuting_eagerlyr'   r(   Zconvert_to_tensor_or_compositern   )ZtensorZcomponent_tensorsr   r   r   rn   S  s    


rn   c             C   s   t |  dS )a  Allows users to specify types regarded as symbolic `Tensor`s.

  Used in conjunction with `tf.register_tensor_conversion_function`, calling
  `tf.keras.utils.register_symbolic_tensor_type(cls)` allows non-`Tensor`
  objects to be plumbed through Keras layers.

  Example:

  ```python
  # One-time setup.
  class Foo(object):
    def __init__(self, input_):
      self._input = input_
    def value(self):
      return tf.constant(42.)

  tf.register_tensor_conversion_function(
      Foo, lambda x, *args, **kwargs: x.value())

  tf.keras.utils.register_symbolic_tensor_type(Foo)

  # User-land.
  layer = tf.keras.layers.Lambda(lambda input_: Foo(input_))
  ```

  Arguments:
    cls: A `class` type which shall be regarded as a symbolic `Tensor`.
  N)r(   r/   )clsr   r   r   register_symbolic_tensor_types  s    rx   c             C   sD   t | tjr| jS t| dr6t| dr6t| j| jS t	
| S dS )z9Grab type_spec without converting array-likes to tensors.rE   dtypeN)r   r   rt   
_type_specrq   r   
TensorSpecrE   ry   r   type_spec_from_value)rK   r   r   r   r|     s
    r|   c             C   s   t | pt| tjS )N)r   r,   r   r   r   )r5   r   r   r   is_tensor_or_variable  s    r}   c             C   s8   dd | D }|r4d dd |D }td|dS )aH  Prevent tf.layers.Layers from being used with Keras.

  Certain legacy layers inherit from their keras analogs; however they are
  not supported with keras and can lead to subtle and hard to diagnose bugs.

  Args:
    layers: A list of layers to check

  Raises:
    TypeError: If any elements of layers are tf.layers.Layers
  c             S   s   g | ]}t |d dr|qS )Z_is_legacy_layerN)rv   )r8   lr   r   r   r;     s    z+assert_no_legacy_layers.<locals>.<listcomp>
c             s   s   | ]}d t | V  qdS )z  N)r.   )r8   r~   r   r   r   rM     s    z*assert_no_legacy_layers.<locals>.<genexpr>a  The following are legacy tf.layers.Layers:
{}
To use keras as a framework (for instance using the Network, Model, or Sequential classes), please use the tf.keras.layers implementation instead. (Or, if writing custom layers, subclass from tf.keras.layers rather than tf.layers)N)joinr-   rB   )ZlayersZlegacy_layersZ	layer_strr   r   r   assert_no_legacy_layers  s    r   c          	   c   s:   t  r0t| ddr0t   dV  W dQ R X ndV  dS )zOpen an `init_scope` if in V2 mode and using the keras graph.

  Arguments:
    layer: The Layer/Model that is currently active.

  Yields:
    None
  Z_keras_styleTN)r   #executing_eagerly_outside_functionsrv   Z
init_scope)Zlayerr   r   r   maybe_init_scope  s
    
r   c           	   o   sL   t dd t| t|  D rBt   dV  W dQ R X ndV  dS )zHReturns graph context manager if any of the inputs is a symbolic tensor.c             s   s   | ]}t |V  qd S )N)rn   )r8   r#   r   r   r   rM     s    z5graph_context_for_symbolic_tensors.<locals>.<genexpr>N)ru   rO   rD   KZ	get_graphZ
as_default)argskwargsr   r   r   "graph_context_for_symbolic_tensors  s    "r   c             C   s>   t  rtt| tjS t t| }|tjkS dS )z'True if the passed dataset is infinite.N)	r   r   r   equalr   ZINFINITEr   Zget_sessionrun)ZdatasetZdataset_sizer   r   r   dataset_is_infinite  s
    r   c             C   s   t | tjr| }nht | tjr&| j}nTt| drLt| jd drL| jd jS t| drvt| drvtj	| j
| j|d}ndS |s|S t|}|j }|rd|d< t||_|S )z?Returns a `TensorSpec` given a single `Tensor` or `TensorSpec`.rs   r   rz   rE   ry   )rE   ry   r   N)r   r   ZTypeSpecr   rt   rz   rq   rs   r   r{   rE   ry   copydeepcopyZ_shaperS   r
   rN   )rr   Zdynamic_batchr   specZdynamic_batch_specrE   r   r   r   get_tensor_spec  s$    


r   c             C   s   dd }t || S )a{  Converts a structure of `Tensor`s to `NumPy` arrays or Python scalar types.

  For each tensor, it calls `tensor.numpy()`. If the result is a scalar value,
  it converts it to a Python type, such as a float or int, by calling
  `result.item()`.

  Numpy scalars are converted, as Python types are often more convenient to deal
  with. This is especially useful for bfloat16 Numpy scalars, which don't
  support as many operations as other Numpy values.

  Args:
    tensors: A structure of tensors.

  Returns:
    `tensors`, but scalar tensors are converted to Python types and non-scalar
    tensors are converted to Numpy arrays.
  c             S   s2   t | tjr.|  }t|dkr*| S |S | S )Nr   )r   r   r"   numpynpndimitem)rr   r5   r   r   r   _to_single_numpy_or_python_type  s    z@to_numpy_or_python_type.<locals>._to_single_numpy_or_python_type)r   rH   )rI   r   r   r   r   to_numpy_or_python_type  s    r   c             C   sT   t | }t|dd}|dkr(td| g }x|D ]}|t| |j q2W t|S )z2Converts the given attrs to tuple non-recursively.Z__attrs_attrs__Nz#%r is not an attrs-decorated class.)typerv   rA   appendr   r'   )attrsrw   fieldsrD   fieldr   r   r   rC     s    
rC   )NNN)N)T)F)FN):r^   
__future__r   r   r   r   r   r   rb   Z'tensorflow.python.data.experimental.opsr   Ztensorflow.python.eagerr   Ztensorflow.python.frameworkr   r   r	   r   r
   r   r   r   Ztensorflow.python.kerasr   r   Ztensorflow.python.opsr   r   r   Ztensorflow.python.utilr   r   r   r    r$   r7   r<   rJ   rV   objectrW   rh   rl   ro   setr(   rn   rx   r|   r}   r   contextmanagerr   r   r   r   r   rC   r   r   r   r   <module>   sZ   

7#
3

- !


