o
    "jJc                     @   s2  d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
 d dlmZmZmZ d dlmZ ddlmZ d	d
 Zdd Zdd Zdd Z	d(ddZe e fddZdd Zdd Zdd Zdedejdedefdd Zdedejd!ejdedef
d"d#Z dedejd!ejded$ed%edefd&d'Z!dS ))    N)pir)ir_backward)call_decomp decomp_ops_contain_unused_output
has_decomp)Block	OperationProgram)core   )registerc                 C   s:   t | tjr	| fS t | tjrt| S tdt|  dS )NzType z is not supported.)
isinstancer   OpResulttypingSequencetuple	TypeErrortype)Zxs r   \/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/decomposition/decomp.py_build_tensor_tuple    s
   r   c                 C   s   t | t |ks
J g }t|D ]B\}}t| | tjrM| t v r5|t|  v r5|d d u s4J nt |dkrCt|d tjsEJ ||d  q|| q|S )Nr   r   )	len	enumerater   r   r   namer   keysappend)	orig_outsdecomp_outsopresidxvaluer   r   r   _analyse_decomp_results(   s    r"   c                    s   d}g }   D ]/}| }|r2| r2| }t|tr,| |kr,dd |  D }|| q|d q  |krA|fS | fdd  D  }t	|S )z
    For standard api of operator, its inputs should keep consistent with organization of its inputs and attrs.

    Args:
    op (Operator): The target operator.
    builtin.combinec                 S      g | ]}|  qS r   source).0itemr   r   r   
<listcomp>K       z1_prepare_python_api_arguments.<locals>.<listcomp>Nc                    s   g | ]}   | qS r   )attrsr'   xr   r   r   r)   W       )
operandsr&   initializedget_defining_opr   r   r   r   Zget_attr_namesr   )r   combine_op_nameinputsr-   inputprev_opZapi_argumentsr   r.   r   _prepare_python_api_arguments:   s    r7   c              	   C   s   d}g }|   D ]Z}| }|rb| rb| }t|trI| |krI|  D ] }| j}d|v rGt	d| j d|   d   dS q'q|j}d|v rbt	d|j d|   d  dS qd S )Nr#   z;Decomp op does not support dynamic shape -1, but got shape z in inputs of op  Tz in op )
r0   r&   r1   r2   r   r   r   shapewarningswarn)r   r3   r4   r-   r5   r6   r(   r:   r   r   r   _check_prim_dynamic[   s4   
r=   c                 C   sH  t |t |ksJ d|  dt | dt | t||D ]\}}|du s*|du r<| tjvr<td|  d| d| |du rAq|dur|durY|durY|| v rY|||| < |j}|j}|j}	|j}
||ksvJ d|  d| d	| d
|
vsJ d|  d|	|
ksJ d|  d|	 d|
 |du |du A rJ d dS dS )az  
    Check whether the replaced outputs are consistent with origin outputs.

    Args:
    op_name (str): The name of operator.
    orig_outs (tuple): The outputs of original operator.
    new_outs (tuple): The outputs of replaced operator.
    orig_vars (dict): Origin variables of original block.
    dst_vars (list): Corresponding replaced variables of Origin variables.
    z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) = Nzop z2 should not contain any None value. original outs=z and its composite rule outs=z\ with composite rule, origin out dtype should be equal to new out dtype, but orig_out dtype=z and new_out dtype=r8   z1 with composite rule, composite out shape has -1.z\ with composite rule, origin out shape should be equal to new out shape, but orig_out shape=z and new_out shape=z"orig_out and new_out should match.)r   zipr
   Zops_contain_none
ValueErrorr   Zdtyper:   )op_namer   new_outs	orig_varsdst_varsZorig_outZnew_outZ
orig_dtypeZ	new_dtypeZ
orig_shapeZ	new_shaper   r   r   _check_op_resultsv   sd   




rD   c           
         s  t  s|S t| tstdt|  d|  }t ttfs*tdt  dtttfs;tdt dt j	d  B  t
