
    BVhI                         d 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 Zd Zdd	Zd
 Z	 	 	 ddZd Zd Zd Zd Zd Zd Zd Zy)z%Utilities used by convolution layers.    N)ops)tensor_shape)backend)	array_opsc                     | dk(  r|dk(  ry|dk(  ry|dk(  ryt        d|      | d	k(  r|dk(  ry
|dk(  ry|dk(  ryt        d|      t        d|       )Nchannels_last   NWC   NHWC   NDHWCzInput rank not supported:channels_firstNCWNCHWNCDHWzInvalid data_format:)
ValueError)data_formatndims     X/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/keras/utils/conv_utils.pyconvert_data_formatr      sy    O#qy		2D99&&qy		2D99
+[
99    c           
      (   t        | t              r| f|z  S 	 t        |       }t        |      |k7  r,t	        d|z   dz   t        |      z   dz   t        |       z         |D ]  }	 t        |        |S # t        $ r- t	        d|z   dz   t        |      z   dz   t        |       z         w xY w# t        t        f$ rW t	        d|z   dz   t        |      z   dz   t        |       z   dz   t        |      z   dz   dz   t        t        |            z         w xY w)a  Transforms a single integer or iterable of 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.

  Returns:
    A tuple of n integers.

  Raises:
    ValueError: If something else than an int/long or iterable thereof was
      passed.
  zThe `z` argument must be a tuple of z integers. Received: z including element z of type )
isinstanceinttuple	TypeErrorr   strlentype)valuennamevalue_tuplesingle_values        r   normalize_tupler'   2   sv   " s8a<F%Lk ;1w~(HH1v 78:=e*E F F# 88L8   Fw~(HH1v 78:=e*E F FF )$ 84*JJQ "9:<?JGJ..03L0ABDNO   #4#567 8 	88s   A2 #B+26B(+A&Dc                     | y|dv sJ ||dz
  |dz
  z  z   }|dv r| }n|dk(  r	| |z
  dz   }n|dk(  r| |z   dz
  }|z   dz
  |z  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>   fullsamevalidcausal   )r*   r,   r+   r)    )input_lengthfilter_sizepaddingstridedilationdilated_filter_sizeoutput_lengths          r   conv_output_lengthr6   Y   s     	7	77	7#{Q8a<&HH"" M' #66:M& #66:M
&
 1
$	//r   c                 p    | y|dv sJ |dk(  r|dz  }n|dk(  rd}n
|dk(  r|dz
  }| dz
  |z  dz  z
  |z   S )	zDetermines 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.   )r5   r0   r1   r2   pads        r   conv_input_lengthr:   s   sj     	-	--	-

C'
C&
/C
!
v	%C	/+	==r   c                    |dv sJ | y||dz
  |dz
  z  z   }|=|dk(  r| |z  t        ||z
  d      z   }|S |dk(  r| |z  ||z   dz
  z
  }|S |dk(  r| |z  }S |dk(  r|dz  }n|dk(  rd}n
|dk(  r|dz
  }| dz
  |z  |z   dz  z
  |z   }|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)   r8   r*   )max)r/   r0   r1   output_paddingr2   r3   lengthr9   s           r   deconv_output_lengthr?      s   ( 
-	--	- {Q8a<@@+ 'f$s;+?'CCf  
- 
F	f$(<q(@Af 
- 
F	f$f 
- &1c	G	c	F	!Oca6)K7!c'AF	-r   c                     | t        j                         } | j                         }|dvrt        dt	        |       z         |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   s     r   normalize_data_formatrC      sP    
]%%'E+;;
 EZ  ! ! 
r   c                     t        | t        t        f      r| S | j                         }|dvrt	        dt        |      z         |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   rB   r   r   )r"   r1   s     r   normalize_paddingrF      sN    e}%LKKM'//
 "$'L1 2 2 
.r   c                 ,   |dvrt        d|z        t        |       }t        |t              r|f|z  }t        |t              r|f|z  }t        |      }t        |      }||k7  s||k7  rt	        d|||fz        t        | |||      }| |z   }t        j                  |t        j                        }	|D 
cg c]  }
t        |
       }}
t        j                  | D ]0  }t        | ||||      }t        j                  | D ]
  }d|	||z   <    2 |	S c c}
