a
    SicN                     @   s   d Z ddlZddlZddlm  mZ ddlm	Z	 dd Z
dddZdd
dZdd Zd ddZdd Zdd Zdd Zdd Zdd Zdd Zdd ZdS )!z%Utilities used by convolution layers.    N)backendc                 C   s   | dkr>|dkrdS |dkr dS |dkr,dS t d| d	nN| d
kr||dkrRdS |dkr^dS |dkrjdS t d| d	nt d|  dd S )Nchannels_last   NWC   NHWC   NDHWCzInput rank not supported: z. Expected values are [3, 4, 5]channels_firstNCWNCHWNCDHWzInvalid data_format: z9. Expected values are ["channels_first", "channels_last"])
ValueError)data_formatndim r   R/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/utils/conv_utils.pyconvert_data_format   s.    


r   Fc           	   
   C   s  d| d| d|  }t | tr,| f| }nzt| }W n tyR   t|Y n0 t||krht||D ]H}zt| W ql ttfy   |d| dt| 7 }t|Y ql0 ql|rdd |D }d}nd	d |D }d
}|r|d| d| d7 }t||S )a  Transforms non-negative/positive integer/integers into an integer tuple.

    Args:
      value: The value to validate and convert. Could an int, or any iterable of
        ints.
      n: The size of the tuple to be returned.
      name: The name of the argument being validated, e.g. "strides" or
        "kernel_size". This is only used to format error messages.
      allow_zero: Default to False. A ValueError will raised if zero is received
        and this param is False.

    Returns:
      A tuple of n integers.

    Raises:
      ValueError: If something else than an int/long or iterable thereof or a
      negative value is
        passed.
    zThe `z` argument must be a tuple of z integers. Received: zincluding element z	 of type c                 S   s   h | ]}|d k r|qS r   r   .0vr   r   r   	<setcomp>f       z"normalize_tuple.<locals>.<setcomp>z>= 0c                 S   s   h | ]}|d kr|qS r   r   r   r   r   r   r   i   r   z> 0z including z( that does not satisfy the requirement `z`.)
isinstanceinttuple	TypeErrorr   lentype)	valuenname
allow_zero	error_msgvalue_tuplesingle_valueZunqualified_valuesZreq_msgr   r   r   normalize_tuple9   sF    
r'      c                 C   st   | du rdS |dv sJ ||d |d   }|dv r:| }n*|dkrP| | d }n|dkrd| | d }|| d | S )a:  Determines output length of a convolution given input length.

    Args:
        input_length: integer.
        filter_size: integer.
        padding: one of "same", "valid", "full", "causal"
        stride: integer.
        dilation: dilation rate, integer.

    Returns:
        The output length (integer).
    N>   validcausalsamefullr(   )r+   r*   r)   r,   r   )input_lengthfilter_sizepaddingstridedilationdilated_filter_sizeoutput_lengthr   r   r   conv_output_lengthv   s    r4   c                 C   s`   | du rdS |dv sJ |dkr*|d }n|dkr8d}n|dkrH|d }| d | d|  | S )	a  Determines input length of a convolution given output length.

    Args:
        output_length: integer.
        filter_size: integer.
        padding: one of "same", "valid", "full".
        stride: integer.

    Returns:
        The input length (integer).
    N>   r)   r+   r,   r+      r)   r   r,   r(   r   )r3   r.   r/   r0   padr   r   r   conv_input_length   s    
r7   c                 C   s   |dv sJ | du rdS ||d |d   }|du r|dkrT| | t || d }q|dkrr| | || d  }q|dkr| | }nL|dkr|d }n|dkrd}n|dkr|d }| d | | d|  | }|S )	a  Determines output length of a transposed convolution given input length.

    Args:
        input_length: Integer.
        filter_size: Integer.
        padding: one of `"same"`, `"valid"`, `"full"`.
        output_padding: Integer, amount of padding along the output dimension.
          Can be set to `None` in which case the output length is inferred.
        stride: Integer.
        dilation: Integer.

    Returns:
        The output length (integer).
    >   r)   r+   r,   Nr(   r)   r   r,   r5   r+   )max)r-   r.   r/   output_paddingr0   r1   lengthr6   r   r   r   deconv_output_length   s(    

r;   c                 C   s2   | d u rt  } |  }|dvr.td|  |S )N>   r
   r   zWThe `data_format` argument must be one of "channels_first", "channels_last". Received: )r   image_data_formatlowerr   )r    r   r   r   r   normalize_data_format   s    r>   c                 C   s4   t | ttfr| S |  }|dvr0td| |S )N>   r)   r*   r+   zqThe `padding` argument must be a list/tuple or one of "valid", "same" (or "causal", only for `Conv1D). Received: )r   listr   r=   r   )r    r/   r   r   r   normalize_padding   s    r@   c                 C   s   |dvrt d| dt| }t|tr4|f| }t|trH|f| }t|}t|}||ksh||krtd| d| d| t| |||}| | }t|tj}	dd |D }
t	j
|
 D ]0}t| ||||}t	j