d t dkr[tdkr[ fdd	}n*t dkrntdkrn fd
d	}nt dkrtdkrfdd	}ndd	 }dgt| }i }t|D ]\}}	t|	tjstdt|	 d| d|||	< qtj |  t|||| W d   n1 sw   Y  t|D ]"\}}	t|	tjs|	du r|| ||< qtdt|	 d| dqt
dt j	d  |S )a  
    Search nonbasic ops which have be registered composite rules and replace them with primitive ops.
    The operators in blacklist will be excluded from program when decomposed into primitives, and only the
    operators in whitelist will be decomposed. The priority of blacklist is higher than whitelist, it means
    an operator both in blacklist and whitelist will not be decomposed.

    The finally set that will be decomposed is:
        (block.ops & ops have decomposite rule & whitelist) - blacklist

    Note:
        All variables must be contained inside the given program.

    Args:
        program (Program): The program to be processed.
        src_vars (list[OpResult]): In program, once some operator is decomposed, its vars will be replaced by new ones. This argument means some vars will be used later and corresponding vars will be returned for later usage.
        blacklist (frozenset): The Operators that will be exclude when decomposed into primitives.
        whitelist (frozenset): Only the operators in whitelist will be decomposed into primitives.

    Returns:
        dst_vars (list): A list contains all vars which replace origin ones in src_vars.
    z"Expect type Program, but got type .z6Expected type of blacklisst is set|frozenset, but got z6Expected type of whiltelist is set|frozenset, but got Zforward_blacklistz(Decompose composite forward ops begin...r   c                    s   |   v o|    vS Nr   r-   	blacklist	whitelistr   r   <lambda>   r/   zdecompose.<locals>.<lambda>c                    s   |    vS rF   rG   rH   )rJ   r   r   rL          c                    s   |    v S rF   rG   rH   )rK   r   r   rL      rM   c                 S   s   dS )NTr   rH   r   r   r   rL      s    NzLEach var in dst_vars should map corresponding var in src_vars, but got type z in z*Decompose composite forward ops finish: {}composite_ops_record)r
   _is_fwd_prim_enabledr   r	   r   r   Zglobal_blockset	frozensetprim_configloggingdebugr   r   r   r   program_guard_decompose_subgraphformat)
programZsrc_varsrJ   rK   block	op_filterrC   Zdst_vars_dctr    r(   r   rI   r   	decompose   sj   


r[   c                 C   s  t | tr| j}d}t|D ]\}}| }t|}	t|}
|	s#|
o&||}|r3t	 r3t
|r3d}| dkr;|}|rtjd | |durY||d   dkrYt| nt| t|}| }|
rst|}t|||}nt|	| }t||||| | t v rtt|D ]}|t|  vr|| ||  qn| t v r|d |d  n|| | | |durd}| D ]
}| rd} nq|r| | d}qdS t | tjr| D ]	}t|||| qdS tdt |  )	a  
    The operators in block wich satisfy the filter conditon will be decomposed into primitives.

    Args:
        block (Block|Sequence[Block]): The blocks of program to be processed.
        op_filter (function): The filter to specify which ops to be processed.
        orig_vars (dict): Origin variables of original block.
        dst_vars (list): Corresponding replaced variables of Origin variables.
    NFr#   rN   r   r   Tz5Expect type Block or Sequence of Block, but got type )!r   r   opsr   r   r   get_decomp_ruler   r
   Z_enable_prim_dynamic_shaper=   rR   addr   set_insertion_pointr7   resultsr   r"   r   rD   r   r   ranger   replace_all_uses_with	remove_opZhas_one_user   r   rV   r   r   )rY   rB   rC   rZ   Zops_listZtemp_opr    r   r@   
