
    2Vh*                     J    d dl mZ d dl mZ d dlmZ d dlmZ  G d de      Zy)    )backend)ops)KerasTensor)Layerc                   ^     e Zd ZdZ fdZd Zd Zd Zd Zd Z	d Z
d	 Zdd
Z fdZ xZS )MergezGeneric merge layer for elementwise merge functions.

    Used to implement `Sum`, `Average`, etc.

    Args:
        **kwargs: standard layer keyword arguments.
    c                 2    t        |   di | d| _        y )NT )super__init__supports_masking)selfkwargs	__class__s     S/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/layers/merging/base_merge.pyr   zMerge.__init__   s    "6" $    c                     t         N)NotImplementedError)r   inputss     r   _merge_functionzMerge._merge_function   s    !!r   c                    d}d}|D ]  }t        j                  |      }|=t        j                  t        j                  |d      t        j
                  |            }||}|}^|t        j                  |||      }|t        j                  |||      }||t        j                  ||      }nd} |||      } |.t        j                  |dd      }t        j                  ||       |S )a  Merge a set of inputs by applying `op_fn` and ORing the masks.

        We use this for `Minimum` and `Maximum` as it handles the fact that
        there is no identity element. If applicable, the mask obtained by ORing
        all masks is set on the output.

        Args:
            op_fn: binary operation to apply to tensor pair.
            inputs: array of tensors to apply operation on.
        NF)axiskeepdims)
r   get_keras_maskr   broadcast_toexpand_dimsshapewhere
logical_oranyset_keras_mask)r   op_fnr   outputoutput_maskxmasks          r   _apply_merge_op_and_or_maskz!Merge._apply_merge_op_and_or_mask   s      	&A))!,D''b(A399Q<P~"IIdAv.&;:K$;!nn[$?"61%F!	&$ "''+BGK""6;7r   c                    d||fv ryt        |      t        |      k  r| j                  ||      S |s|S t        |dt        |              }t        |t        |       d |      D ]p  \  }}|||j	                  d       |dk(  r|j	                  |       3|dk(  r|j	                  |       J||k7  rt        d| d|       |j	                  |       r 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   z1Inputs have incompatible shapes. Received shapes z and )len!_compute_elemwise_op_output_shapelistzipappend
ValueErrortuple)r   shape1shape2output_shapeijs         r   r-   z'Merge._compute_elemwise_op_output_shape<   s   " FF##[3v;&99&&IIMF>c&k\23F|~.7 	'DAqyAI##D)a##A&a##A&6$++1(%xA  ##A&	' \""r   c                 "   t        |d   t        t        f      st        d| d      t	        |      dk  rt        dt	        |       d|       |D ch c]
  }|s|d    c}d hz
  }t	        |      dkD  rt        d|       |d   d }n|d   dd  }t        dt	        |            D ]$  }||   d }n||   dd  }| j                  ||      }& d |vr-t	        t        t        t        |                  dk(  rd| _	        y d	| _	        y c c}w )
Nr   zJA merge layer should be called on a list of inputs. Received: input_shape=z (not a list of shapes)r+   zGA merge layer should be called on a list of at least 1 input. Received z$ inputs. Full input_shape received: zNCannot merge tensors with different batch sizes. Received tensors with shapes FT)

isinstancer2   r.   r1   r,   ranger-   setmap_reshape_required)r   input_shapesbatch_sizesr5   r6   r   s          r   buildzMerge.buildd   s^   +a.5$-8))45LN  {a,- ...9]<  &16Aqt6$?{a00;}> 
 q>!L&q>!"-Lq#k*+ 	A1~%#Aqr*AAeL	 {"s3s3/D+E'F!'K%*D"%)D"5 7s   DDc                    t        |t        t        f      st        d| d      | j                  rg }t        t        t        j                  |            }d |vrst        |      }|D ]R  }t        j                  |      }t        ||z
        D ]  }t        j                  |d      } |j                  |       T | j                  |      S d}|D ]K  }t        j                  |      }|t        j                  |      }	|	d   }
