
    {-jf                         d dl Z d dlmZ d dlmZ d dlmZmZ d dlm	Z	m
Z
 d dlmZmZmZ d dlmZmZ dd	lmZmZ  G d
 de          Z G d d          Zd Zd Zd Z G d d          ZddZdS )    N)core)_append_grad_suffix_)Variablein_pir_mode)build_pylayer_opcf_yield)LayerHelper
check_typein_dygraph_mode)flattenmap_structure   )
BlockGuardcopy_var_to_parent_blockc                   2     e Zd Z fdZ fdZ fdZ xZS )StaticPyLayerBlockGuardc                     t          |dt          d           t                                          |j        j                   || _        d S )Nblockr   )r
   StaticPyLayerBlocksuper__init__helpermain_programblock_manager)selfr   	__class__s     _/var/www/html/banglarbhumi/venv/lib/python3.11/site-packages/paddle/static/nn/static_pylayer.pyr   z StaticPyLayerBlockGuard.__init__   sO    %		
 	
 	
 	-:;;;*    c                 R    t                                                       | j        S N)r   	__enter__r   )r   r   s    r   r!   z!StaticPyLayerBlockGuard.__enter__&   s"    !!r   c                 |    | j                                          t                                          |||          S r    )r   completer   __exit__)r   exc_typeexc_valexc_tbr   s       r   r$   z StaticPyLayerBlockGuard.__exit__*   s4    ##%%%ww'6:::r   )__name__
__module____qualname__r   r!   r$   __classcell__)r   s   @r   r   r      sj        + + + + +" " " " "; ; ; ; ; ; ; ; ;r   r   c                   r    e Zd ZddZddZed             Zed             Zed             Zd Z	d	 Z
d
 ZdS )r   Nc                     d |D             | _         g | _        || _        t          d|          | _        d | _        d | _        d | _        i | _        d S )Nc                 <    g | ]}t          |t                    |S  
isinstancer   ).0
each_inputs     r   
<listcomp>z/StaticPyLayerBlock.__init__.<locals>.<listcomp>2   s8     
 
 
*h//

 
 
r   static_pylayer_block)name)	
fwd_inputsfwd_outputscontextr	   r   	fwd_op_id_forward_block_id_backward_block_idvar_old_to_new)r   inputsr6   pylayer_contexts       r   r   zStaticPyLayerBlock.__init__0   sm    
 
$
 
 
 &!"8tDDD!%"& r   Fc                 .    || _         t          |           S r    )is_backward_blockr   )r   rA   s     r   r   zStaticPyLayerBlock.blockC   s    !2&t,,,r   c                     | j         S r    )r;   r   s    r   forward_block_indexz&StaticPyLayerBlock.forward_block_indexG   s    %%r   c                     | j         S r    )r<   rC   s    r   backward_block_indexz'StaticPyLayerBlock.backward_block_indexK   s    &&r   c                     | j         S r    )r:   rC   s    r   fwd_op_indexzStaticPyLayerBlock.fwd_op_indexO   s
    ~r   c                    | j         j                                        }| j         j                            |j                  }|j        | _        |                    t          j	        j
        j                  }|                    dd| j        i| j        |gdd|gi          }|j        | _        | j         j                                         d S )N)typepylayerInput)OutScopeblocks)rJ   r>   outputsattrs)r   r   current_blockr   
parent_idxidxr;   
create_varr   VarDescVarTypeSTEP_SCOPES	append_opr7   r8   r:   _sync_with_cpp)r   inside_blockparent_block
step_scope
pylayer_ops        r   complete_forward_blockz)StaticPyLayerBlock.complete_forward_blockS   s    {/==??{/55l6MNN!-!1!,,%1 - 
 

 "++ !,
|DD<. , 	
 	

 $ //11111r   c                 p   | j         j                                        }| j         j                            |j                  }|j        | _        |j        D ]Q}t          j	        
                                }t          j	        j        j        }|j                            ||           R|                    | j                   t#          || j                   |j                            | j                  j        }|j        }|j        | j                 j                            d||g           | j        rb| j        j        D ]U}|                    |j                  st5          |j         d|j         d          |                    |j                   V| j         j                                         d S )NrO   zL was saved in forward block but could not be found in backward block. Maybe z was renamed somewhere.)r   r   rR   r   rS   rT   r<   opsr   op_proto_and_checker_makerkOpRoleAttrNameOpRoleBackwarddesc	_set_attr_set_forward_block_idxrD   _rename_var_recursively_r=   programrH   set_blocks_attrr9   