decom_rulehas_sink_decomp_rulelower
input_argsr   r   rA   rc   r(   r   r   r   rV     s   







rV   c           	      C   s  t | tstdt|  t |tstdg }g }i }| jD ]}g }| D ]}| r3|| q(|||< q |D ]=}|	 D ]6}||| v rw||vrc|| || 
||
|gg qA||
| | 
||
|g qAq;t|t|fS )aP  
    This API checks which op contributes to the outputs of the entire computation graph,
    as well as determining the corresponding output index.

    Args:
        block (Block): the block of program to be processed.
        global_outputs (tuple(Value)): the outputs of the entire computation graph.

    Returns:
        related_ops (tuple(pir.Operation)): a tuple of op that contributes to the outputs of the entire graph.
        related_ops_output_indexes (tuple(tuple())) : a tuple records the mapping of tuple(the output index of the op,  the output index of the entire graph)
    z$block should be Block, but got type z)The type of global_outputs should be list)r   r   r   r   listr\   r`   r1   r   r   indexr   )	rY   global_outputsZrelated_opsrelated_ops_output_indexesZop_to_op_valid_resultr   Zop_valid_resultr-   Zglobal_outputr   r   r   get_leaf_ops\  sB   





	rl   c                 C   s&   || D ]}||d  | |d < qdS )z
    This API replace the outputs of the entire computation graph with the new outputs of the op,
    when the op contributes to the outputs of the entire computation graph.
    r   r   Nr   )rj   Z
op_outputsZop_indexrk   ri   r   r   r   replace_graph_outputs  s   
rm   rY   fwd_opgrad_var_to_var_mapreturnc                 C   s  t  stdtj | jr | }| }t	|}t
|}|p$|}|rtt|}t| |r=t|}	t||	|}
nt|| }
t|||
 | D ]\}}||v r^|
|| ||< qM||
 | | |
dfW  d   S t|dfW  d   S 1 sw   Y  dS )a  
    Decompose the fwd_op into a list of primitive ops.

    Args:
        block (Block): the block to which the fwd_op belongs.
        fwd_op (pir.Operation): the forward op to be decomposed.
        grad_var_to_var_map (dict): a dict obtained from distributed processing,
            which maps the backward grad variable to its corresponding forward variable.
    Returns:
        new_outputs (tuple(Value)): the new outputs after decomposing.
        has_decomposed: whether the forward op has been successfully decomposed.
    zRTo decompose forward op, please set `core._set_prim_forward_enabled(True)` firstlyTNF)r
   rO   RuntimeErrorr   rU   rX   r   r`   r   r]   r   r7   r_   r   r"   r   rD   itemsri   rb   rc   r   )rY   rn   ro   r@   r   rd   re   rf   rg   r   rA   Zgrad_varvarr   r   r   decompose_fwd_op  s@   




$rt   bwd_opc                    s  t  stddd   D }  }dd | D }| }g }g }	|D ]}
|
|v s8|
|v s8|	|
g q(dd |D } fddtd  D }g }|D ]}| r_|dg qR|d	g qR| j	
|}t| j	}t  |||	|}t| j	}|| }|d
kr| j	d  | kr| | j	d  dS |D ]}|d dur|d  r||d  q|t  qt|D ]\}}|| v r||||| < q|}t||D ]}| | j	| | |d
7 }q|| | | t|d	fS )ac  
    Decompose the bwd_op into a list of primitive ops.
    If fwd_op has composite vjp rules (including custom vjp), call call_vjp() to get a list of primitive operators in backward graph, then replace bwd_op.

    Args:
        block (Block): the block to which the bwd_op belongs.
        fwd_op (pir.Operation): the forward op.
        bwd_op (pir.Operation): the backward op to be decomposed.
        grad_var_to_var_map (dict): a dict obtained from distributed processing,
            which maps the backward grad variable to its corresponding forward variable.
    Return:
        new_input_grads (tuple(Value)): new results of backward op after decomposing.
        has_decomposed: whether the backward op has been successfully decomposed. If a fwd op does not have composite vjp rules and can not be decomposed directly, this function will return False.
    TTo decompose backward op, please set `core._set_prim_backward_enabled(True)` firstlyc                 S   r$   r   r%   r,   r   r   r   r)     r*   z-decompose_bwd_op_directly.<locals>.<listcomp>c                 S   r$   r   r%   r,   r   r   r   r)     r*   c                 S   s   g | ]}|gqS r   r   )r'   Z
