o
    "jx                     @   sN  d dl Z d dlZd dlmZ d dl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 ddlmZ dd	lmZmZ dd
lmZmZmZmZmZ ddlmZmZmZmZ ddlm Z m!Z!m"Z"m#Z#m$Z$m%Z% d!ddZ&dd Z'G dd dZ(G dd dZ)dd Z*dd ddfdej+ejge,f fddZ-ej.d!ddZ/ej.d"dd Z0dS )#    N)OrderedDict)	framework)ops_contain_noneprim_config)Operatordefault_main_program)
as_tensors   )
_composite)add
fill_const)lookup_compositelookup_orig2primlookup_prim2origop_position_inputsop_position_output)_jvp
_orig2prim
_prim2orig
_transpose)flattenflatten_and_remove_noneget_input_var_listget_output_var_listmap_output_for_compositeprepare_python_api_argumentsc                    s8  |du r	t   n|}g }g }t  t | D ]}|du s&|j|ks&J d| t|< q fdd}|jD ]}||rP|| tt|D ]}| t|< qGq6t fdd|D fdd}	t	|D ]}|	|r|| tt
|D ]}|t|< qwqffdd	| D }
 fd
d	|D }tt	||
|fS )a  Returns the list of ops on the path from `xs` to `ys` in topological
    order.

    TODO(Tongxin): supporting control flow and nested blocks.
    Args:
        xs: a list|tuple of vars as source
        ys: a list|tuple of vars as sink
        block: the program block containing the path, optional
    Returns:
        (path, unused_xs, unreached_ys): a tuple comprised of the resulting op
        path, the unused variables in `xs`, and the unreached variables in `ys`
    Nz"x is not None and x.block != blockc                       t  fddtt| D S )Nc                 3       | ]	}t | v V  qd S Nid.0vreached_vars _/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/incubate/autograd/primx.py	<genexpr>J   
    

.topo_path.<locals>.<lambda>.<locals>.<genexpr>)anyr   r   opr$   r&   r'   <lambda>J       
ztopo_path.<locals>.<lambda>c                 3   s(    | ]}t | v rt ||fV  qd S r   r   r"   yr$   r&   r'   r(   X   s   & ztopo_path.<locals>.<genexpr>c                    r   )Nc                 3   r   r   r   )r"   out	used_varsr&   r'   r(   Y   r)   r*   )r+   r   r   r,   r3   r&   r'   r.   Y   r/   c                       g | ]
}t | vr|qS r&   r   r"   xr3   r&   r'   
<listcomp>e       ztopo_path.<locals>.<listcomp>c                    r5   r&   r   r0   r$   r&   r'   r8   f   r9   )r   current_blockr   blockr    opsappendr   r   reversedr   list)xsysr;   pathZbackpathr7   Zreachingr-   varZback_reaching	unused_xsZunreached_ysr&   )r%   r4   r'   	topo_path-   s8   


rE   c                 C   s2   t  }| D ]}tt|D ]}||t|< qq|S )zReturns the output variables of all the ops on the path from `xs`
    to `ys`.

    Args:
        path: a list of ops on which to find the output variables

    Returns:
        vars: the output vars
    )r   r   r   r    )rB   varsr-   r2   r&   r&   r'   output_vars_on_pathk   s   
