o
    Qe/                     @   s   d dl mZ d dlmZ d dlmZ d dlmZ d dlm	Z	 ddl
mZ ddlmZ dd	l
mZmZ d d
lmZ g ZG dd deZdS )   )Initializer)check_variable_and_dtype)VarDesc)	framework)_current_expected_place    )in_dynamic_mode)unique_name)_C_ops_legacy_C_ops)fluidc                       s,   e Zd ZdZd fdd	Zd	ddZ  ZS )
Diraca	  Initialize the 3D/4D/5D Tensor with Dirac delta function.
    
    It can reserve the feature of convolution layer input, which means that
    as many channels are reserved as possible.

    In this initialize method, elements in the middle of convolution kernels will
    be set to 1 . The formula can be described as follow.

    .. math::

        X[d, d, shape[2]//2, shape[3]//2, ...]=1,  \   d=0,1...N
    
    where, ``N`` is the minimum value of ``in_channels`` and ``out_channels``

    Args:
        groups(int, optional): 0-dimension of the Tensor will be divided by groups, 
            each group has the same value. Default: 1.
        name(str, optional): The default value is None. Normally there is no need for user to set this
            property. For more information, please refer to :ref:`api_guide_Name`.

    Returns:
        Dirac initializer instance objects.

    Examples:
        .. code-block:: python

            import paddle
            
            #1. For kernel_size is uneven number:
            
            attr = paddle.ParamAttr(initializer=paddle.nn.initializer.Dirac())
            conv = paddle.nn.Conv1D(3, 2, 3, weight_attr=attr)
            conv.weight
            # Tensor(shape=[2, 3, 3], dtype=float32, place=CPUPlace, stop_gradient=False,
            #       [[[0., 1., 0.],
            #         [0., 0., 0.],
            #         [0., 0., 0.]],
            # 
            #        [[0., 0., 0.],
            #         [0., 1., 0.],
            #         [0., 0., 0.]]])

            input = paddle.rand([8, 3, 10])
            output = conv(input)
            output == input[:, 0:2, 1:9]  
            # output.shape is [8, 2, 8], It means output is almost the same with input, 2 channels are reserved


            #2. For kernel_size is even number:
            attr = paddle.ParamAttr(initializer=paddle.nn.initializer.Dirac())
            conv = paddle.nn.Conv1D(3, 2, 4, weight_attr=attr)
            conv.weight
            # Tensor(shape=[2, 3, 4], dtype=float32, place=CPUPlace, stop_gradient=False,
            #       [[[0., 0., 1., 0.],
            #         [0., 0., 0., 0.],
            #         [0., 0., 0., 0.]],
            # 
            #        [[0., 0., 0., 0.],
            #         [0., 0., 1., 0.],
            #         [0., 0., 0., 0.]]])
       Nc                    s2   |dkr	t |tsJ dtt|   || _d S )Nr   z& 'groups' must be a positive integer. )
isinstanceintsuperr   __init___groups)selfgroupsname	__class__ KD:\Projects\ConvertPro\env\Lib\site-packages\paddle/nn/initializer/dirac.pyr   [   s   

zDirac.__init__c                 C   sZ  |  |}t|tjsJ t|tjsJ t|dg dd t|jdv s)J d|jd | j dks7J d|j	t
jjkrX|jtdd	|jd
g|jt
jjt
jjdd}n|}d}t rtj  t }t||jttd|j	| W d   n1 sw   Y  n|jdi d|itd|j	|jddd |j}|d | j }t||d }g }	g }
g }d}t|D ]}|d| ||9 }qt | jD ]B}t |D ];}|
!d d}t"|D ](\}}|dkr||||  | 7 }q|dkr||| 7 }q||| d | 7 }q|	!| qqt r6tj  t#|dg}|$| W d   n	1 s0w   Y  n*|jtd|jdg|j	|jt
jjddd}|jdd|iddgi||ddd |jtdddd}t rtj   t% }t&|t|	gt
jj'|	t  |$| W d   n	1 sw   Y  n|jdd|it
jj't|	g|	d dd! |jtd"ddd}t rtj   t% }t&|t|
gt
jj|
t  |$| W d   n	1 sw   Y  n|jdd|it
jjt|
g|
d#dd! t rNtj 4 t(|||d}|$| t#||}|$| |j	t
jjkr=t)||j	}|$| W d   n	1 sHw   Y  nV|jd$|||d%d&did|idd}|jtd|jdg|j	|jt
jjddd}|jdd|id|i||ddd |j	t
jjkr|jd'd|id|i|j	|j	d(dd t* s||_+|S ))a  Initialize the input tensor with dirac initializer.

        Args:
            var(Tensor): Tensor that needs to be initialized.
            block(Block, optional): The block in which initialization ops
                   should be added. Used in static graph only, default None.

        Returns:
            The most critical OP(scatter) in this initializer, which contains 7~8 ops in total.
        Out)Zfloat16Zbfloat16Zfloat32Zfloat64r   )r         z=Only Tensor with 3/4/5 dimensions can be initialized by Diracr   z.Tensor 0-dimension must be divisible by groups.ZdiractmpF)r   shapedtypetypepersistableNZfill_constant)valuer!   r    T)r"   inputsoutputsattrsstop_gradientr   g      ?   XShape)r   r!   r    r"   r#   r(   Zreshape2Xr    )r   r+   )r"   r%   r'   r&   r(   Zscatter_index)r   r#   r(   Zassign_value)r!   r    Zint64_values)r"   r&   r'   r(   Zscatter_value)r!   r    Zfp32_valuesscatter)r,   ZIdsZUpdates	overwritecast)Zin_dtypeZ	out_dtype),Z_check_blockr   r   	ParameterZBlockr   lenr    r   r!   r   ZVarTypeZFP32Z
create_varr	   generatejoinr   Z
LOD_TENSORZin_dygraph_moder   ZdygraphZno_gradr   r
   Zfull_strfloatZ	append_opminreversedinsertrangeappend	enumerateZreshapeZ_share_underline_tensor_toZ_varbase_creatorZassign_value_ZINT64r-   r/   r   op)r   varblockZout_varr<   ZplaceZorigin_shapeZnum_per_groupZ	min_shapeZidx_listZ
value_liststridesproddimijoffsetkZstrideZtmp_outZx_shapeZindex_tensorZ
tmp_tensorZvalue_tensorZtmp_reshape_outZtmp_cast_outr   r   r   __call__a   sx  





	
	

	




	zDirac.__call__)r   N)N)__name__
__module____qualname____doc__r   rF   __classcell__r   r   r   r   r      s    >r   N)Zfluid.initializerr   Zfluid.data_feederr   Z
fluid.corer   r   r   Zfluid.frameworkr   Zpaddler   Zpaddle.utilsr	   r
   r    __all__r   r   r   r   r   <module>   s   