w )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+   GPadding type %s not supported. Only "valid" and "same" are implemented.TNumber of strides, input and kernel dimensions must all match. Received: %d, %d, %d.T)NotImplementedErrorr    r   r   r   conv_output_shapenpzerosbool_range	itertoolsproductconv_connected_inputs)input_shapekernel_shapestridesr1   in_dimskernel_dimsstride_dimsoutput_shape
mask_shapemaskdimoutput_axes_ticksoutput_positioninput_axes_ticksinput_positions                  r   conv_kernel_maskra      sS   \ %%
 13:; < < 'c" ?W,Lj7"GL!+G+G{g5
 4!7K89 : : #;gwO,\)*	*bhh	'$-9:cuSz::"**,=> 4o,[,-<gwP#++-=> 4/3d>O+,44 
+ ;s   6Dc              #     K   |dvrt        d|z        t        |       }t        |t              r|f|z  }t        |t              r|f|z  }t        |      }t        |      }	||k7  s|	|k7  rt	        d|	||fz        t        | |||      }
|
D cg c]  }t        |       }}|dk(  rd }n|dk(  rd }nt	        d|z        t        j                  | D ]  }t        | ||||      }t        j                  | D ]r  }t        |      D ]b  }t        |      D ]R  }t        j                   |||       ||
|      	      }t        j                   |||       || |      	      }||f T d t  y
c c}w w)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+   rH   rI   r   c                     |f| z   S Nr.   spatial_idx
filter_idxs     r   <lambda>z"conv_kernel_idxs.<locals>.<lambda>h  s    :-+2M r   r   c                     | |fz   S rd   r.   re   s     r   rh   z"conv_kernel_idxs.<locals>.<lambda>j  s    +2M r   zXData format %s not recognized.`data_format` must be "channels_first" or "channels_last".)multi_indexdimsN)rJ   r    r   r   r   rK   rO   rP   rQ   rR   rL   ravel_multi_index)rS   rT   rU   r1   
filters_infilters_outr   rV   rW   rX   rY   r\   r]   concat_idxsr^   r_   r`   f_inf_outout_idxin_idxs                        r   conv_kernel_idxsrt   !  s    b %%
 13:; < < 'c" ?W,Lj7"GL!+G+G{g5
 4!7K89 : : #;gwO,-9:cuSz::$$MKo%MK
 (*56 7 7 #**,=> "o,[,-<gwP#++-=> 	"
# "$;' 	"E((%ou=|[9;' ''%nd;{J79& &!
!	""	"" ;s   BE6E1!CE6c                    g }t        |       }t        |      D ]l  }t        ||   dz        }||   |z
  }	||   ||   z  }
|dk(  r|
|z  }
t        d|
|z
        }t	        | |   |
|	z         }|j                  t        ||             n |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.
  r8   r+   r   )r    rO   r   r<   minappend)rS   rT   r^   rU   r1   rangesndimsd
left_shiftright_shiftcenterstartends                r   rR   rR     s    N &
k
%< %a\!_q()Jq/J.KQ'!*,F'
f6J&'E
k!nf{2
3C
MM%s#$% 
-r   c           
          t        t        |            }|D cg c]  }t        | |   ||   |||          }}t        |D cg c]  }| |   dk(  rdn||    c}      }|S c c}w c c}w )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.
  r   )rO   r    r6   r   )rS   rT   rU   r1   rk   rz   rY   s          r   rK   rK     s    & 
s< 	!$ 
 Qa'71:N,  >BCKNaq\!_4CE,	
 Ds   A!A&c                 N   t        j                  d      5  | j                  }|| d }|j                         st	        j                  |       | d }|d|  }|j                         st	        j                  |       d|  }t        |t        j                        r)t	        j                  | dg|j                         z         }n.t	        j                  | t	        j                  dg|fd            } ||      }|j                  | d }|j                         st	        j                  |      | d }t	        j                  |t	        j                  ||fd            }	|	j                  | j                  d|  |	j                  | d z          |	cddd       S # 1 sw Y   yxY w)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)r   name_scope_v2shapeis_fully_definedr   r   r   TensorShapereshapeas_listconcat	set_shape)
inpop
inner_rankr   inner_shapebatch_shapeinp_reshapedout_reshapedout_inner_shapeouts
             r   r   r     s   " -. IIE%K'')OOC(*6k*%K'')OOC(:+6k+|778&&sRD;3F3F3H,HIl&&
y"{ 3"=?l l#L"((*6O++-!5zklCo


i&&_'EBOQC MM#))Lj[)CIIzkl,CCD7  s   E;FF$)r-   )Nr   r-   )__doc__rP   numpyrL   tensorflow.python.frameworkr   r   tensorflow.python.kerasr   tensorflow.python.opsr   r   r'   r6   r:   r?   rC   rF   ra   rt   rR   rK   r   r.   r   r   <module>r      sj    ,   + 4 + +:.$N04>6 )- !"#.bL^["|8v:,r   