rG   c                   @   s`   e Zd ZdZg dZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd ZdS )VarMapz~A general map data structure for linking variables to variables.

    An example is linking variables to their gradients.
    )namevarsettabc                 C   s   || _ || _t | _d S r   )rI   rJ   r   rK   )selfrI   rJ   r&   r&   r'   __init__   s   zVarMap.__init__c                 C   s   t || jt |< d S r   r    rK   )rL   key_var	value_varr&   r&   r'   r      s   z
VarMap.addc                 C   s   |d u rd S t |tjjjr*t |tjjjstdt| t|| jt|< d S t	|t	|ksAJ dt	| dt	| dt
||D ]
\}}| || qFd S )Nz%value_vars must be Variable, but got zDlen(key_vars) shoule be equal to len(value_vars), but len(key_vars)=z and len(value_vars)=.)
isinstancepaddlebaser   Variable	TypeErrortyper    rK   lenzipadd_rec)rL   key_vars
value_varsrO   rP   r&   r&   r'   rZ      s$   zVarMap.add_recc                 C   s(   | j t|}|d ur| j|S d S r   )rK   getr    rJ   )rL   rO   Zvalue_idr&   r&   r'   lookup   s   zVarMap.lookupc                 C   s&   t |}|| jv r| jt |= d S d S r   rN   )rL   rO   varidr&   r&   r'   delete   s   
zVarMap.deletec                 C   s(   |D ]}t |}|| jv r| j|= qd S r   rN   )rL   r[   rC   r_   r&   r&   r'   delete_keyvars   s   
zVarMap.delete_keyvarsc                    s<   dd |D   fdd| j  D }|D ]}| j |= qd S )Nc                 S   s   g | ]}t |qS r&   r   r!   r&   r&   r'   r8      s    z+VarMap.delete_valuevars.<locals>.<listcomp>c                    s   g | ]
\}}| v r|qS r&   r&   )r"   kr#   Zidsr&   r'   r8      r9   )rK   items)rL   r\   keysrb   r&   rc   r'   delete_valuevars   s
   
zVarMap.delete_valuevarsc                 C   s   | j t|S r   )rK   __contains__r    )rL   rO   r&   r&   r'   contain_var   s   zVarMap.contain_varc                 C   s   t || j v S r   )r    rK   values)rL   rP   r&   r&   r'   contain_value   s   zVarMap.contain_valueN)__name__
__module____qualname____doc__	__slots__rM   r   rZ   r^   r`   ra   rf   rh   rj   r&   r&   r&   r'   rH   }   s    rH   c                   @   sd   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdddZdddZdS )	TransformzXAn object that maintains the state of transformations applied to a
    primitve program.c                 C   sH   |t   ksJ d|| _| || _td| j| _td| j| _d S )Nz8only support transform on current block of main program.var2dotZdot2var)r   r:   r;   	init_varsrF   rH   rq   dot2bar)rL   r;   r&   r&   r'   rM      s   zTransform.__init__c                 C   s*   t  }|j D ]
\}}||t|< q|S r   )r   rF   rd   r    )rL   r;   rF   _rC   r&   r&   r'   rr      s   zTransform.init_varsc                 C   s   | j dd |D  d S )Nc                 S   s   i | ]}|d urt ||qS r   r   r!   r&   r&   r'   
<dictcomp>       z&Transform.add_vars.<locals>.<dictcomp>)rF   update)rL   new_varsr&   r&   r'   add_vars   s   zTransform.add_varsc                 C   sh   |d u rd S t |tjjjr| jt||i d S t |ts(t	dt
| |D ]}| | q*d S )Nznew_vars must be list, but got )rR   rS   rT   r   rU   rF   rw   r    r?   rV   rW   add_vars_rec)rL   rx   rC   r&   r&   r'   rz      s   
zTransform.add_vars_recc                 C   sH   | j }t|D ]}|j||d  qt|D ]}|j|= q|  d S )Nr	   )r;   r>   desc
_remove_opr<   _sync_with_cpp)rL   Zordered_indexesr;   Zop_indexr&   r&   r'   	erase_ops   s   
zTransform.erase_opsc                 C   sv   |D ]}t || jv r| jt |= q| j| | j| | j}|D ]}|j}|j	|
  |j|= q#|  d S r   )r    rF   rs   ra   rq   rf   r;   rI   r{   _remove_varencoder}   )rL   Zvars_to_eraserC   r;   rI   r&   r&   r'   
erase_dots   s   
zTransform.erase_dotsc                    s6   t |tjjjr j|}|S  fdd|D }|S )zLookup var2dot recursively.c                       g | ]}  |qS r&   )var2dot_recr"   rC   rL   r&   r'   r8          z)Transform.var2dot_rec.<locals>.<listcomp>)rR   rS   rT   r   rU   rq   r^   )rL   rF   dotdotsr&   r   r'   r      s
   zTransform.var2dot_recc                    sF   t |tjjjr j|}|d usJ d|S  fdd|D }|S )Nzbar must be not Nonec                    r   r&   )dot2bar_rec)r"   r   r   r&   r'   r8     r   z)Transform.dot2bar_rec.<locals>.<listcomp>)rR   rS   rT   r   rU   rs   r^   )rL   r   barZbarsr&   r   r'   r      s   zTransform.dot2bar_recNc                    sH  |du rdd |D }  | nt|t|ks'J dt| dt| t||D ]/\}}|j|jksBJ d|j d|j |j|jksTJ d|j d	|j  j|| q,t|| j\}}}|D ]} j	| qh|D ]#}	t