saved_varshas_varr6   
ValueError_remove_varrZ   )	r   r[   r\   opop_role_attr_namebackwardforward_block_descbackward_block_descvars	            r   complete_backward_blockz*StaticPyLayerBlock.complete_backward_blockj   s   {/==??{/55l6MNN"."2" 	; 	;B/??AA  6=FHG/::::++D,DEEE
 	!t/BCCC *177$
 

 	 +/*+0@@)+>?	
 	
 	

 < 	3|. 3 3#++CH55 $8  S  Sqtqy  S  S  S   ((2222 //11111r   c                 `    | j         s|                                 S |                                 S r    )rA   r_   rv   rC   s    r   r#   zStaticPyLayerBlock.complete   s1    % 	2..000//111r   NN)F)r(   r)   r*   r   r   propertyrD   rF   rH   r_   rv   r#   r/   r   r   r   r   /   s        ! ! ! !&- - - - & & X& ' ' X'   X2 2 2.%2 %2 %2N2 2 2 2 2r   r   c                     | d S t          | dd           }|d S ddlm} d }t          |          dk    rt	          |d         |          r|d         }|S )Nargsr   )StaticPyLayerContext)getattrpaddle.jit.dy2static.py_layerr|   lenr1   )funcfn_bind_argsr|   fn_ctxs       r   _get_ctx_from_func_r      s{    |t4..LtBBBBBBF
<1Q-" " aMr   c                 L   |                                 D ]\  }}|                     |          r@| j                            |                                |                                           Z| j        D ].}|                    ||           |                    ||           /ddg}| j        D ]}|                                D ]}||vr|	                    |          t          j        j        k    r@|                    |          }| j                            |          }t!          ||           o|	                    |          t          j        j        k    rD|                    |          }	|	D ],}| j                            |          }t!          ||           -܌dS )aD  
    Rename the var both the Variable instances and all ops' input and output arg names
    in `cur_block` based on dict `var_old_to_new`.
    Dict `var_old_to_new` should be the following format:
    {
        old_name_0 : new_name_0,
        old_name_1 : new_name_1,
        ...
        old_name_n : new_name_n,
    }
    rO   	sub_blockN)itemsrm   rf   _rename_varencodera   _rename_input_rename_output	all_attrs	attr_typer   AttrTypeBLOCK_block_attr_idrj   r   ri   BLOCKS_blocks_attr_ids)
	cur_blockr=   old_var_namenew_var_namerp   block_attr_names	attr_namesub_block_idr   sub_blocks_idss
             r   ri   ri      s    '5&:&:&<&< > >"l \** 
	>N&&##%%|':':'<'<     m > >  |<<<!!,====> !+.m H H 	H 	HI 000||I&&$-*===!00;;%-33LAA	(NCCCCi((DM,@@@!#!4!4Y!?!?$2 H HL ) 1 7 7 E EI,YGGGG	HH Hr   c                 Z   t          | t                    s| S |j        }|                                }| j        t
          j        j        j        k    r|	                    | j
                  r| }n<|                    | j        | j        | j                  }t          j        | |           |S )N)dtypeshaperJ   )r1   r   r   rR   rJ   r   rV   rW   DENSE_TENSOR_ARRAY_find_var_recursiver6   rU   r   r   paddleassign)parent_block_varlayer_helperprogrR   current_block_vars        r   copy_var_from_parent_blockr      s    &11  $D&&((M 	!5!HHH--.>.CDD 	I -)44"("(!& 5 
 

 	&(9:::r   c                       e Zd Zg Zd Zd ZdS )PyLayerBackwardFunctionc                     |t          |          st          d          || _        || _        	 t          j                            |            d S )Nzfunc must be a Python function)callable	TypeError_func_hook_check_funcr   _register_backward_funcsappend)r   backward_functionhook_check_funcs      r   r   z PyLayerBackwardFunction.__init__   sZ    $H5F,G,G$<===&

 !0	 	 8??EEEEEr   c                     | j         sJ  | j        | }t          |t          t          f          s|f}|                      ||           d t          |          D             }|S )Nc           	      n    g | ]2}t          |t          j        j        t	          d           f          0|3S r    r1   r   pirValuerJ   )r2   
input_grads     r   r4   z4PyLayerBackwardFunction.__call__.<locals>.<listcomp>  sH     
 
 
*vz'7d&DEE

 
 
r   )r   r   r1   listtupler   )r   output_gradsinput_gradss      r   __call__z PyLayerBackwardFunction.__call__  s    $$$$ dj,/+e}55 	)&.KlK888
 
%k22
 
 
 r   N)r(   r)   r*   r   r   r   r/   r   r   r   r      s;        !F F F*    r   r   c                 
  #$ t                      du s
J d            t          t                    sJ |-D ]*}|j        du rt	          d|j         d|j                   +t          |           }t          |          }|r||k    r|nd}t                      rd t                    D             }t          |          }	d}
| t          |           st	          d          |	                                5   |  }
ddd           n# 1 swxY w Y   |
dS d t          |
          D             #|	                                5  #t          t          #                     ddd           n# 1 swxY w Y   |	                                 |Jt          |          st	          d	          #fd
}t          ||          }|	                    |           d}t          |
          }
t!          t#          |
                    D ]I}t          |
|         t$          j        j                  r"|	                                |         |
|<   |dz  }Jt#          |
          dk    r|
d         n|
S t-          |dt.          t1          d          fd           t3          di t5                      $$fd}| t          |           sJ t7          |          }|                    d          5 } |  }|/t;          ||          }d t          |          D             |_        ng |_        ddd           n# 1 swxY w Y   $j                                         }|!                                 | t          |          sJ |g }g }|j        D ]}|j        }tE          |          }|j#        $                    |%                                          st	          d| d|           |&                    |j'        |j(        |j        |          }|)                    |           $fd}t          |t                    sJ |                    d          5 }t;          ||          } || }|t          |          }|j*        |j+                 j#        ,                                }t#          |          t#          |          k    s*J dt#          |           dt#          |                       t[          ||          D ]8\  }} t          |t\                    rtE          |           }!|!|j/        |j        <   9ddd           n# 1 swxY w Y   |D ]}"|0                    |"j                   |dS |S )a  
    This API returns ``forward_fn(inputs)``, and two sub-block are created based on
    the logic of ``forward_fn`` and ``backward_fn``, with the operator ``pylayer``
    holding information about the two blocks.

    ``forward_fn`` and ``backward_fn`` should return a nest structure of Variables.
    A nest structure of Variables in PaddlePaddle is Variable(s), or tuple of Variables, or
    list of Variables.

    Note:
        1. If ``backward_fn`` is not None, user needs to keep the number of `Variable` inputs to ``forward_fn`` the same as the
        number of `Variable` outputs to ``backward_fn``, and the number of `Variable` outputs to ``forward_fn``
        the same as the number of `Variable` inputs to ``backward_fn``.

        2. If ``backward_fn`` is None, ``stop_gradient`` attr of all Variable in ``inputs`` is expected to be True.
        Otherwise it might get unexpected results in backward propagation.

        3. This API can only be used under static graph mode.

    Args:
        forward_fn (callable): A callable to be performed in forward propagation
        inputs (list[Variable]): The list of input Variable to the ``forward_fn``
        backward_fn (callable, optional): A callable to be performed in backward propagation. Default: None, which means no need to do backward propagation.
        name (str, optional): The default value is ``None`` . Normally users
            don't have to set this parameter. For more information, please
            refer to :ref:`api_guide_Name` .

    Returns:
        Variable|list(Variable)|tuple(Variable): returns the output of ``forward_fn(inputs)``

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> import numpy as np

            >>> paddle.enable_static()

            >>> def forward_fn(x):
            ...     return paddle.exp(x)

            >>> def backward_fn(dy):
            ...     return 2 * paddle.exp(dy)

            >>> main_program = paddle.static.Program()
            >>> start_program = paddle.static.Program()

            >>> place = paddle.CPUPlace()
            >>> exe = paddle.static.Executor(place)
            >>> with paddle.static.program_guard(main_program, start_program):
            ...     data = paddle.static.data(name="X", shape=[None, 5], dtype="float32")
            ...     data.stop_gradient = False
            ...     ret = paddle.static.nn.static_pylayer(forward_fn, [data], backward_fn)
            ...     data_grad = paddle.static.gradients([ret], data)[0]

            >>> exe.run(start_program)
            >>> x = np.array([[1.0, 2.0, 3.0, 4.0, 5.0]], dtype=np.float32)
            >>> x, x_grad, y = exe.run(
            ...     main_program,
            ...     feed={"X": x},
            ...     fetch_list=[data, data_grad, ret],
            ... )

            >>> print(x)
            [[1. 2. 3. 4. 5.]]
            >>> print(x_grad)
            [[5.4365635 5.4365635 5.4365635 5.4365635 5.4365635]]
            >>> print(y)
            [[  2.7182817   7.389056   20.085537   54.59815   148.41316  ]]
    Fz<please use PyLayer instead of static_pylayer in dygraph modeNzr``stop_gradient`` attr of all inputs to ``forward_fn`` are expected to be True, when ``backward_fn == None``, but z.stop_gradient got c                 P    g | ]#}t          |t          j        j                  !|$S r/   r1   r   r   r   )r2   inps     r   r4   z"static_pylayer.<locals>.<listcomp>t  s<     
 
 
jfj>N.O.O

 
 
r   z`forward_fn` should be callablec                 P    g | ]#}t          |t          j        j                  !|$S r/   r   )r2   outs     r   r4   z"static_pylayer.<locals>.<listcomp>  s=       c6:#344  r   z `backward_fn` should be callablec                    d t          	          D             }d t          |          D             }t          |          t          |          k    r0t          dt          |           dt          |           d          t          ||          D ]e\  }}|	|j        |j        k    sJ d|j         d|j         d            |j        |j        k    sJ d	|j         d|j         d            |                                r|                                s
J d
            |                                j        |                                j        k    s?J d|                                j         d|                                j         d            |	                                |	                                k    s5J d|	                                 d|	                                 d            gd t                    D             }t          |           t          |          k    r0t          dt          |            dt                     d          t          | |          D ]K\  }}|	|j        |j        k    sJ d|j         d|j         d            |j        |j        k    sJ d|j         d|j         d            |                                r|                                s
J d            |                                j        |                                j        k    s?J d|                                j         d|                                j         d            |	                                |	                                k    sJ d|j	         d|j	         d            Md S )Nc                 P    g | ]#}t          |t          j        j                  !|$S r/   r   r2   xs     r   r4   zNstatic_pylayer.<locals>.hook_inputs_outputs_check_function.<locals>.<listcomp>  s=     " " "!!VZ%566"" " "r   c           	      n    g | ]2}t          |t          j        j        t	          d           f          0|3S r    r   r   s     r   r4   zNstatic_pylayer.<locals>.hook_inputs_outputs_check_function.<locals>.<listcomp>  sH       !!fj&6T

%CDD  r   zKThe number of input grads should be equal to the number of inputs, but got  and .zdtype of inp_grad(z) and fwd_input(z) should be the samezshape of inp_grad(z1fwd_input and inp_grad should both be distributedzprocess_mesh of fwd_input(z) and inp_grad(ztype of inp_grad(c                 P    g | ]#}t          |t          j        j                  !|$S r/   r   r   s     r   r4   zNstatic_pylayer.<locals>.hook_inputs_outputs_check_function.<locals>.<listcomp>  s=     # # #!!VZ%566## # #r   zMThe number of output grads should be equal to the number of outputs, but got zdtype of out_grad(z) and fwd_output(zshape of out_grad(z2fwd_output and out_grad should both be distributedzprocess_mesh of fwd_output(z) and out_grad(ztype of out_grad()
r   r   rn   zipr   r   is_dist	dist_attrprocess_meshrJ   )
r   r   forward_inputsinp_grad	fwd_inputforward_outputsout_grad
fwd_outputr8   r>   s
           r   "hook_inputs_outputs_check_functionz:static_pylayer.<locals>.hook_inputs_outputs_check_function  s   " "$V__" " "
 $[11  
 {##s>':':::$ Tfijufvfv  T  T  ~A  BP  ~Q  ~Q  T  T  T   ,/{N+K+K  'Hi' #>Y_<<<rX^rrY_rrr =<< $>Y_<<<rX^rrY_rrr =<< !((** '//11  O 1 &//11>'1133@A A A d9L9L9N9N9[  d  dltl~l~  mA  mA  mN  d  d  dA A A A  (}})..2B2BBBBwwwQZQ_Q_QaQawww  CBBB# #$[11# # #
 |$$O(<(<<<$ Thklxhyhy  T  T  AD  EP  AQ  AQ  T  T  T   -0o,N,N  (Hj' #>Z-====tX^ttjN^ttt >== $>Z-====tX^ttjN^ttt >== "))++ '//11  P 1 '0022?'1133@A A A f*:N:N:P:P:]  f  fnv  oA  oA  oC  oC  oP  f  f  fA A A A  (}}*//2C2CCCCuuuPZP_uuu  DCCC+ r   )r   r   r   r6   zbase.layers.static_pylayerstatic_pylayerc                 $    t          |           S r    )r   ru   r   s    r   <lambda>z static_pylayer.<locals>.<lambda>  s    &>sF&K&K r   )r?   )rA   c                 <    g | ]}t          |t                    |S r/   r0   r   s     r   r4   z"static_pylayer.<locals>.<listcomp>  s7       jH.E.E  r   z	Grad var z) , we can't find its related forward var )r   r   rJ   r6   c                 $    t          |           S r    )r   r   s    r   r   z static_pylayer.<locals>.<lambda>  s    ,F-
 -
 r   Tzneeds to keep the number of inputs to ``forward_fn`` the same as the number of outputs to ``backward_fn``,                     but got r   )r   )1r   r1   r   stop_gradientrn   r6   r   r   r   r   r   forward_blockr   update_outputr   register_backward_functionranger   r   r   r   resultsr
   strrJ   r	   localsr   r   r   r8   r   rR   rZ   r   rf   has_var_recursiver   rU   r   r   r   ra   rH   input_arg_namesr   r   r=   ro   )%