| D ]}d	|	|| < qq|	S )
a  Compute a mask representing the connectivity of a convolution operation.

    Assume a convolution with given parameters is applied to an input having N
    spatial dimensions with `input_shape = (d_in1, ..., d_inN)` to produce an
    output with shape `(d_out1, ..., d_outN)`. This method returns a boolean
    array of shape `(d_in1, ..., d_inN, d_out1, ..., d_outN)` with `True`
    entries indicating pairs of input and output locations that are connected by
    a weight.

    Example:

      >>> input_shape = (4,)
      >>> kernel_shape = (2,)
      >>> strides = (1,)
      >>> padding = "valid"
      >>> conv_kernel_mask(input_shape, kernel_shape, strides, padding)
      array([[ True, False, False],
             [ True,  True, False],
             [False,  True,  True],
             [False, False,  True]])

      where rows and columns correspond to inputs and outputs respectively.


    Args:
      input_shape: tuple of size N: `(d_in1, ..., d_inN)`, spatial shape of the
        input.
      kernel_shape: tuple of size N, spatial shape of the convolutional kernel /
        receptive field.
      strides: tuple of size N, strides along each spatial dimension.
      padding: type of padding, string `"same"` or `"valid"`.
        `"valid"` means no padding. `"same"` results in padding evenly to
        the left/right or up/down of the input such that output has the same
        height/width dimension as the input.

    Returns:
      A boolean 2N-D `np.ndarray` of shape
      `(d_in1, ..., d_inN, d_out1, ..., d_outN)`, where `(d_out1, ..., d_outN)`
      is the spatial shape of the output. `True` entries in the mask represent
      pairs of input-output locations that are connected by a weight.

    Raises:
      ValueError: if `input_shape`, `kernel_shape` and `strides` don't have the
          same number of dimensions.
      NotImplementedError: if `padding` is not in {`"same"`, `"valid"`}.
    >   r)   r+   Padding type 8 not supported. Only "valid" and "same" are implemented.UNumber of strides, input and kernel dimensions must all match. Received: stride_dims=
, in_dims=, kernel_dims=c                 S   s   g | ]}t |qS r   ranger   dimr   r   r   
<listcomp>@  r   z$conv_kernel_mask.<locals>.<listcomp>T)NotImplementedErrorr   r   r   r   conv_output_shapenpzerosbool	itertoolsproductconv_connected_inputs)input_shapekernel_shapestridesr/   in_dimskernel_dimsstride_dimsoutput_shape
mask_shapemaskoutput_axes_ticksoutput_positioninput_axes_ticksinput_positionr   r   r   conv_kernel_mask   sD    /





r`   c              	   c   sd  |dvrt d| dt| }t|tr4|f| }t|trH|f| }t|}t|}	||ksh|	|krtd|	 d| d| t| |||}
dd |
D }|d	krd
d }n"|dkrdd }ntd| dtj| D ]}t| ||||}tj| D ]b}t	|D ]T}t	|D ]D}t
j|||||
|d}t
j||||| |d}||fV  qqqqdS )a'  Yields output-input tuples of indices in a CNN layer.

    The generator iterates over all `(output_idx, input_idx)` tuples, where
    `output_idx` is an integer index in a flattened tensor representing a single
    output image of a convolutional layer that is connected (via the layer
    weights) to the respective single input image at `input_idx`

    Example:

      >>> input_shape = (2, 2)
      >>> kernel_shape = (2, 1)
      >>> strides = (1, 1)
      >>> padding = "valid"
      >>> filters_in = 1
      >>> filters_out = 1
      >>> data_format = "channels_last"
      >>> list(conv_kernel_idxs(input_shape, kernel_shape, strides, padding,
      ...                       filters_in, filters_out, data_format))
      [(0, 0), (0, 2), (1, 1), (1, 3)]

    Args:
      input_shape: tuple of size N: `(d_in1, ..., d_inN)`, spatial shape of the
        input.
      kernel_shape: tuple of size N, spatial shape of the convolutional kernel /
        receptive field.
      strides: tuple of size N, strides along each spatial dimension.
      padding: type of padding, string `"same"` or `"valid"`.
        `"valid"` means no padding. `"same"` results in padding evenly to
        the left/right or up/down of the input such that output has the same
        height/width dimension as the input.
      filters_in: `int`, number if filters in the input to the layer.
      filters_out: `int', number if filters in the output of the layer.
      data_format: string, "channels_first" or "channels_last".

    Yields:
      The next tuple `(output_idx, input_idx)`, where `output_idx` is an integer
      index in a flattened tensor representing a single output image of a
      convolutional layer that is connected (via the layer weights) to the
      respective single input image at `input_idx`.

    Raises:
        ValueError: if `data_format` is neither `"channels_last"` nor
          `"channels_first"`, or if number of strides, input, and kernel number
          of dimensions do not match.

        NotImplementedError: if `padding` is neither `"same"` nor `"valid"`.
    )r+   r)   rA   rB   rC   rD   rE   c                 S   s   g | ]}t |qS r   rF   rH   r   r   r   rJ     r   z$conv_kernel_idxs.<locals>.<listcomp>r
   c                 S   s
   |f|  S Nr   spatial_idx
