o
    7?eE&                     @   sN   d Z ddlm  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 )zEPrivate base class for layers that can merge several inputs into one.    N)backend)Layer)tf_utilsc                       sj   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 fddZ  ZS )_MergezgGeneric merge layer for elementwise merge functions.

    Used to implement `Sum`, `Average`, etc.
    c                    s   t  jdi | d| _dS )zhInitializes a Merge layer.

        Args:
          **kwargs: standard layer keyword arguments.
        TN )super__init__Zsupports_masking)selfkwargs	__class__r   d/home/www/facesmatcher.com/pyenv/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||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	   Zshape1Zshape2output_shapeijr   r   r   r   *   s0    z(_Merge._compute_elemwise_op_output_shapec                 C   s  t |d tstd| dt|dk r!tdt| d| dd |D d h }t|dkr8td	| |d d u rAd }n|d dd  }tdt|D ]}|| d u r[d }n|| dd  }| ||}qPd |vr~tttt|dkr~d
| _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   zBA merge layer should be called on a list of at least 1 input. Got z$ inputs. Full input_shape received: c                 S   s   h | ]}|r|d  qS )r   r   .0sr   r   r   	<setcomp>`   s    z_Merge.build.<locals>.<setcomp>zICannot merge tensors with different batch sizes. Got tensors with shapes FT)	
isinstancer   r   r   ranger   setmap_reshape_required)r	   input_shapebatch_sizesr   r   shaper   r   r   buildQ   sD   

z_Merge.buildc                 C   sP  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 ]m}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	 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   axisFr   )r   r   )permT)r!   r   r   r   r%   r$   r   ndimmaxr"   tfexpand_dimsr   r   r(   concatenateZreshapestackZreduce_prodZ	transpose)r	   r   Zreshaped_inputsZinput_ndimsZmax_ndimxZx_ndim_Z
transposedZx_shapeZ
batch_sizeZ	new_shapeZx_transposeddimsyZy_ndimZy_shaper   r   r   cally   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   r   r   r   r   r       s    z._Merge.compute_output_shape.<locals>.<setcomp>r   )r"   r   r   r   )r	   r&   r   r   r(   r'   r   r   r   compute_output_shape   s    z_Merge.compute_output_shapeNc              
   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 }tjtj|d
dd
dd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   r   mr   r   r   	<genexpr>   s    z&_Merge.compute_mask.<locals>.<genexpr>c                 S   s"   g | ]}|d urt j|ddqS )Nr   r*   )r0   r1   r:   r   r   r   
<listcomp>   s   " z'_Merge.compute_mask.<locals>.<listcomp>r   r*   F)r+   Zkeepdims)r!   r   r   r   r   allr   r2   )r	   r   maskmasksr   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   Zshape_type_conversionr)   r8   r9   rA   rB   __classcell__r   r   r   r   r      s    	'
'M

r   )rF   Ztensorflow.compat.v2compatv2r0   Z	keras.srcr   Zkeras.src.engine.base_layerr   Zkeras.src.utilsr   r   r   r   r   r   <module>   s   