|	}
 |
}t|	g|R  } | t|	} j|| qs fd
d|D }||fS )a  Performs the linearization transform, a.k.a, forward mode AD
        transform, on a primitive lowered program.

        Args:
            xs: a list of input variables
            ys: a list of output variables
            xs_dot: optional, a list of gradient input variables. The list size
                must be equal to `len(xs)`. The shape and dtype of each element
                must be the same as in `xs`

        Returns:
            (xs_dot, ys_dot): a tuple of two lists. `xs_dot` is the list of
            gradient inputs of the resulting linearized program. `ys_dot` is
            the list gradient outputs of the resulting linearized program

        Nc                 S   s   g | ]}t d |j|jdqS )      ?shapedtype)r   r   r   r6   r&   r&   r'   r8     rv   z'Transform.linearize.<locals>.<listcomp>z4len(xs) should be equal to len(xs_dot), but len(xs)=z and len(xs_dot)=z2x.dtype should be equal to dot.dtype, but x.dtype=z and dot.dtype=z2x.shape should be equal to dot.shape, but x.shape=z and dot.shape=c                       g | ]} j |qS r&   )rq   r^   r0   r   r&   r'   r8   A      )ry   rX   rY   r   r   rq   r   rE   r;   r`   r   r   r   rz   r   rZ   )rL   r@   rA   xs_dotr7   r   rB   rD   rt   r-   insZjvp_insZouts_dotZoutsys_dotr&   r   r'   	linearize	  sL   

zTransform.linearizeFc                    s  t dd |D sJ dt dd |D sJ d|du r7g }|D ]}|td|j|jd q"| nDt|t|ksMJ d	t| d
t| t||D ](\}}|j|jkshJ d|j d|j |j|jkszJ d|j d|j qRt||D ]\}}	j	||	 qt
||j\}
}}|D ]}j| qt|
  dd |D   fdd}t|
D ]y}t|}|}t|||}t|trt|}n|g}| t|}tt|}t|t|ksJ dt| dt| t||D ]0\}}	|	dur0j|}|du rj	||	 qt	||	}|g j	|| qqfdd|D }|st|
dkrt }|
D ]}|tt| qKg }j}t|jD ]\}}||
v r~|| |
d t|
dkr~ nqb | !| ||fS )a  Performs the transpose transform, a.k.a, reverse mode AD
        transform, on a linearized primitive program.

        Note, `transpose` is supposed to be used in couple with `linearize`.

        Args:
            ys_dot: a list of outputs of the linearized program.
            xs_dot: a list of inputs of the linearized program.
            ys_bar: optional, a list of inputs of the resulting transposed
                program. The list size must be equal to `len(ys_dot)`. The shape
                and dtype of each element must be the same as in `ys_dot`

        Returns:
            (ys_bar, xs_bar): a tuple of two lists. `ys_bar` is the list of
            inputs of the resulting transposed program. `xs_bar` is
            the list outputs of the resulting transposed program

        c                 s       | ]}|d uV  qd S r   r&   r!   r&   r&   r'   r(   W      z&Transform.transpose.<locals>.<genexpr>z`xs_dot` includes None.c                 s   r   r   r&   r!   r&   r&   r'   r(   X  r   z`ys_dot` includes None.Nr   r   z<len(ys_dot) should be equal to len(ys_bar), but len(ys_dot)=z and len(ys_bar)=z<y_dot.shape should be equal to y_bar.shape, but y_dot.shape=z and y_bar.shape=z<y_dot.dtype should be equal to y_bar.dtype, but y_dot.dtype=z and y_bar.dtype=c                 s   s    | ]	}t ||fV  qd S r   r   r   r&   r&   r'   r(   y  s    c                    s   t |  v S r   r   )r#   )dotvarsr&   r'   r.   {  s    z%Transform.transpose.<locals>.<lambda>z7len(ins) should be equal to len(ins_bar), but len(ins)=z and len(ins_bar)=c                    r   r&   )rs   r^   r6   r   r&   r'   r8     r   z'Transform.transpose.<locals>.<listcomp>r   )"allr=   r   r   r   ry   rX   rY   rs   r   rE   r;   r`   rG   rw   r>   r   r   r   rR   tupler?   rz   r   r   r^   setr   r   	enumerater<   popr~   r   )rL   r   r   Zys_barZ
