B
    ӻd~                 @   s  d 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 G d
d deZedG dd deZedG dd deZedG dd deZedG dd deZedG dd deZedG dd deZedG dd  d eZed!G d"d# d#eZed$d%d& Zed'd(d) Zed*d+d, Zed-d.d/ Zed0d1d2 Zed3d4d5 Zed6d?d8d9Zed:d@d<d=Zd>S )Az.Layers that can merge several inputs into one.    )backend)base_layer_utils)Layer)tf_utils)	array_ops)math_ops)nn)keras_exportc                   s^   e Zd ZdZ fddZdd Zdd Zejdd	 Z	d
d Z
ejdd ZdddZ  ZS )_MergezcGeneric merge layer for elementwise merge functions.

  Used to implement `Sum`, `Average`, etc.
  c                s   t t| jf | d| _dS )z[Intializes a Merge layer.

    Args:
      **kwargs: standard layer keyword arguments.
    TN)superr
   __init__supports_masking)selfkwargs)	__class__ V/var/www/html/venv/lib/python3.7/site-packages/tensorflow/python/keras/layers/merge.pyr   #   s    z_Merge.__init__c             C   s   t d S )N)NotImplementedError)r   inputsr   r   r   _merge_function,   s    z_Merge._merge_functionc             C   s   d||gkrdS t |t |k r,| ||S |s4|S t|dt |  }xt|t | d |D ]z\}}|dks||dkr|d qd|dkr|| qd|dkr|| qd||krtdt| d t| || qdW t|S )a  Computes the shape of the resultant of an elementwise operation.

    Args:
        shape1: tuple or None. Shape of the first tensor
        shape2: tuple or None. Shape of the second tensor

    Returns:
        expected output shape when an element-wise operation is
        carried out on 2 tensors with shapes shape1 and shape2.
        tuple or None.

    Raises:
        ValueError: if shape1 and shape2 are not compatible for
            element-wise operations.
    N   z5Operands could not be broadcast together with shapes  )len!_compute_elemwise_op_output_shapelistzipappend
ValueErrorstrtuple)r   shape1shape2output_shapeijr   r   r   r   /   s&    "z(_Merge._compute_elemwise_op_output_shapec             C   s  t |d tstdt|dk r:tdtt| d dd |D d h }t|dkrjtd	t| |d d kr|d }n|d dd  }xDtdt|D ]2}|| d krd }n|| dd  }| ||}qW d |krtttt|dkrd
| _	nd| _	d S )Nr   z3A merge layer should be called on a list of inputs.   zCA merge layer should be called on a list of at least 2 inputs. Got z inputs.c             S   s   h | ]}|r|d  qS )r   r   ).0sr   r   r   	<setcomp>^   s    z_Merge.build.<locals>.<setcomp>r   zLCan not merge tensors with different batch sizes. Got tensors with shapes : FT)