forward_fnr>   backward_fnr6   	input_var
fwd_fn_ctx
bwd_fn_ctxstatic_pylayer_contextr7   r^   rP   r   bwd_fnop_result_idxicopy_to_parent_funcpylayer_block_managermgrorigin_outputoutputrR   grad_var_insfwd_varfwd_var_namebwd_var_nameru   copy_from_parent_funcinside_block_inputsgrad_origin_outputflat_grad_originforward_input_names
bwd_outputfwd_input_namebwd_out_newbwd_varr8   r   s%    `                                 @@r   r   r     s   N %%%F &%% fd##### 	 	I&%//  F  JS  JX  F  F  mv  mD  F  F   0 %Z00J$[11J IjJ&>&>

T  }} x<
 
"6??
 
 

 &j11
!J'' D !BCCC))++ . .$*f-. . . . . . . . . . . . . . . t "7++  K ))++ 3 3*W[112223 3 3 3 3 3 3 3 3 3 3 3 3 3 3 $$&&&"K(( E !CDDDM M M M M M^ --O  F 11&999 '""s7||$$ 	# 	#A'!*fj&677 #'//11-@
" \\Q..wqzzG;tVc4::.0LMMM66VXX66FKKKK!hz&:&:!!:. 6   
	$	$u	$	=	= !"
F+$"#6FFF "6??  COO !CO! ! ! ! ! ! ! ! ! ! ! ! ! ! ! '5577M  """$$$$$ F ,8 	% 	%G"<L/==L %778K8K8M8MNN  eeeWcee    **mm\!	 +  C $$$$!
 !
 !
 !
 ,-----"((4(@@ 5	C"/%|# #
 "-.A!B!- $++=#>#>  '4&7)6'(( $ .//37G3H3HHHHT !455T T<?@P<Q<QT T IHH 36$&93 3  .J. "*h77 &:*' ' ( *:?;g5	 5	 5	 5	 5	 5	 5	 5	 5	 5	 5	 5	 5	 5	 5	p $ 	4 	4G%%gl3333tMsI   ;DDD	E44E8;E80>L::L>L>C#UUUrx   )r   paddle.baser   paddle.base.backwardr   paddle.base.frameworkr   r   paddle.base.libpaddle.pirr   r   paddle.common_ops_importr	   r
   r   paddle.utilsr   r   control_flowr   r   r   r   r   ri   r   r   r   r/   r   r   <module>r     s          5 5 5 5 5 5 7 7 7 7 7 7 7 7 @ @ @ @ @ @ @ @ M M M M M M M M M M / / / / / / / / ? > > > > > > >; ; ; ; ;j ; ; ;(f2 f2 f2 f2 f2 f2 f2 f2R  &-H -H -H`  *& & & & & & & &RC C C C C Cr   