o
    –hé  ã                   @   sZ   d Z ddlZddlZddlmZ G dd„ dejƒZG dd„ dejƒZG dd	„ d	ejƒZdS )
z\
Based on
https://pytorch.org/tutorials/beginner/transformer_tutorial.html#define-the-model
é    N)Únnc                       s>   e Zd ZdZ‡ fdd„Zeddd„ƒZdd„ Zd	d
„ Z‡  Z	S )ÚSinusoidalEncodingz2
    Uses sine & cosine to represent position
    c                    s"   t ƒ  ¡  |  d|  ||¡¡ d S )NÚpe)ÚsuperÚ__init__Úregister_bufferÚbuild_position)ÚselfÚ	model_dimÚmax_len©Ú	__class__© úi/var/www/html/env_mimamsha/lib/python3.10/site-packages/stanza/models/constituency/positional_encoding.pyr      s   
zSinusoidalEncoding.__init__Nc                 C   s˜   t  |¡ d¡}t  t  d| d¡t d¡ |   ¡}t  || ¡}t  || ¡|d d …dd d…f< t  || ¡|d d …dd d…f< |d urJ|j	|d}|S )Né   r   é   g     ˆÃ@©Údevice)
ÚtorchÚarangeÚ	unsqueezeÚexpÚmathÚlogÚzerosÚsinÚcosÚto)r
   r   r   ÚpositionÚdiv_termr   r   r   r   r      s   $  z!SinusoidalEncoding.build_positionc                 C   s^   t |ƒ| jjd kr*| jj}| jjd }|  dd ¡ |  d| j|t |ƒd |d¡ | j| S )Nr   r   r   r   )Úmaxr   Úshaper   r   r   )r	   Úxr   r!   r   r   r   Úforward   s    
zSinusoidalEncoding.forwardc                 C   s   | j jd S )Nr   )r   r!   )r	   r   r   r   r   *   s   zSinusoidalEncoding.max_len©N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ústaticmethodr   r#   r   Ú__classcell__r   r   r   r   r      s    
r   c                       s,   e Zd ZdZd	‡ fdd„	Zd
dd„Z‡  ZS )ÚAddSinusoidalEncodingz
    Uses sine & cosine to represent position.  Adds the position to the given matrix

    Default behavior is batch_first
    é   é   c                    ó   t ƒ  ¡  t||ƒ| _d S r$   ©r   r   r   Úencoding©r	   Úd_modelr   r   r   r   r   4   ó   
zAddSinusoidalEncoding.__init__ç      ð?c                 C   sv   t |jƒdkr |  tj|jd |jd¡}| |jd dd¡}nt |jƒdkr5|  tj|jd |jd¡}|||  S )z¼
        Adds the positional encoding to the input tensor

        The tensor is expected to be of the shape B, N, D
        Properly masking the output tensor is up to the caller
        é   r   r   r   éÿÿÿÿr   )Úlenr!   r0   r   r   r   Úexpand)r	   r"   ÚscaleÚtimingr   r   r   r#   8   s   zAddSinusoidalEncoding.forward©r,   r-   )r4   ©r%   r&   r'   r(   r   r#   r*   r   r   r   r   r+   .   s    r+   c                       s*   e Zd ZdZd‡ fdd„	Zdd„ Z‡  ZS )	ÚConcatSinusoidalEncodingzŠ
    Uses sine & cosine to represent position.  Concats the position and returns a larger object

    Default behavior is batch_first
    r,   r-   c                    r.   r$   r/   r1   r   r   r   r   M   r3   z!ConcatSinusoidalEncoding.__init__c                 C   sr   t |jƒdkr |  tj|jd |jd¡}| |jd dd¡}n|  tj|jd |jd¡}tj||fdd}|S )Nr5   r   r   r   r6   )Údim)r7   r!   r0   r   r   r   r8   Úcat)r	   r"   r:   Úoutr   r   r   r#   Q   s   z ConcatSinusoidalEncoding.forwardr;   r<   r   r   r   r   r=   G   s    r=   )r(   r   r   r   ÚModuler   r+   r=   r   r   r   r   Ú<module>   s    #