isinstancer   r   r   r   ranger   setmap_reshape_required)r   input_shapebatch_sizesr"   r#   shaper   r   r   buildU   s*    z_Merge.buildc             C   s\  t |ttfstd| jrNg }tttj|}d |krt|}xD|D ]<}t|}x"t	|| D ]}t
j|dd}qdW || qHW | |S d}x|D ]}t|}|d kr8t
|}	|	d }
t|	dd  t
j|
ddg}t
|t
j|
t|	dd  gdd}t
j|dd}t
||}|| d	}q|dkrptt	d|dg }|t
j||d d	}q|| qW | |}t|}|rH|d krt
|}t
|d }||d  }
tt
j|
dd|d |d  g}t
|d|
f}t
j|dd}t
||}n2|dkrH|d gtt	|d  }t
j||d}|S n
| |S d S )
Nz3A merge layer should be called on a list of inputs.r   )axisFr   )r   r   )ZpermT)r)   r   r   r   r-   r,   r   ndimmaxr*   r   expand_dimsr   r   r0   concatenateZreshapestackr   Zreduce_prodZ	transpose)r   r   Zreshaped_inputsZinput_ndimsZmax_ndimxZx_ndim_Z
transposedZx_shapeZ
batch_sizeZ	new_shapeZx_transposedZdimsyZy_ndimZy_shaper   r   r   callt   sh    













 
z_Merge.callc             C   s   |d d krd }n|d dd  }xDt dt|D ]2}|| d krHd }n|| dd  }| ||}q2W dd |D d h }t|dkrt|d f| }nd| }|S )Nr   r   c             S   s   h | ]}|d k	r|d qS )Nr   r   )r&   r'   r   r   r   r(      s    z._Merge.compute_output_shape.<locals>.<setcomp>)N)r*   r   r   r   )r   r.   r"   r#   r0   r/   r   r   r   compute_output_shape   s    z_Merge.compute_output_shapeNc             C   s   |d krd S t |ttfs"tdt |ttfs8tdt|t|krPtdtdd |D rfd S dd |D }tjtj|dd	dd
dS )Nz`mask` should be a list.z`inputs` should be a list.z:The lists `inputs` and `mask` should have the same length.c             s   s   | ]}|d kV  qd S )Nr   )r&   mr   r   r   	<genexpr>   s    z&_Merge.compute_mask.<locals>.<genexpr>c             S   s"   g | ]}|d k	rt j|ddqS )Nr   )r2   )r   r6   )r&   r>   r   r   r   
<listcomp>   s    z'_Merge.compute_mask.<locals>.<listcomp>r   )r2   F)r2   keepdims)r)   r   r   r   r   allr   r7   )r   r   maskmasksr   r   r   compute_mask   s    z_Merge.compute_mask)N)__name__
__module____qualname____doc__r   r   r   r   shape_type_conversionr1   r<   r=   rE   __classcell__r   r   )r   r   r
      s   	&Ar
   zkeras.layers.Addc               @   s   e Zd ZdZdd ZdS )AddaK  Layer that adds a list of inputs.

  It takes as input a list of tensors,
  all of the same shape, and returns
  a single tensor (also of the same shape).

  Examples:

  >>> input_shape = (2, 3, 4)
  >>> x1 = tf.random.normal(input_shape)
  >>> x2 = tf.random.normal(input_shape)
  >>> y = tf.keras.layers.Add()([x1, x2])
  >>> print(y.shape)
  (2, 3, 4)

  Used in a functional model:

  >>> input1 = tf.keras.layers.Input(shape=(16,))
  >>> x1 = tf.keras.layers.Dense(8, activation='relu')(input1)
  >>> input2 = tf.keras.layers.Input(shape=(32,))
  >>> x2 = tf.keras.layers.Dense(8, activation='relu')(input2)
  >>> # equivalent to `added = tf.keras.layers.add([x1, x2])`
  >>> added = tf.keras.layers.Add()([x1, x2])
  >>> out = tf.keras.layers.Dense(4)(added)
  >>> model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)

  c             C   s0   |d }x"t dt|D ]}||| 7 }qW |S )Nr   r   )r*   r   )r   r   outputr#   r   r   r   r      s    zAdd._merge_functionN)rF   rG   rH   rI   r   r   r   r   r   rL      s   rL   zkeras.layers.Subtractc                   s.   e Zd ZdZej fddZdd Z  ZS )Subtracta  Layer that subtracts two inputs.

  It takes as input a list of tensors of size 2,
  both of the same shape, and returns a single tensor, (inputs[0] - inputs[1]),
  also of the same shape.

  Examples:

  ```python
      import keras

      input1 = keras.layers.Input(shape=(16,))
      x1 = keras.layers.Dense(8, activation='relu')(input1)
      input2 = keras.layers.Input(shape=(32,))
      x2 = keras.layers.Dense(8, activation='relu')(input2)
      # Equivalent to subtracted = keras.layers.subtract([x1, x2])
      subtracted = keras.layers.Subtract()([x1, x2])

      out = keras.layers.Dense(4)(subtracted)
      model = keras.models.Model(inputs=[input1, input2], outputs=out)
  ```
  c                s(   t t| | t|dkr$tdd S )Nr%   z7A `Subtract` layer should be called on exactly 2 inputs)r   rN   r1   r   r   )r   r.   )r   r   r   r1     s    zSubtract.buildc             C   s$   t |dkrtd|d |d  S )Nr%   z7A `Subtract` layer should be called on exactly 2 inputsr   r   )r   r   )r   r   r   r   r   r     s    zSubtract._merge_function)	rF   rG   rH   rI   r   rJ   r1   r   rK   r   r   )r   r   rN      s   rN   zkeras.layers.Multiplyc               @   s   e Zd ZdZdd ZdS )Multiplya  Layer that multiplies (element-wise) a list of inputs.

  It takes as input a list of tensors, all of the same shape, and returns
  a single tensor (also of the same shape).

  >>> tf.keras.layers.Multiply()([np.arange(5).reshape(5, 1),
  ...                             np.arange(5, 10).reshape(5, 1)])
  <tf.Tensor: shape=(5, 1), dtype=int64, numpy=
  array([[ 0],
       [ 6],
       [14],
       [24],
       [36]])>

  >>> x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
  >>> x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
  >>> multiplied = tf.keras.layers.Multiply()([x1, x2])
  >>> multiplied.shape
  TensorShape([5, 8])
  c             C   s0   |d }x"t dt|D ]}|||  }qW |S )Nr   r   )r*   r   )r   r   rM   r#   r   r   r   r   <  s    zMultiply._merge_functionN)rF   rG   rH   rI   r   r   r   r   r   rO   %  s   rO   zkeras.layers.Averagec               @   s   e Zd ZdZdd ZdS )Averageay  Layer that averages a list of inputs element-wise.

  It takes as input a list of tensors, all of the same shape, and returns
  a single tensor (also of the same shape).

  Example:

  >>> x1 = np.ones((2, 2))
  >>> x2 = np.zeros((2, 2))
  >>> y = tf.keras.layers.Average()([x1, x2])
  >>> y.numpy().tolist()
  [[0.5, 0.5], [0.5, 0.5]]

  Usage in a functional model:

  >>> input1 = tf.keras.layers.Input(shape=(16,))
  >>> x1 = tf.keras.layers.Dense(8, activation='relu')(input1)
  >>> input2 = tf.keras.layers.Input(shape=(32,))
  >>> x2 = tf.keras.layers.Dense(8, activation='relu')(input2)
  >>> avg = tf.keras.layers.Average()([x1, x2])
  >>> out = tf.keras.layers.Dense(4)(avg)
  >>> model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)

  Raises:
    ValueError: If there is a shape mismatch between the inputs and the shapes
      cannot be broadcasted to match.
  c             C   s8   |d }x"t dt|D ]}||| 7 }qW |t| S )Nr   r   )r*   r   )r   r   rM   r#   r   r   r   r   a  s    zAverage._merge_functionN)rF   rG   rH   rI   r   r   r   r   r   rP   C  s   rP   zkeras.layers.Maximumc               @   s   e Zd ZdZdd ZdS )Maximuma  Layer that computes the maximum (element-wise) a list of inputs.

  It takes as input a list of tensors, all of the same shape, and returns
  a single tensor (also of the same shape).

  >>> tf.keras.layers.Maximum()([np.arange(5).reshape(5, 1),
  ...                            np.arange(5, 10).reshape(5, 1)])
  <tf.Tensor: shape=(5, 1), dtype=int64, numpy=
  array([[5],
       [6],
       [7],
       [8],
       [9]])>

  >>> x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
  >>> x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
  >>> maxed = tf.keras.layers.Maximum()([x1, x2])
  >>> maxed.shape
  TensorShape([5, 8])
  c             C   s4   |d }x&t dt|D ]}t||| }qW |S )Nr   r   )r*   r   r   maximum)r   r   rM   r#   r   r   r   r     s    zMaximum._merge_functionN)rF   rG   rH   rI   r   r   r   r   r   rQ   h  s   rQ   zkeras.layers.Minimumc               @   s   e Zd ZdZdd ZdS )Minimuma  Layer that computes the minimum (element-wise) a list of inputs.

  It takes as input a list of tensors, all of the same shape, and returns
  a single tensor (also of the same shape).

  >>> tf.keras.layers.Minimum()([np.arange(5).reshape(5, 1),
  ...                            np.arange(5, 10).reshape(5, 1)])
  <tf.Tensor: shape=(5, 1), dtype=int64, numpy=
  array([[0],
       [1],
       [2],
       [3],
       [4]])>

  >>> x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
  >>> x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
  >>> minned = tf.keras.layers.Minimum()([x1, x2])
  >>> minned.shape
  TensorShape([5, 8])
  c             C   s4   |d }x&t dt|D ]}t||| }qW |S )Nr   r   )r*   r   r   minimum)r   r   rM   r#   r   r   r   r     s    zMinimum._merge_functionN)rF   rG   rH   rI   r   r   r   r   r   rS     s   rS   zkeras.layers.Concatenatec                   s\   e Zd ZdZd fdd	Zejdd Zdd Zejd	d
 Z	dddZ
 fddZ  ZS )Concatenatea  Layer that concatenates a list of inputs.

  It takes as input a list of tensors, all of the same shape except
  for the concatenation axis, and returns a single tensor that is the
  concatenation of all inputs.

  >>> x = np.arange(20).reshape(2, 2, 5)
  >>> print(x)
  [[[ 0  1  2  3  4]
    [ 5  6  7  8  9]]
   [[10 11 12 13 14]
    [15 16 17 18 19]]]
  >>> y = np.arange(20, 30).reshape(2, 1, 5)
  >>> print(y)
  [[[20 21 22 23 24]]
   [[25 26 27 28 29]]]
  >>> tf.keras.layers.Concatenate(axis=1)([x, y])
  <tf.Tensor: shape=(2, 3, 5), dtype=int64, numpy=
  array([[[ 0,  1,  2,  3,  4],
          [ 5,  6,  7,  8,  9],
          [20, 21, 22, 23, 24]],
         [[10, 11, 12, 13, 14],
          [15, 16, 17, 18, 19],
          [25, 26, 27, 28, 29]]])>

  >>> x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
  >>> x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
  >>> concatted = tf.keras.layers.Concatenate()([x1, x2])
  >>> concatted.shape
  TensorShape([5, 16])

  r3   c                s(   t t| jf | || _d| _d| _dS )a  Instantiates a Concatenate layer.

    >>> x = np.arange(20).reshape(2, 2, 5)
    >>> print(x)
    [[[ 0  1  2  3  4]
      [ 5  6  7  8  9]]
     [[10 11 12 13 14]
      [15 16 17 18 19]]]
    >>> y = np.arange(20, 30).reshape(2, 1, 5)
    >>> print(y)
    [[[20 21 22 23 24]]
     [[25 26 27 28 29]]]
    >>> tf.keras.layers.Concatenate(axis=1)([x, y])
    <tf.Tensor: shape=(2, 3, 5), dtype=int64, numpy=
    array([[[ 0,  1,  2,  3,  4],
            [ 5,  6,  7,  8,  9],
            [20, 21, 22, 23, 24]],
           [[10, 11, 12, 13, 14],
            [15, 16, 17, 18, 19],
            [25, 26, 27, 28, 29]]])>

    Args:
      axis: Axis along which to concatenate.
      **kwargs: standard layer keyword arguments.
    TFN)r   rU   r   r2   r   r-   )r   r2   r   )r   r   r   r     s    zConcatenate.__init__c       	         s   t |d trt|dk r"tdtdd |D r8d S dd |D }t }x2tt|D ]"}|| | j= |t||  qZW t|dkrd| }td	d |D }t|dkrt||\}x:t|D ]. t fd
