o
    2h*                     @   sD   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dS )    )backend)ops)KerasTensor)Layerc                       sn   e Zd ZdZ f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ddZ fddZ  ZS )MergezGeneric merge layer for elementwise merge functions.

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

    Args:
        **kwargs: standard layer keyword arguments.
    c                    s   t  jdi | d| _d S )NT )super__init__supports_masking)selfkwargs	__class__r   ^/var/www/html/chatgem/venv/lib/python3.10/site-packages/keras/src/layers/merging/base_merge.pyr	      s   
zMerge.__init__c                 C   s   t N)NotImplementedError)r   inputsr   r   r   _merge_function   s   zMerge._merge_functionc                 C   s   d}d}|D ]M}t |}|durtt|dt|}|du r'|}|}q|dur2t|||}|dur=t|||}|durL|durLt||}nd}|||}q|durftj|ddd}t 	|| |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maskr   r   r   _apply_merge_op_and_or_mask   s,   
z!Merge._apply_merge_op_and_or_maskc                 C   s   d||fv rdS t |t |k r| ||S |s|S t|dt |  }t|t | d |D ]9\}}|du s=|du rC|d q1|dkrM|| q1|dkrW|| q1||kretd| d| || q1t|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jr   r   r   r'   <   s0    z'Merge._compute_elemwise_op_output_shapec                 C   s
  t |d ttfstd| dt|dk r#tdt| d| dd |D d h }t|dkr:td	| |d d u rCd }n|d dd  }tdt|D ]}|| d u r]d }n|| dd  }| ||}qRd |vrtttt|dkrd
| _	d S d| _	d S )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: c                 S   s   h | ]}|r|d  qS )r   r   .0sr   r   r   	<setcomp>s   s    zMerge.build.<locals>.<setcomp>zNCannot merge tensors with different batch sizes. Received tensors with shapes FT)

isinstancer,   r(   r+   r&   ranger'   setmap_reshape_required)r   input_shapebatch_sizesr/   r0   r   r   r   r   buildd   sD   

zMerge.buildc                 C   sX  t |ttfstd| d| jr'g }tttj|}d |vrIt|}|D ]}t|}t	|| D ]	}tj
|dd}q4|| q'| |S d}|D ]q}t|}|d u rt|}	|	d }
t|	dd  tj
|
ddg}t|tj|
t|	dd  gdd}tj|dd	}t||}|| d
}qM|dkrtt	d|dg }|tj||d	 t| d
}qM|| qM| |}t|}|r%|d u rt|}t|d }||d  }
ttj
|
dd|d |d  g}t|d|
f}tj|dd	}t||}|S |dkr%|d gtt	|d  }tj||d	}|S | |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)r6   r(   r,   r+   r:   r9   r   ndimmaxr7   r   r*   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_shaper   r   r   call   s   










z
Merge.callc                 C   s   |d d u r	d }n|d dd  }t dt|D ]}|| d u r#d }n|| dd  }| ||}qdd |D d h }t|dkrMt|d f| }|S d| }|S )Nr   r%   c                 S   s   h | ]
}|d ur|d qS )Nr   r   r2   r   r   r   r5      s    z-Merge.compute_output_shape.<locals>.<setcomp>r   )r7   r&   r'   r(   )r   r;   r/   r0   r   r<   r   r   r   compute_output_shape   s    zMerge.compute_output_shapec                 C   s6   |  dd |D }tdd |D }t|| j|dS )Nc                 S   s   g | ]}|j qS r   )r   r3   r"   r   r   r   
<listcomp>   s    z-Merge.compute_output_spec.<locals>.<listcomp>c                 s   s    | ]}|j V  qd S r   )sparserW   r   r   r   	<genexpr>   s    z,Merge.compute_output_spec.<locals>.<genexpr>)dtyperY   )rV   allr   compute_dtype)r   r   r/   output_sparser   r   r   compute_output_spec   s
   zMerge.compute_output_specNc              
   C   s   |d u rd S t |ttfstd| t |ttfs"td| t|t|kr>td| dt| d| dt| tdd |D rId S |d }|d	d  D ]}t||}qS|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                 s   s    | ]}|d u V  qd S r   r   )r3   mr   r   r   rZ     s    z%Merge.compute_mask.<locals>.<genexpr>r   r%   )r6   r,   r(   r+   r&   r   r   r   )r   r   r#   r!   r`   r   r   r   compute_mask   s4   zMerge.compute_maskc                    s
   t   S r   )r   
get_config)r   r   r   r   rb     s   
zMerge.get_configr   )__name__
__module____qualname____doc__r	   r   r$   r'   r=   rU   rV   r_   ra   rb   __classcell__r   r   r   r   r      s    %(+T
r   N)	keras.srcr   r   %keras.src.backend.common.keras_tensorr   keras.src.layers.layerr   r   r   r   r   r   <module>   s
    