retain_fwdr1   Zy_dotZy_barr   r   rB   Zunused_xs_dotrt   Zis_dotr-   r2   Zout_bar_recZins_bar_recZins_barr   ZgradZxs_barvars_to_removeZ
op_indexesr;   ir&   )r   rL   r'   	transposeD  s   












zTransform.transposer   )NF)rk   rl   rm   rn   rM   rr   ry   rz   r~   r   r   r   r   r   r&   r&   r&   r'   rp      s    		
	;rp   c                    sZ   fdd fddfdd|rt nt}|rtnt}i }i }i }| j D ]}| | || < q)g }	t }
t	t
| jD ]}| j| }|	| ||jd ur|j|vrt|} ||| tt|t||g|R  D ]'\}}|d u |d u A rJ d|
|j |||j< |j||j< |j||j< qxqCi }t	t
|jD ]}||j| |||j| < qi }t	t
|jD ]}||j| ||j| < qi }t|jD ]	}||||< qdd	lm} | j }||( || t| ||j|||d
}W d    n	1 sw   Y  W d    n	1 s"w   Y  | j| qCt|	D ]}| j||d  | j|= q2|    t	t
| jD ]0}| j| }|j!D ]}||v rg|"|||  qX|j#D ]}||v r{|$|||  qlqNt|
D ]#}||v sJ d| d||| kr| j%|&  | j'|= q|    d S )Nc                    sf   t t| D ]*}t| | tr | | || q| | d ur0| | j|v r0||| | j  | |< qd S r   )rangerX   rR   r?   rI   argsto_bindvalue_tabler   bindr&   r'   r     s   z_lower.<locals>.bindc                    H   g }| D ]}t |tr| || q|||v r|| n| q|S r   rR   r?   r=   namesr   return_listrI   	bind_namer&   r'   r        
z_lower.<locals>.bind_namec                    4   g }| D ]}t |tr| | }q|| q|S r   r   r@   r   r7   expand_nested_listr&   r'   r        
z"_lower.<locals>.expand_nested_list"orig_out and new_out should match.r   )param_guard)r;   r{   rW   inputsoutputsattrsr	   
var_name "" is not in to_bind_rev.)(r   r   r   r   r{   all_varsrC   rI   r   r   rX   r<   r=   rW   r   rY   r   r   r   Zinput_namesinputZoutput_namesoutputsortedZ
attr_namesattrZpaddle.base.dygraph.baser   	append_opr   r>   r|   r}   input_arg_names_rename_inputoutput_arg_names_rename_outputr   r   rF   )r;   reverse	blacklistlower_fn	lookup_fnr   r   to_bind_revrC   ops_to_remover   op_idxr-   
input_argsorig_outnew_outr   r   r   r   rI   r   Znew_op_descin_nameout_namevar_namer&   r   r   r   r'   _lower  s   	





 	





r   c                 C   s   dS )NTr&   )r7   r&   r&   r'   r.   *  s    r.   filter_c                    sH   fdd fddfddt | tjjjrtd t}t}i }i }i }| j	
 D ]}	| |	 ||	 < q/g }