d|D }t|dkrt|qW d S )Nr   r   zEA `Concatenate` layer should be called on a list of at least 1 input.c             s   s   | ]}|d kV  qd S )Nr   )r&   r0   r   r   r   r?     s    z$Concatenate.build.<locals>.<genexpr>c             S   s   g | ]}t |qS r   )r   )r&   r0   r   r   r   r@     s    z%Concatenate.build.<locals>.<listcomp>zlA `Concatenate` layer requires inputs with matching shapes except for the concat axis. Got inputs shapes: %sc             s   s   | ]}t |V  qd S )N)r   )r&   r0   r   r   r   r?     s    c             3   s"   | ]}|  d k	r|  V  qd S )Nr   )r&   r0   )r2   r   r   r?     s    )	r)   r   r   r   rB   r+   r*   r2   add)	r   r.   Zreduced_inputs_shapesZ	shape_setr#   err_msgZranksZrankZunique_dimsr   )r2   r   r1     s*    zConcatenate.buildc             C   s   t j|| jdS )N)r2   )r   r7   r2   )r   r   r   r   r   r     s    zConcatenate._merge_functionc             C   s   t |ttfr t |d ttfs(td|}t|d }xT|dd  D ]D}|| j d ksf|| j d krrd || j< P || j  || j 7  < qFW t|S )Nr   z;A `Concatenate` layer should be called on a list of inputs.r   )r)   r   r   r   r2   )r   r.   Zinput_shapesr"   r0   r   r   r   r=   	  s    
z Concatenate.compute_output_shapeNc             C   s   |d krd S t |ttfs"tdt |ttfs8tdt|t|krPtdtdd |D rfd S g }xht||D ]Z\}}|d kr|tj	|dd qvt
|t
|k r|tj|dd	 qv|| qvW t
j|| jd	}t
j|dd
dS )Nz`mask` should be a list.z`inputs` should be a list.z:The lists `inputs` and `mask` should have the same length.c             s   s   | ]}|d kV  qd S )Nr   )r&   r>   r   r   r   r?   %  s    z+Concatenate.compute_mask.<locals>.<genexpr>bool)Zdtyper3   )r2   F)r2   rA   )r)   r   r   r   r   rB   r   r   r   Z	ones_liker   r4   r6   r7   r2   )r   r   rC   rD   Zinput_iZmask_iZconcatenatedr   r   r   rE     s&    zConcatenate.compute_maskc                s4   d| j i}tt|  }tt| t|  S )Nr2   )r2   r   rU   
get_configdictr   items)r   configbase_config)r   r   r   rY   7  s    
zConcatenate.get_config)r3   )N)rF   rG   rH   rI   r   r   rJ   r1   r   r=   rE   rY   rK   r   r   )r   r   rU     s   ! 
rU   zkeras.layers.Dotc                   s\   e Zd ZdZd fdd	Zejdd Zdd Zejd	d
 Z	dddZ
 fddZ  ZS )Dotaj  Layer that computes a dot product between samples in two tensors.

  E.g. if applied to a list of two tensors `a` and `b` of shape
  `(batch_size, n)`, the output will be a tensor of shape `(batch_size, 1)`
  where each entry `i` will be the dot product between
  `a[i]` and `b[i]`.

  >>> x = np.arange(10).reshape(1, 5, 2)
  >>> print(x)
  [[[0 1]
    [2 3]
    [4 5]
    [6 7]
    [8 9]]]
  >>> y = np.arange(10, 20).reshape(1, 2, 5)
  >>> print(y)
  [[[10 11 12 13 14]
    [15 16 17 18 19]]]
  >>> tf.keras.layers.Dot(axes=(1, 2))([x, y])
  <tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
  array([[[260, 360],
          [320, 445]]])>

  >>> x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
  >>> x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
  >>> dotted = tf.keras.layers.Dot(axes=1)([x1, x2])
  >>> dotted.shape
  TensorShape([5, 1])


  Fc                s   t t| jf | t|tsjt|ttfs2tdt|dkrFt	dt|d trbt|d tsjt	d|| _