filter_idxr   r   r   <lambda>  r   z"conv_kernel_idxs.<locals>.<lambda>r   c                 S   s
   | |f S ra   r   rb   r   r   r   re     s   zData format `zK` not recognized.`data_format` must be "channels_first" or "channels_last".)multi_indexdimsN)rK   r   r   r   r   rL   rP   rQ   rR   rG   rM   ravel_multi_index)rS   rT   rU   r/   
filters_infilters_outr   rV   rW   rX   rY   r\   concat_idxsr]   r^   r_   f_inf_outout_idxin_idxr   r   r   conv_kernel_idxsK  sb    8







rp   c                 C   s   g }t | }t|D ]p}t|| d }|| | }	|| ||  }
|dkrT|
|7 }
td|
| }t| | |
|	 }|t|| q|S )a%  Return locations of the input connected to an output position.

    Assume a convolution with given parameters is applied to an input having N
    spatial dimensions with `input_shape = (d_in1, ..., d_inN)`. This method
    returns N ranges specifying the input region that was convolved with the
    kernel to produce the output at position
    `output_position = (p_out1, ..., p_outN)`.

    Example:

      >>> input_shape = (4, 4)
      >>> kernel_shape = (2, 1)
      >>> output_position = (1, 1)
      >>> strides = (1, 1)
      >>> padding = "valid"
      >>> conv_connected_inputs(input_shape, kernel_shape, output_position,
      ...                       strides, padding)
      [range(1, 3), range(1, 2)]

    Args:
      input_shape: tuple of size N: `(d_in1, ..., d_inN)`, spatial shape of the
        input.
      kernel_shape: tuple of size N, spatial shape of the convolutional kernel /
        receptive field.
      output_position: tuple of size N: `(p_out1, ..., p_outN)`, a single
        position in the output of the convolution.
      strides: tuple of size N, strides along each spatial dimension.
      padding: type of padding, string `"same"` or `"valid"`.
        `"valid"` means no padding. `"same"` results in padding evenly to
        the left/right or up/down of the input such that output has the same
        height/width dimension as the input.

    Returns:
      N ranges `[[p_in_left1, ..., p_in_right1], ...,
                [p_in_leftN, ..., p_in_rightN]]` specifying the region in the
      input connected to output_position.
    r5   r)   r   )r   rG   r   r8   minappend)rS   rT   r]   rU   r/   rangesndimsd
left_shiftright_shiftcenterstartendr   r   r   rR     s    (rR   c                    s@   t t} fdd|D t fdd|D S )a  Return the output shape of an N-D convolution.

    Forces dimensions where input is empty (size 0) to remain empty.

    Args:
      input_shape: tuple of size N: `(d_in1, ..., d_inN)`, spatial shape of the
        input.
      kernel_shape: tuple of size N, spatial shape of the convolutional kernel /
        receptive field.
      strides: tuple of size N, strides along each spatial dimension.
      padding: type of padding, string `"same"` or `"valid"`.
        `"valid"` means no padding. `"same"` results in padding evenly to
        the left/right or up/down of the input such that output has the same
        height/width dimension as the input.

    Returns:
      tuple of size N: `(d_out1, ..., d_outN)`, spatial shape of the output.
    c                    s&   g | ]}t  | | | qS r   )r4   r   ru   )rS   rT   r/   rU   r   r   rJ     s   z%conv_output_shape.<locals>.<listcomp>c                    s$   g | ]} | d krd n| qS r   r   r{   )rS   rY   r   r   rJ     r   )rG   r   r   )rS   rT   rU   r/   rg   r   )rS   rT   rY   r/   rU   r   rL     s    rL   c           
      C   sD  t d" | j}|| d }| s>t | | d }|d|  }| sht | d|  }t|t jrt | dg|  }nt | t jdg|fdd}||}|j| d }| st || d }t |t j||fdd}	|		| jd|  |	j| d   |	W  d   S 1 s60    Y  dS )a.  Returns `unsqueeze_batch(op(squeeze_batch(inp)))`.

    Where `squeeze_batch` reshapes `inp` to shape
    `[prod(inp.shape[:-inner_rank])] + inp.shape[-inner_rank:]`
    and `unsqueeze_batch` does the reverse reshape but on the output.

    Args:
      inp: A tensor with dims `batch_shape + inner_shape` where `inner_shape`
        is length `inner_rank`.
      op: A callable that takes a single input tensor and returns a single.
        output tensor.
      inner_rank: A python integer.

    Returns:
      `unsqueeze_batch_op(squeeze_batch(inp))`.
    squeeze_batch_dimsN)axis)
tf
name_scopeshapeis_fully_definedr   TensorShapereshapeas_listconcat	set_shape)
inpop
inner_rankr   inner_shapebatch_shapeinp_reshapedout_reshapedout_inner_shapeoutr   r   r   r|     s,    &r|   )F)r(   )Nr   r(   )__doc__rP   numpyrM   tensorflow.compat.v2compatv2r   kerasr   r   r'   r4   r7   r;   r>   r@   r`   rp   rR   rL   r|   r   r   r   r   <module>   s&    
=
   
4Vr<