fwd_outputr   r   r   r)     s    c                    s   g | ]}  |gqS r   )Zoperand_source)r'   irn   r   r   r)     s    r   FTr   r8   )NFN)r
   _is_bwd_prim_enabledrq   r0   r`   r   ra   Znum_operandsr1   r\   ri   r   Zcall_vjpr   rc   r   fake_op_resultr   r   popmove_oprb   r   )rY   rn   ru   ro   
fwd_inputsZfwd_outputs
bwd_inputsgrad_inputsr   grad_outputs	bwd_inputfwd_outputs_fwd_inputs_Zstop_gradients
grad_input
bwd_op_idxbefore_num_opsnew_grad_inputsafter_num_opsZnum_appended_opsr    
insert_idxrw   r   rx   r   decompose_bwd_op_directly  sd   






r   r}   fwd_outputs_after_decomposec                    sn  t  stddu rtddd | D }| }g }t fdd|D }	tfdd|	D }
tfd	d|D }| j|}t| j}t	
|
||	}t| j}d
}t|D ]\}}| rr|||  |d7 }q^|t  q^t|D ]\}}| v r||| < q~|}t||D ]}| | j| | |d7 }q|| | | t|S )a  
    Decompose the bwd_op into a list of primitive ops.
    If fwd_op has no composite vjp rules, and fwd_op has been decomposed to a list of primitive operators in forward graph previously,
    call grad() for the decomposed forward subgraph to get a list of primitive operators in backward graph, then replace bwd_op.

    Args:
        block (Block): the block to which the bwd_op belongs.
        fwd_op (pir.Operation): the forward op.
        bwd_op (pir.Operation): the backward op to be decomposed.
        grad_var_to_var_map (dict): a dict obtained from distributed processing,
            which maps the backward grad variable to its corresponding forward variable.
        fwd_inputs: (tuple(Value)): the original input of the forward op,
        fwd_outputs_after_decompose (tuple(Value)): the output of the decomposed forward op, if forward op has no vjp rules, forward op shoule be decomposed firstly,
            fwd_outputs_after_decompose means the new output of the decomposed forward op. If forward op has vjp rules, fwd_outputs_after_decompose is None.
    Return:
        new_input_grads (tuple(Value)): results of backward op after decomposing.
    rv   Nz=To decompose backward op, please decompose forward op firstlyc                 S   r$   r   r%   r,   r   r   r   r)   V  r*   z1decompose_bwd_op_after_fwd_op.<locals>.<listcomp>c                 3   s$    | ]}| v s|v s|V  qd S rF   r   )r'   r   )r}   r   r   r   	<genexpr>[  s    z0decompose_bwd_op_after_fwd_op.<locals>.<genexpr>c                 3   s    | ]} | V  qd S rF   r   )r'   Zgrad_outputro   r   r   r   b  s    
c                 3   s     | ]}|  r | V  qd S rF   )r1   )r'   r   r   r   r   r   e  s    
r   r   )r
   ry   rq   r0   r`   r   r\   ri   r   r   Zgradr   r1   r   r   rz   r   r{   ra   r|   rb   rc   )rY   rn   ru   ro   r}   r   r~   r   r   r   r   r   r   r   r   r   Zinput_grads_idxr    r   r   rw   r   )r}   r   ro   r   decompose_bwd_op_after_fwd_op2  sR   





r   )NN)"rS   r   r;   Zpaddler   Zpaddle.autogradr   Zpaddle.base.corer   r   r   Zpaddle.base.libpaddle.pirr   r   r	   Zpaddle.frameworkr
    r   r   r"   r7   r=   rD   rQ   r[   rV   rl   rm   dictr   rt   r   r   r   r   r   r   <module>   sp   !
;
WW5
7
\