|| _d| _d| _d	S )
aR  Initializes a layer that computes the element-wise dot product.

      >>> x = np.arange(10).reshape(1, 5, 2)
      >>> print(x)
      [[[0 1]
        [2 3]
        [4 5]
        [6 7]
        [8 9]]]
      >>> y = np.arange(10, 20).reshape(1, 2, 5)
      >>> print(y)
      [[[10 11 12 13 14]
        [15 16 17 18 19]]]
      >>> tf.keras.layers.Dot(axes=(1, 2))([x, y])
      <tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
      array([[[260, 360],
              [320, 445]]])>

    Args:
      axes: Integer or tuple of integers,
        axis or axes along which to take the dot product. If a tuple, should
        be two integers corresponding to the desired axis from the first input
        and the desired axis from the second input, respectively. Note that the
        size of the two selected axes must match.
      normalize: Whether to L2-normalize samples along the
        dot product axis before taking the dot product.
        If set to True, then the output of the dot product
        is the cosine proximity between the two samples.
      **kwargs: Standard layer keyword arguments.
    z5Invalid type for `axes` - should be a list or an int.r%   z8Invalid format for `axes` - should contain two elements.r   r   z:Invalid format for `axes` - list elements should be "int".TFN)r   r^   r   r)   intr   r   	TypeErrorr   r   axes	normalizer   r-   )r   ra   rb   r   )r   r   r   r   a  s    
