
    ёif                         S SK r S SKJr  S SKJr  S SKJrJr  S SKJ	r	J
r
  S SKJrJrJr  S SKJrJr  SS	KJrJr   " S
 S\5      r " S S5      rS rS rS r " S S5      rSS jrg)    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                   @   ^  \ rS rSrU 4S jrU 4S jrU 4S jrSrU =r$ )StaticPyLayerBlockGuard   c                 |   > [        US[        S5        [        TU ]  UR                  R
                  5        Xl        g )Nblockr   )r
   StaticPyLayerBlocksuper__init__helpermain_programblock_manager)selfr   	__class__s     _/var/www/html/banglarbhumi/venv/lib/python3.13/site-packages/paddle/static/nn/static_pylayer.pyr    StaticPyLayerBlockGuard.__init__   s8    %		
 	--::;*    c                 8   > [         TU ]  5         U R                  $ N)r   	__enter__r   )r   r   s    r   r#   !StaticPyLayerBlockGuard.__enter__&   s    !!!r    c                 X   > U R                   R                  5         [        TU ]  XU5      $ r"   )r   completer   __exit__)r   exc_typeexc_valexc_tbr   s       r   r'    StaticPyLayerBlockGuard.__exit__*   s'    ##%w6::r    )r   )	__name__
__module____qualname____firstlineno__r   r#   r'   __static_attributes____classcell__)r   s   @r   r   r      s    +"; ;r    r   c                   j    \ rS rSrSS jrSS jr\S 5       r\S 5       r\S 5       r	S r
S	 rS
 rSrg)r   /   Nc                     U Vs/ s H  n[        U[        5      (       d  M  UPM     snU l        / U l        X0l        [        SUS9U l        S U l        S U l        S U l	        0 U l
        g s  snf )Nstatic_pylayer_block)name)
isinstancer   
fwd_inputsfwd_outputscontextr	   r   	fwd_op_id_forward_block_id_backward_block_idvar_old_to_new)r   inputsr6   pylayer_context
each_inputs        r   r   StaticPyLayerBlock.__init__0   so     %
$
*h/ $
 &!"8tD!%"& 
s
   A)A)c                 $    Xl         [        U 5      $ r"   )is_backward_blockr   )r   rD   s     r   r   StaticPyLayerBlock.blockC   s    !2&t,,r    c                     U R                   $ r"   )r<   r   s    r   forward_block_index&StaticPyLayerBlock.forward_block_indexG   s    %%%r    c                     U R                   $ r"   )r=   rG   s    r   backward_block_index'StaticPyLayerBlock.backward_block_indexK   s    &&&r    c                     U R                   $ r"   )r;   rG   s    r   fwd_op_indexStaticPyLayerBlock.fwd_op_indexO   s    ~~r    c                    U R                   R                  R                  5       nU R                   R                  R                  UR                  5      nUR
                  U l        UR                  [        R                  R                  R                  S9nUR                  SSU R                  0U R                  U/S.SU/0S9nUR
                  U l        U R                   R                  R!                  5         g )N)typepylayerInput)OutScopeblocks)rQ   r?   outputsattrs)r   r   current_blockr   