t        j                  |	dd  t        j                  |
d      g      }t        j                   |t        j"                  |
t        j$                  |	dd        gd            }t        j&                  |d	      }t        j                   ||      }|j                  |       d
}|dkD  rNt        t        d|            dgz   }|j                  t        j&                  ||	             t)        |       d
};|j                  |       N | j                  |      }t        j                  |      }|r|t        j                  |      }t        j                  |      d   }||dz
     }
t        j                  t        j                  |
d      |d |dz
   g      }t        j                   |d|
f      }t        j&                  |d	      }t        j                   ||      }|S |dkD  r5|dz
  gt        t        |dz
              z   }t        j&                  ||	      }|S | j                  |      S )NzEA merge layer should be called on a list of inputs. Received: inputs=z (not a list of tensors)r+   )r   Fr   r   )r+   r   )permT)r9   r.   r2   r1   r=   r<   r   ndimmaxr:   r   r0   r   r   r   concatenatereshapestackprod	transposeprint)r   r   reshaped_inputsinput_ndimsmax_ndimr'   x_ndim_
transposedx_shape
batch_size	new_shapex_transposeddimsyy_ndimy_shapes                    r   callz
Merge.call   s
   &4-0$$*8+CE  !! Os388V45K;& {+ .A XXa[F"8f#45 7OOAA67#**1-	.
 ++O<<
 #
 2A XXa[F~"%))A,%,QZ
$+$7$7$QR[#//*2*NO%	 (+{{II!+SXXgabk-B C%&( (+}}\'O'*{{<'K'..|<%)
!#E!V$45;'..s}}QT/JKd%)
 (..q1?2B ((9! ~"%))A,!$7!3A!6%,VaZ%8
$'OO #
 D '&1* 5%	  KKB
+;<MM!&9KK95   ! &
|d5!3D.EEMM!$7''//r   c                 *   |d   d }n|d   dd  }t        dt        |            D ]$  }||   d }n||   dd  }| j                  ||      }& |D ch c]
  }||d    c}d hz
  }t        |      dk(  rt        |      d   f|z   }|S d|z   }|S c c}w )Nr   r+   r   )r:   r,   r-   r.   )r   r>   r5   r6   r   r?   r@   s          r   compute_output_shapezMerge.compute_output_shape   s    q>!L&q>!"-Lq#k*+ 	A1~%#Aqr*AAeL	 &1BAMqtBdVK{q  -a02\AL  #\1L Cs   BBc                     | j                  |D cg c]  }|j                   c}      }t        d |D              }t        || j                  |      S c c}w )Nc              3   4   K   | ]  }|j                     y wr   )sparse).0r'   s     r   	<genexpr>z,Merge.compute_output_spec.<locals>.<genexpr>   s     5AHH5s   )dtyper_   )r\   r   allr   compute_dtype)r   r   r'   r5   output_sparses        r   compute_output_speczMerge.compute_output_spec   sQ    0061Ja!''1JK5f55 2 2=
 	
 2Ks   Ac                    |y t        |t        t        f      st        d|       t        |t        t        f      st        d|       t	        |      t	        |      k7  r)t        d| dt	        |       d| dt	        |             t        d |D              ry |d   }|dd  D ]  }t        j                  ||      } |S )	Nz(`mask` should be a list. Received: mask=z,`inputs` should be a list. Received: inputs=zLThe lists `inputs` and `mask` should have the same length. Received: inputs=z of length z, and mask=c              3   $   K   | ]  }|d u  
 y wr   r
   )r`   ms     r   ra   z%Merge.compute_mask.<locals>.<genexpr>  s     'QqDy's   r   r+   )r9   r2   r.   r1   r,   r"   r   r!   )r   r   r(   r&   ri   s        r   compute_maskzMerge.compute_mask   s    <$.GvNOO&5$-0>vhG  t9F#$$*8;s6{m Dv[T5  '$''1gab 	9A..a8K	9r   c                      t         |          S r   )r   
get_config)r   r   s    r   rl   zMerge.get_config  s    w!##r   r   )__name__
__module____qualname____doc__r   r   r)   r-   rA   rZ   r\   rf   rj   rl   __classcell__)r   s   @r   r   r      sD    %"#J&#P)*VR0h*
0$ $r   r   N)	keras.srcr   r   %keras.src.backend.common.keras_tensorr   keras.src.layers.layerr   r   r
   r   r   <module>ru      s      = (Q$E Q$r   