zDot.__init__c             C   s   t |d trt|dkr"td|d }|d }|d ksB|d krFd S t | jtr| jdk rz| jt| | jt| g}q| jgd }n| j}||d  ||d  krtd||d  ||d  f d||f  d|d |d f  d S )Nr   r%   z5A `Dot` layer should be called on a list of 2 inputs.r   z$Dimension incompatibility %s != %s. zLayer shapes: %s, %s. zChosen axes: %s, %s)r)   r   r   r   ra   r_   )r   r.   r    r!   ra   r   r   r   r1     s    
&z	Dot.buildc             C   s  t || j t|dkr"td|d }|d }t| jtrx| jdk rj| jt	| | jt	| g}q| jgd }nZg }xTt
t| jD ]B}| j| dk r|| j| t	||   q|| j|  qW | jrtj||d d}tj||d d}t|||}|S )Nr%   z2A `Dot` layer should be called on exactly 2 inputsr   r   )r2   )r   Zno_ragged_supportnamer   r   r)   ra   r_   r   r4   r*   r   rb   r   Zl2_normalizeZ	batch_dot)r   r   x1Zx2ra   r#   rM   r   r   r   r     s&    
" zDot._merge_functionc             C   s   t |ttfrt|dkr"tdt|d }t|d }t | jtr|| jdk rn| jt| | jt| g}q| jgd }n| j}||d  ||d  |d || }t|dkr|dg7 }t|S )Nr%   z5A `Dot` layer should be called on a list of 2 inputs.r   r   )r)   r   r   r   r   ra   r_   pop)r   r.   r    r!   ra   r"   r   r   r   r=     s     