parent_idxidxr<   
create_varr   VarDescVarTypeSTEP_SCOPES	append_opr8   r9   r;   _sync_with_cpp)r   inside_blockparent_block
step_scope
pylayer_ops        r   complete_forward_block)StaticPyLayerBlock.complete_forward_blockS   s    {{//==?{{//55l6M6MN!-!1!1!,,%%11 - 

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

 $  //1r    c                 N   U R                   R                  R                  5       nU R                   R                  R                  UR                  5      nUR
                  U l        UR                   H`  n[        R                  R                  5       n[        R                  R                  R                  nUR                  R                  XE5        Mb     UR                  U R                   5        [#        XR$                  5        UR&                  R                  U R                   5      R                  nUR                  nUR                  U R(                     R                  R+                  SXg/5        U R,                  (       a}  U R,                  R.                   Hc  nUR1                  UR2                  5      (       d%  [5        UR2                   SUR2                   S35      eUR7                  UR2                  5        Me     U R                   R                  R9                  5         g )NrV   zL was saved in forward block but could not be found in backward block. Maybe z was renamed somewhere.)r   r   rY   r   rZ   r[   r=   opsr   op_proto_and_checker_makerkOpRoleAttrNameOpRoleBackwarddesc	_set_attr_set_forward_block_idxrH   _rename_var_recursively_r>   programrN   set_blocks_attrr:   
saved_varshas_varr6   
ValueError_remove_varra   )	r   rb   rc   opop_role_attr_namebackwardforward_block_descbackward_block_descvars	            r   complete_backward_block*StaticPyLayerBlock.complete_backward_blockj   s   {{//==?{{//55l6M6MN"."2"2""B//??A  66==FFHGG/: # 	++D,D,DE
 	!/B/BC *1177$$

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

 <<||..#++CHH55$88*$pqtqyqypz  {R  S  ((2 / 	  //1r    c                 d    U R                   (       d  U R                  5       $ U R                  5       $ r"   )rD   rf   r~   rG   s    r   r&   StaticPyLayerBlock.complete   s)    %%..00//11r    )	r=   r<   r:   r8   r;   r9   r   rD   r>   NN)F)r,   r-   r.   r/   r   r   propertyrH   rK   rN   rf   r~   r&   r0    r    r   r   r   /   sX    !&- & & ' '  2.%2N2r    r   c                     U c  g [        U SS 5      nUc  g SSKJn  S n[        U5      S:  a  [	        US   U5      (       a  US   nU$ )Nargsr   )StaticPyLayerContext)getattrpaddle.jit.dy2static.py_layerr   lenr7   )funcfn_bind_argsr   fn_ctxs       r   _get_ctx_from_func_r      s\    |4.LBF
<1Q-" " aMr    c                 T   UR                  5        H  u  p#U R                  U5      (       a:  U R                  R                  UR	                  5       UR	                  5       5        MU  U R
                   H%  nUR                  X#5        UR                  X#5        M'     M     SS/nU R
                   H  nUR                  5        H  nXe;  a  M
  UR                  U5      [        R                  R                  :X  a9  UR                  U5      nU R                  R                  U5      n[!        X5        Mp  UR                  U5      [        R                  R"                  :X  d  M  UR%                  U5      n	U	 H)  nU R                  R                  U5      n[!        X5        M+     M     M     g)a  
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,
}
rV   	sub_blockN)itemsru   rn   _rename_varencoderi   _rename_input_rename_output	all_attrs	attr_typer   AttrTypeBLOCK_block_attr_idrr   r   rq   BLOCKS_blocks_attr_ids)
	cur_blockr>   old_var_namenew_var_namerx   block_attr_names	attr_namesub_block_idr   sub_blocks_idss
             r   rq   rq      sR    '5&:&:&<" \**NN&&##%|':':'<  mm  <!!,= $ '=" !+.mmI0||I&$--*=*==!00;%--33LA	(Ci(DMM,@,@@!#!4!4Y!?$2L ) 1 1 7 7 EI,YG %3 ( r    c                    [        U [        5      (       d  U $ UR                  nUR                  5       nU R                  [
        R                  R                  R                  :X  a$  UR                  U R                  5      (       a  U nU$ UR                  U R                  U R                  U R                  S9n[        R                  " X5        U$ )N)dtypeshaperQ   )r7   r   r   rY   rQ   r   r]   r^   DENSE_TENSOR_ARRAY_find_var_recursiver6   r\   r   r   paddleassign)parent_block_varlayer_helperprogrY   current_block_vars        r   copy_var_from_parent_blockr      s    &11$$D&&(M 	!5!5!H!HH--.>.C.CDD,  *44"(("((!&& 5 

 	&:r    c                   $    \ rS rSr/ rS rS rSrg)PyLayerBackwardFunction   c                     Ub  [        U5      (       d  [        S5      eXl        X l         [        R
                  R                  U 5        g )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    PyLayerBackwardFunction.__init__   sG    $H5F,G,G<==&

 !0	 	 88??Er    c           
      T   U R                   (       d   eU R                  " U6 n[        U[        [        45      (       d  U4nU R                  X5        [        U5       Vs/ s H;  n[        U[        R                  R                  [        S 5      45      (       d  M9  UPM=     nnU$ s  snf r"   )
r   r   r7   listtupler   r   pirValuerQ   )r   output_gradsinput_grads
input_grads       r   __call__ PyLayerBackwardFunction.__call__  s    $$$$jj,/+e}55&.Kl8 &k2
2
*vzz'7'7d&DE 2 	 
 
s   8B%B%)r   r   N)r,   r-   r.   r/   r   r   r   r0   r   r    r   r   r      s    !F*r    r   c                   ^^&^' [        5       SL d   S5       e[        T[        5      (       d   eUc=  T H7  nUR                  SL d  M  [	        SUR
                   SUR                   35      e   [        U 5      n[        U5      nU(       a  XV:X  a  UOSn[        5       (       Ga  [        T5       Vs/ s H0  n[        U[        R                  R                  5      (       d  M.  UPM2     n	n[        U	5      n
SnU b  [        U 5      (       d  [	        S5      eU
R                  5          U " T6 nSSS5        Uc  g[        U5       Vs/ s H0  n[        U[        R                  R                  5      (       d  M.  UPM2     snm&U
R                  5          T&b  [        [        T&5      5        SSS5        U
R!                  5         Ub<  [        U5      (       d  [	        S5      eU&U4S jn[#        X-S	9nU
R%                  U5        S
n[        U5      n['        [)        U5      5       HL  n[        UU   [        R                  R                  5      (       d  M1  U
R+                  5       U   UU'   US-  nMN     [)        U5      S:X  a  US
   $ U$ [-        US[.        [1        S5      4S5        [3        S0 [5        5       D6m'U'4S jnU b  [        U 5      (       d   e[7        TUS9nUR9                  SS9 nU " T6 nUbE  [;        UU5      n[        U5       Vs/ s H  n[        U[<        5      (       d  M  UPM     snUl        O/ Ul        SSS5        T'R@                  RC                  5       nURE                  5         UGb  [        U5      (       d   eWc  / n/ nUR>                   H  nUR
                  n[G        U5      nURH                  RK                  URM                  5       5      (       d  [	        SU SU 35      eURO                  URP                  URR                  UR0                  US9nURU                  U5        M     U'4S jn[        U[        5      (       d   eUR9                  SS9 n[;        UU5      nU" U6 nUb  [        U5      n URV                  URX                     RH                  R[                  5       n![)        U!5      [)        U 5      :X  d   S[)        U!5       S[)        U 5       35       e[]        U U!5       HA  u  n"n#[        U"[<        5      (       d  M  [G        U#5      n$U$UR^                  U"R
                  '   MC     SSS5        U H  n%URa                  U%R
                  5        M      Wc  gW$ s  snf ! , (       d  f       GNN= fs  snf ! , (       d  f       GN= fs  snf ! , (       d  f       GNj= f! , (       d  f       N}= f)a3  
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 z`forward_fn` should be callablez `backward_fn` should be callablec           
        > [        T
5       Vs/ s H0  n[        U[        R                  R                  5      (       d  M.  UPM2     nn[        U5       Vs/ s H;  n[        U[        R                  R                  [        S 5      45      (       d  M9  UPM=     nn[        U5      [        U5      :w  a$  [        S[        U5       S[        U5       S35      e[        X5       GHw  u  pEUc  M  UR                  UR                  :X  d"   SUR                   SUR                   S35       eUR                  UR                  :X  d"   SUR                   SUR                   S35       eUR                  5       (       a  UR                  5       (       d   S5       eUR                  5       R                  UR                  5       R                  :X  d>   S	UR                  5       R                   S
UR                  5       R                   S35       eGM+  UR                  5       UR                  5       :X  a  GMP   SUR                  5        SUR                  5        S35       e   [        T	5       Vs/ s H0  n[        U[        R                  R                  5      (       d  M.  UPM2     nn[        U 5      [        U5      :w  a$  [        S[        U 5       S[        T	5       S35      e[        X5       GHo  u  pxUc  M  UR                  UR                  :X  d"   SUR                   SUR                   S35       eUR                  UR                  :X  d"   SUR                   SUR                   S35       eUR                  5       (       a  UR                  5       (       d   S5       eUR                  5       R                  UR                  5       R                  :X  d>   SUR                  5       R                   SUR                  5       R                   S35       eGM+  UR                  5       UR                  5       :X  a  GMP   SUR
                   SUR
                   S35       e   g s  snf s  snf s  snf )NzKThe 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(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   r7   r   r   r   rQ   r   rv   zipr   r   is_dist	dist_attrprocess_mesh)r   r   xforward_inputsinp_grad	fwd_inputforward_outputsout_grad
fwd_outputr9   r?   s            r   "hook_inputs_outputs_check_function:static_pylayer.<locals>.hook_inputs_outputs_check_function  s   
 %V_",!!VZZ%5%56 ,  " %[11!!fjj&6&6T
%CD 1  
 {#s>'::$efijufveww|  ~A  BP  ~Q  }R  RS  T  ,/{+K'H' #>>Y__< ,X^^,<<LY__L]]qr< $>>Y__< ,X^^,<<LY__L]]qr< !((**'//11 O1 &//1>>'113@@A 99L9L9N9[9[8\\kltl~l~  mA  mN  mN  lO  Oc  d	A  (}})..2BB //@@PQZQ_Q_QaPbbvwB- ,L< %[1#1!!VZZ%5%56 1   #
 |$O(<<$ghklxhygzz  AD  EP  AQ  @R  RS  T  -0,N(H' #>>Z-=-== ,X^^,<<MjN^N^M__st= $>>Z-=-== ,X^^,<<MjN^N^M__st= "))++'//11 P1 '002??'113@@A :*:N:N:P:]:]9^^mnv  oA  oA  oC  oP  oP  nQ  Qe  f	A  (}}*//2CC />OPZP_P_O``tuC+ -Og"
J#s#   -Q Q8Q#Q#)-Q(Q()r   r   r   r6   zbase.layers.static_pylayerc                    > [        U T5      $ r"   )r   r}   r   s    r   <lambda> static_pylayer.<locals>.<lambda>  s    &>sF&Kr    )r@   )rD   z	Grad var z) , we can't find its related forward var )r   r   rQ   r6   c                    > [        U T5      $ r"   )r   r   s    r   r   r     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   )static_pylayer)1r   r7   r   stop_gradientrv   r6   r   r   r   r   r   r   r   r   forward_blockr   update_outputr   register_backward_functionranger   resultsr
   strrQ   r	   localsr   r   r   r   r9   r   rY   ra   r   rn   has_var_recursiver   r\   r   r   r   ri   rN   input_arg_namesr   r>   rw   )(
forward_fnr?   backward_fnr6   	input_var
fwd_fn_ctx
bwd_fn_ctxstatic_pylayer_contextinpr8   re   rW   outr   bwd_fnop_result_idxicopy_to_parent_funcpylayer_block_managermgrorigin_outputoutputr   rY   grad_var_insfwd_varfwd_var_namebwd_var_namer}   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_varr9   r   s(    `                                    @@r   r   r     s   N % F% fd####I&&%/  I  JS  JX  JX  IY  Yl  mv  mD  mD  lE  F    %Z0J$[1J j&>
T  }}"6?
*Cjfjj>N>N.OC? 	 
 &j1
!J'' !BCC))+$f- ,  #7++Cc6::#3#34 +K ))+*W[12 , $$&"K(( !CDDM^ -F 11&9 '"s7|$A'!*fjj&6&677'//1-@
" % !\Q.wqz;G;tVc4:.0LM6VX6FK!hz&:&:::. 6 
	$	$u	$	="F+$"#6FF"6?*ajH.E?CO !CO 
> ''557M  "$$$$ F ,88G"<<L/=L %%778K8K8MNN ~-VWcVde   **mmmm\\!	 + C $ 9"!
 ,----"((4(@C"/%|#
 "-.A!B!- $++=#>  '4&7&7)66'$( $ ./37G3HH  !456eC@P<Q;RTH 36$&93.J. "*h77&:*' ( **:??;731 Ap $G%%gll3 $ MQ
 ,+ ,+b	 
>	=R A@sg   2-U.#U.&U3-V6VV
)"V!V(V.V!#B-V3(V33
V

VV!!
V03
Wr   )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   rq   r   r   r   r   r    r   <module>r     s_      5 7 @ M M / ?;j ;(f2 f2R&-H`*& &RCr    