t }t }d}t| j}t|}d	|  krZ|ksen J d
| d| d	|  kro|kszn J d| d| |d	kr|d	krJ d| d| |d	krt|| }|d	krt||}d }}t|D ]}| j| }|
| |j}||duo||o||v }|s|r|   |}|rd}td | t|} ||| t|}t||g|R  }t|t|ksJ d| dt| dt| t||D ]\}}|du s$|du r6|tvr6td| d| d| |du r=q|dur|j|jks`J d| d|j d|j d|j d|j 
d	|jvsnJ d| d|j|jksJ d| d|j d|j d|j d|j 
|du |du A rJ d||j |||j< |j||j< |j||j< q||j qq| j	 }||j	 q|   t |
D ]}| j	!||d   | j|= q|   tt| jD ]0}| j| }|j"D ]}||v r|#|||  q|j$D ]}||v r|%|||  q	qt&|D ]#}||v s/J d!| d"||| krB| j	'|(  | j)|= q |   t&|D ]}| j	'|(  | j)|= qL|   | jD ]}|*|j	 r||j	+| j	 |j	,| j	 qc|rt-| |||d# dS t | t.j/r| D ]}t-||||d# qdS t0)$z\The operators in block wich satisfy the filter conditon will be decomposite into primitives.c                    sz   t t| D ]4}t| | tr | | || t| | tjjjs"q| | d ur:| | j|v r:||| | j  | |< qd S r   )	r   rX   rR   r?   rS   rT   r   rU   rI   r   r   r&   r'   r   0  s   z_lower_composite.<locals>.bindc                    r   r   r   r   r   r&   r'   r   9  r   z#_lower_composite.<locals>.bind_namec                    r   r   r   r   r   r&   r'   r   B  r   z,_lower_composite.<locals>.expand_nested_listz,Atomize composite op to primitive ops begin.Nr   z expect -1 <= backward_length <= z, but got backward_length: zexpect -1 <= start_idx <= z, but got start_idx: zgot start_idx: z and backward_length: FTZcomposite_ops_recordzwhen replace origin op z[ with composite rule, num of origin outs should be equal to new outs, but len(orig_outs) = z and len(new_outs) = zop z2 should not contain any None value. original outs=z and its composite rule outs=zW with composite rule, origin out dtype should be equal to new out dtype, but orig_out: z.dtype=z and new_out: z1 with composite rule, composite out shape has -1.zW with composite rule, origin out shape should be equal to new out shape, but orig_out: z.shape=r   r	   r   r   )	start_idxbackward_length)1rR   rS   rT   r   ZBlocklogginginfor
   r   r{   r   rC   rI   r   rX   r<   r   r=   rW   r}   r   r   r   r   r   rY   r   
ValueErrorr   r   r   Z	copy_fromr>   r|   r   r   r   r   r   r   r   rF   Z_has_kernelZinfer_var_typeZinfer_shape_lower_compositetypingSequencerV   )r;   r   r   r   r   r   r   r   r   rC   r   r   Znone_vars_to_removeZchangelengthZidx_listlowerZ	lower_prer   r-   Zop_namer   Z	orig_outsZnew_outsr   r   Zop_descr   r   r   itemr&   r   r'   r   (  sD  			










#







r   c                 C   s>   | du r	t   n| } | t   ksJ dt| dg d dS )a-  
    Note:
        **This API is ONLY available in the static graph mode.**
        **Args block must be None or current block of main program.**

    All operators in the target block are processed as follows.
    If it is an original operator, it will be transformed into
    one or a series of automatic differential basic operators with
    equivalent function.

    Args:
        block(paddle.static.Block|None, optional): The
            target block to process on. Default None, and will
            process on the current block of main program.
    N7block is neither None nor current block of main programFr   r   r   r:   r   )r;   r&   r&   r'   	orig2prim  s
   r   c                 C   sN   | du r	t   n| } | t   ksJ d|du rg n|}t| d|d dS )a  
    Note:
        **ONLY available in the static graph mode.**
        **Args block must be None or current block of main program.**

    All operators in the target block are processed as follows.
    If it is an automatic differential basic operator, it will be
    transformed into one or a series of original operators with
    equivalent function to support execution.

    Args:
        block(paddle.static.Block|None, optional): The
            target block to process on. Default None, and will
            process on the current block of main program.
        blacklist(list[string]|None, optional): The names of automatic
            differential basic operator that will not be transformed
            into original operators. Default None, and the blacklist
            is treated as empty list.

    Examples:

        .. code-block:: python

            >>> import paddle
            >>> from paddle.incubate.autograd import enable_prim, prim_enabled, prim2orig

            >>> paddle.enable_static()
            >>> enable_prim()

            >>> x = paddle.ones(shape=[2, 2], dtype='float32')
            >>> x.stop_gradients = False
            >>> y = x * x
            >>> dy_dx = paddle.static.gradients(y, x)
            >>> if prim_enabled():
            ...     prim2orig()
    Nr   Tr   r   )r;   r   r&   r&   r'   	prim2orig  s   'r   r   )NN)1r   r   collectionsr   rS   Zpaddle.baser   Zpaddle.base.corer   r   Zpaddle.base.frameworkr   r   Zpaddle.incubate.autograd.utilsr   Zcomposite_rulesr
   Zprimopsr   r   Zprimregr   r   r   r   r   Z	primrulesr   r   r   r   utilsr   r   r   r   r   r   rE   rG   rH   rp   r   Callableboolr   Zstatic_onlyr   r   r&   r&   r&   r'   <module>   s<    

>A zs
 T