zDot.compute_output_shapeNc             C   s   d S )Nr   )r   r   rC   r   r   r   rE     s    zDot.compute_maskc                s8   | j | jd}tt|  }tt| t|  S )N)ra   rb   )ra   rb   r   r^   rY   rZ   r   r[   )r   r\   r]   )r   r   r   rY     s    
zDot.get_config)F)N)rF   rG   rH   rI   r   r   rJ   r1   r   r=   rE   rY   rK   r   r   )r   r   r^   ?  s    /
r^   zkeras.layers.addc             K   s   t f || S )a  Functional interface to the `tf.keras.layers.Add` layer.

  Args:
      inputs: A list of input tensors (at least 2) with the same shape.
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor as the sum of the inputs. It has the same shape as the inputs.

  Examples:

  >>> input_shape = (2, 3, 4)
  >>> x1 = tf.random.normal(input_shape)
  >>> x2 = tf.random.normal(input_shape)
  >>> y = tf.keras.layers.add([x1, x2])
  >>> print(y.shape)
  (2, 3, 4)

  Used in a functional model:

  >>> input1 = tf.keras.layers.Input(shape=(16,))
  >>> x1 = tf.keras.layers.Dense(8, activation='relu')(input1)
  >>> input2 = tf.keras.layers.Input(shape=(32,))
  >>> x2 = tf.keras.layers.Dense(8, activation='relu')(input2)
  >>> added = tf.keras.layers.add([x1, x2])
  >>> out = tf.keras.layers.Dense(4)(added)
  >>> model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)

  )rL   )r   r   r   r   r   rV     s    rV   zkeras.layers.subtractc             K   s   t f || S )a  Functional interface to the `Subtract` layer.

  Args:
      inputs: A list of input tensors (exactly 2).
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor, the difference of the inputs.

  Examples:

  ```python
      import keras

      input1 = keras.layers.Input(shape=(16,))
      x1 = keras.layers.Dense(8, activation='relu')(input1)
      input2 = keras.layers.Input(shape=(32,))
      x2 = keras.layers.Dense(8, activation='relu')(input2)
      subtracted = keras.layers.subtract([x1, x2])

      out = keras.layers.Dense(4)(subtracted)
      model = keras.models.Model(inputs=[input1, input2], outputs=out)
  ```
  )rN   )r   r   r   r   r   subtract  s    rf   zkeras.layers.multiplyc             K   s   t f || S )an  Functional interface to the `Multiply` layer.

  Example:

  >>> x1 = np.arange(3.0)
  >>> x2 = np.arange(3.0)
  >>> tf.keras.layers.multiply([x1, x2])
  <tf.Tensor: shape=(3,), dtype=float32, numpy=array([0., 1., 4.], ...)>

  Usage in a functional model:

  >>> input1 = tf.keras.layers.Input(shape=(16,))
  >>> x1 = tf.keras.layers.Dense(8, activation='relu')(input1) #shape=(None, 8)
  >>> input2 = tf.keras.layers.Input(shape=(32,))
  >>> x2 = tf.keras.layers.Dense(8, activation='relu')(input2) #shape=(None, 8)
  >>> out = tf.keras.layers.multiply([x1,x2]) #shape=(None, 8)
  >>> out = tf.keras.layers.Dense(4)(out)
  >>> model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)

  Args:
      inputs: A list of input tensors (at least 2).
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor, the element-wise product of the inputs.
  )rO   )r   r   r   r   r   multiply   s    rg   zkeras.layers.averagec             K   s   t f || S )a  Functional interface to the `tf.keras.layers.Average` layer.

  Example:

  >>> x1 = np.ones((2, 2))
  >>> x2 = np.zeros((2, 2))
  >>> y = tf.keras.layers.Average()([x1, x2])
  >>> y.numpy().tolist()
  [[0.5, 0.5], [0.5, 0.5]]

  Usage in a functional model:

  >>> input1 = tf.keras.layers.Input(shape=(16,))
  >>> x1 = tf.keras.layers.Dense(8, activation='relu')(input1)
  >>> input2 = tf.keras.layers.Input(shape=(32,))
  >>> x2 = tf.keras.layers.Dense(8, activation='relu')(input2)
  >>> avg = tf.keras.layers.Average()([x1, x2])
  >>> out = tf.keras.layers.Dense(4)(avg)
  >>> model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)

  Args:
      inputs: A list of input tensors (at least 2).
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor, the average of the inputs.

  Raises:
    ValueError: If there is a shape mismatch between the inputs and the shapes
      cannot be broadcasted to match.
  )rP   )r   r   r   r   r   average?  s    !rh   zkeras.layers.maximumc             K   s   t f || S )a}  Functional interface to compute maximum (element-wise) list of `inputs`.

  This is equivalent to the `tf.keras.layers.Maximum` layer.

  For example:

  ```python
  input1 = tf.keras.layers.Input(shape=(16,))
  x1 = tf.keras.layers.Dense(8, activation='relu')(input1) #shape=(None, 8)
  input2 = tf.keras.layers.Input(shape=(32,))
  x2 = tf.keras.layers.Dense(8, activation='relu')(input2) #shape=(None, 8)
  max_inp=tf.keras.layers.maximum([x1,x2]) #shape=(None, 8)
  out = tf.keras.layers.Dense(4)(max_inp)
  model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)
  ```

  Args:
      inputs: A list of input tensors (at least 2) of same shape.
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor (of same shape as input tensor) with the element-wise
      maximum of the inputs.

  Raises:
      ValueError: If input tensors are of different shape.
  )rQ   )r   r   r   r   r   rR   c  s    rR   zkeras.layers.minimumc             K   s   t f || S )zFunctional interface to the `Minimum` layer.

  Args:
      inputs: A list of input tensors (at least 2).
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor, the element-wise minimum of the inputs.
  )rS   )r   r   r   r   r   rT     s    rT   zkeras.layers.concatenater3   c             K   s   t f d|i|| S )aO  Functional interface to the `Concatenate` layer.

  >>> x = np.arange(20).reshape(2, 2, 5)
  >>> print(x)
  [[[ 0  1  2  3  4]
    [ 5  6  7  8  9]]
   [[10 11 12 13 14]
    [15 16 17 18 19]]]
  >>> y = np.arange(20, 30).reshape(2, 1, 5)
  >>> print(y)
  [[[20 21 22 23 24]]
   [[25 26 27 28 29]]]
  >>> tf.keras.layers.concatenate([x, y],
  ...                             axis=1)
  <tf.Tensor: shape=(2, 3, 5), dtype=int64, numpy=
  array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [20, 21, 22, 23, 24]],
       [[10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [25, 26, 27, 28, 29]]])>

  Args:
      inputs: A list of input tensors (at least 2).
      axis: Concatenation axis.
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor, the concatenation of the inputs alongside axis `axis`.
  r2   )rU   )r   r2   r   r   r   r   r7     s     r7   zkeras.layers.dotFc             K   s   t f ||d|| S )a9  Functional interface to the `Dot` layer.

  Args:
      inputs: A list of input tensors (at least 2).
      axes: Integer or tuple of integers,
          axis or axes along which to take the dot product.
      normalize: Whether to L2-normalize samples along the
          dot product axis before taking the dot product.
          If set to True, then the output of the dot product
          is the cosine proximity between the two samples.
      **kwargs: Standard layer keyword arguments.

  Returns:
      A tensor, the dot product of the samples from the inputs.
  )ra   rb   )r^   )r   ra   rb   r   r   r   r   dot  s    ri   N)r3   )F) rI   Ztensorflow.python.kerasr   Ztensorflow.python.keras.enginer   Z)tensorflow.python.keras.engine.base_layerr   Ztensorflow.python.keras.utilsr   Ztensorflow.python.opsr   r   r   Z tensorflow.python.util.tf_exportr	   r
   rL   rN   rO   rP   rQ   rS   rU   r^   rV   rf   rg   rh   rR   rT   r7   ri   r   r   r   r   <module>   sL    =$&$  ""$ "