o
    "jp                     @  s,  d dl mZ 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
 d dl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lmZ d
dlmZmZmZmZ d
dlmZ g Zdd Z dd Z!dfddZ"dd Z#dd Z$dd Z%	dgd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.d/ Z0d0d1 Z1d2d3 Z2	dfd4d5Z3d6d7 Z4d8d9 Z5d:d; Z6d<d= Z7d>d? Z8d@dA Z9dBdC Z:G dDdE dEZ;dFdG Z<dHdI Z=dJdK Z>dLdM Z?dNdO Z@dhdQdRZAdSdTddUdVdWdXZBdYdZ ZCe	[			\	]	[did^d_ZDd`da ZEdbdc ZFddde ZGdS )j    )annotationsN)contextmanager)PyLayerMeta)convert_dtype)_convert_into_variablein_to_static_mode)Variablecoredefault_main_program)Value)
AmpOptions   )StaticPyLayer)RETURN_NO_VALUE_VAR_NAMEDygraph2StaticExceptionGetterSetterHelperUndefinedVar)to_static_variablec                 C  s$   t | tr|dkr|  S t| |S )Nsize)
isinstancer   r   getattr)xattr r   g/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/jit/dy2static/convert_operators.pyconvert_attr)   s   
r   c                 C  s   t  rat| tjr	 t| S t| trt| S t| tr6t 	 }ddl
m} ||jt| }|d ur6|S t| trYt 	 }ddlm} | j|j| j }|d urY|S | tjju ratS | S )Nr   )_global_inplace_mapProgramTranslator)r   r   paddleZTensorr   r   r   r   r
   current_blockZ+paddle.jit.pir_dy2static.parameter_recorderr   getprogramidr   'paddle.jit.dy2static.program_translatorr   get_instance_inplace_mapdescampZ	auto_castconvert_auto_cast)r   Z	cur_blockr   Znew_varr   r   r   r   convert_load4   s.   





r*   c                 C  sD   t | ttfr	| S t| drt| S t| drt| dr| S td)N__iter____len____getitem__z"X can't be convert into indexable.)r   r   r   hasattrlistRuntimeError)r   coder   r   r   	indexable_   s   
r2   c                 C  s"   t | ttfrt| |S t| |S )z/unified unpack interface for paddle and python.)r   r   r   _unpack_by_structure_paddle_unpack_by_structure_pythontarget	structurer   r   r   unpack_by_structurel   s   

r8   c                 C  s
   t | |S )zJTODO(xiongkun): analysis the differences between python and paddle unpack.)r3   r5   r   r   r   r4   t   s   
r4   c                 C  sd   |dkr| S g }t |D ]#\}}|dkr|| |  qt|tr,|t| | | qtd|S )Nr   z#structure element must be 1 or list)	enumerateappendr   r/   r8   AssertionError)r6   r7   retidxZeler   r   r   r3   y   s   
r3   c                 C  s<   |  }t |ttfrt| ||||| dS t| ||| dS )a  
    A function representation of a Python ``while`` statement.

    Args:
        cond(Callable): A callable object that returns a boolean variable to control whether to execute the loop body. It takes ``loop_vars`` as arguments.
        body(Callable): A callable object that returns a tuple or list of variables with the same arguments ``loops_vars`` as ``cond`` .
        get_args(callable): Get all arguments that needed in true_fn and false_fn.
        set_args(callable): Update arguments that modified in trure_fn and false_fn.
        return_name_ids(list[string], optional): the returned names.
        push_pop_names(list[string], optional): the names on which called .append() or .pop().

    Returns:
        A list or tuple of variables which returned by ``body``.
    N)r   r   r   _run_paddle_while_run_py_while)condbodygettersetterreturn_name_idspush_pop_namespredr   r   r   convert_while_loop   s   rG   c                   s<   |  |}|d u rd S dd  | | fdd|D  d S )Nc                 S  s   t | trtjjd| dS | S )Nfloat32)Zinitialized_list)r   r/   r   tensorcreate_array)vr   r   r   maybe_to_tensor_array   s   
zB_convert_tensor_arrray_if_necessary.<locals>.maybe_to_tensor_arrayc                   s   g | ]} |qS r   r   ).0rK   rL   r   r   
<listcomp>   s    z7_convert_tensor_arrray_if_necessary.<locals>.<listcomp>)r!   set)ZsetterhelperrE   Zpush_pop_varsr   rN   r   #_convert_tensor_arrray_if_necessary   s   
rQ   c           
        s   t ||||t| |rt|nt |rt|nt B t fdd}fdd}dd D }| ddlm}	 |	|||}| |S )	Nc                    s    | } |    S )zlwrap the body() and add return value for `while_loop`
        the args may be differ from getter().
        )rP   r!   )argsZmutable_loop_vars)rA   helper
union_namer   r   new_body_fn   s   
z&_run_paddle_while.<locals>.new_body_fnc                    s     S )zYcond is a zero-args function, which is not
        compatible with `while_loop`.
        r   )rR   )r@   r   r   new_cond_fn   s   z&_run_paddle_while.<locals>.new_cond_fnc                 S  s"   g | ]}t |tst|n|qS r   )r   r   r   )rM   varr   r   r   rO      s    z%_run_paddle_while.<locals>.<listcomp>r   
while_loop)r   rQ   rP   r/   r!   paddle.static.nnrY   )
r@   rA   rB   rC   rD   rE   rU   rV   Z	loop_varsrY   r   )rA   r@   rS   rT   r   r>      s    
	r>   c                 C  s.   	 |  }t |ttfrtd|sd S |  q)NTz/python while pred change from bool to variable.)r   r   r   r   )r@   rA   rB   rC   rF   r   r   r   r?      s   r?   c                   ^   |   t  ttfst fdd|S | t ttfs*tfdd fddS t S )a  
    A function representation of a Python ``and`` statement.

    Args:
        x_func(callable): x_func() is the left hand operand of ``and`` operator. x_func() is bool or Tensor.
        y_func(callable): y_func() is the right hand operand of ``and`` operator.  y_func() is bool or Tensor.

    Returns:
        A python bool variable or a bool Tensor.

    NOTE(liym27):
        1) The operands are executed sequentially according to the running logic of Python. So here the arguments
        should be callable.
        2) If the left hand operand is False, the right hand operand should be executed.

        For example:
            a = x > 1 and y < 1
        Transformed code:
            a = paddle.jit.dy2static.convert_logical_and(lambda:x>1, lambda:y<1)

          In `convert_logical_and(lambda:x>1, lambda:y<1)`, `lambda:y<1` must be run after `lambda:x>1`. And
        if `x>1` is False, `y<1` should NOT be run.
    c                         S Nr   r   x_valuer   r   <lambda>      z%convert_logical_and.<locals>.<lambda>c                     r\   r]   r   r   y_valuer   r   r`     ra   c                     r\   r]   r   r   r^   r   r   r`     ra   )r   r   r   _run_py_logical_and_run_paddle_logical_andx_funcy_funcr   r_   rc   r   convert_logical_and      
rj   c                 C     t | } t |}t| |S r]   )cast_bool_if_necessaryr   logical_andr   yr   r   r   re        re   c                 C  s"   |  }t |ttfrJ |o| S r]   r   r   r   rg   rh   r_   r   r   r   rd        
rd   c                   r[   )a  
    A function representation of a Python ``or`` statement.

    Args:
        x_func(callable): x_func() is the left hand operand of ``or`` operator. x_func() is bool or Tensor.
        y_func(callable): y_func() is the right hand operand of ``or`` operator.  y_func() is bool or Tensor.

    Returns:
        A python bool variable or a bool Tensor.

    NOTE(liym27):
        1) The operands are executed sequentially according to the running logic of Python. So here the arguments
        should be callable.
        2) If the left hand operand is True, the right hand operand should be executed.

        For example:
            a = x > 1 or y < 1
        Transformed code:
            a = paddle.jit.dy2static.convert_logical_or(lambda:x>1, lambda:y<1)

        In `convert_logical_or(lambda:x>1, lambda:y<1)`, `lambda:y<1` must be run after `lambda:x>1`. And
        if `x>1` is True, `y<1` should NOT be run.
    c                     r\   r]   r   r   r^   r   r   r`   7  ra   z$convert_logical_or.<locals>.<lambda>c                     r\   r]   r   r   rb   r   r   r`   ;  ra   c                     r\   r]   r   r   r^   r   r   r`   ;  ra   )r   r   r   _run_py_logical_or_run_paddle_logical_orrf   r   ri   r   convert_logical_or  rk   rw   c                 C  rl   r]   )rm   r   
logical_orro   r   r   r   rv   @  rq   rv   c                 C  s"   |  }t |ttfrJ |p| S r]   rr   rs   r   r   r   ru   F  rt   ru   c                 C  s   t | ttfrt| S t| S )z
    A function representation of a Python ``not`` statement.

    Args:
        x(bool|Tensor): Operand of ``not`` operator.

    Returns:
        A python bool variable or a bool Tensor.
    )r   r   r   _run_paddle_logical_not_run_py_logical_notr   r   r   r   convert_logical_notP  s   r|   c                 C  s   t | } t| S r]   )rm   r   Zlogical_notr{   r   r   r   ry   a  s   
ry   c                 C  s   |  S r]   r   r{   r   r   r   rz   f     rz   c                 C  s<   t | ttfrt| ||||||}|S t| |||||}|S )a  
    A function representation of a Python ``if/else`` statement.

    Args:
        pred(bool|Tensor): A boolean Tensor which determines whether to return the result of ``true_fn`` or ``false_fn`` .
        true_fn(callable): A callable to be performed if ``pred`` is true.
        false_fn(callable): A callable to be performed if ``pred`` is false.
        get_args(callable): Get all arguments that needed in true_fn and false_fn.
        set_args(callable): Update arguments that modified in trure_fn and false_fn.
        return_name_ids(list[string], optional): the returned names.
        push_pop_names(list[string], optional): the names on which called .append() or .pop().

    Returns:
        ``true_fn()`` if the predicate ``pred`` is true else ``false_fn()`` .

    )r   r   r   _run_paddle_cond_run_py_ifelse)rF   true_fnfalse_fnget_argsset_argsrD   rE   outr   r   r   convert_ifelsej  s   r   c              
     sX  t |||t| t| } ddlm} | jddu r-|du r-dnr3tnt |r;t|nt B t	fdd} fdd}	zt
jj| ||	d}
W n0 ty } z$tdt|rtd	t| td
t|rtdt| |d}~ww fdd}fdd}t|
||S )zH
    Paddle cond API will evaluate both true_fn and false_fn codes.
    r   r   Nc                    sB     }  tj  }|d u r }|  |S r]   Zsave_checkpointrP   r   utilsZcopy_mutable_varsr!   Zrestore_checkpointZinplace_map_checkpointr<   )rS   	init_argsinplace_maprD   r   rT   r   r   new_true_fn  s   


z%_run_paddle_cond.<locals>.new_true_fnc                    sB     } tj   }|d u r}|  |S r]   r   r   )r   rS   r   r   rD   rT   r   r   new_false_fn  s   


z&_run_paddle_cond.<locals>.new_false_fnz7Unsupported return type of true_fn and false_fn in condzDYour if/else have different return type. TODO: add link to modifty. zIncompatible return values ofzOYour if/else have different number of return value. TODO: add link to modifty. c                     s
     S r]   )r!   r   rS   rT   r   r   r`     s   
 z"_run_paddle_cond.<locals>.<lambda>c                   s     | S r]   )rP   )vsr   r   r   r`         )r   rQ   rm   r!   r$   r   r%   r&   rP   r/   r   staticnnr@   	Exceptionresearchstrr   _recover_args_state)rF   r   r   r   r   rD   rE   r   r   r   Z	cond_outser   )r   rS   r   r   rD   r   rT   r   r~     sL   



r~   c                 C  s   | r| }|S | }|S )z;
    Evaluate python original branch function if-else.
    r   )rF   r   r   r   r   rD   Zpy_outsr   r   r   r     s   
r   c                 C  s
  t | trt| dkr| }| d }t |trXt|D ]=\}}t |ttfrWt|jv rW|dkr7d| dd   }n|dkrH|d d | dd   }n|d | f| dd   } nqt|D ]\}}t |ttfrrt|jv rr|d | }q\|swd S t|dkr|d S |S | S )Nr   r]   r   )r   tuplelenr9   r   r   r   name)r   Zprocessed_outZ	align_retindexitemr   r   r   _remove_no_value_return_var  s2   


r   c                 C  sV   |d u rd S t | ttfs| g} tt| |D ]\}}t |tr(td||qd S )Nz_Required '{}' must be initialized both in if-else branch, but found it not initialized in '{}'.)r   r/   r   zipr   
ValueErrorformat)outsnamesbranch_namerW   r   r   r   r   _check_no_undefined_var  s   
r   c                 C  s   |du r| S | }t |}t |}||ksJ |dkr*t| ttfs%| fnt| }n|dkr1| fnt| } | ||d  }|| |S )z
    Currently we support variant length of early return statement by padding
    _no_return_value.

    # TODO(dev): We shall consider to evaluate whether should support this for Python if-else?
    Nr   )r   r   r/   r   )r   r   r   rD   r   Znum_outsnum_argsZ
final_outsr   r   r   r     s   r   c                 C  s8  t | trL| jdksJ d| jtjjjtjjjfv r6| j	d dkr/| jtjjjkr/| j	d S t
	| d S | jtjjjkrDt
j| S tdt|  t | tr|  sY|  ry| jdksbJ d| j	d dkrr|  rr| j	d S t
	| d S |  rt
j| S tddt|  d t | tr|  S t| S )z
    Returns variable(length) from shape ops based on var.type

    Note: In addition to some ast transformations, some block-related
          operations are added in `len` transformation, such as appending
          `shape_op` in var.block.
    r   zlen() of a 0-D tensor is wrongzNlen(var) only supports LoDTensor/LoDTensorArray/SelectedRows, but received %s.zBlen(var) only supports DenseTensor/DenseTensorArray/SelectedRows, zbut received .)r   r   ndimtyper	   VarDescVarTypeZ
LOD_TENSORZSELECTED_ROWSshaper   LOD_TENSOR_ARRAYrI   array_length	TypeErrorr   Zis_dense_tensor_typeZis_selected_row_typeZis_dense_tensor_array_typeVariableTupler,   r   rW   r   r   r   convert_len9  s@   




r   c                  G  sJ   t | D ]\}}t|ttfr |jd dkr tdt| dqt|  S )Nr   zHNot support zip(tensor, ...) when tensor.shape[0] == -1, but found args[z].shape[0] == -1 in 'zip')r9   r   r   r   r   r0   r   r   )rR   iargr   r   r   convert_zipj  s   r   c                   @  s*   e Zd ZdZd
ddZdd Zdd Zd	S )r   z
    this class will cause enumerate can't be wrapped by other iterator change function.
    this will be fixed when list<Variable> is producted.
    VariableTuple can only deal with variables which is fixed.
    r   c                 C  sT   || _ t|| _t| jttfrt||| j dtj| _	d S t
||| j | _	d S )Nr   )rW   r   r   r   r   r   r   arangeint64ragrange)selfrW   startr   r   r   __init__|  s
   
zVariableTuple.__init__c                 C  s   | j | | j| fS r]   )r   rW   )r   r=   r   r   r   r-     s   zVariableTuple.__getitem__c                 C  s   | j S r]   )r   )r   r   r   r   r,     r}   zVariableTuple.__len__N)r   )__name__
__module____qualname____doc__r   r-   r,   r   r   r   r   r   u  s
    
r   c                  G  s&   t dd | D }|rt|  S t|  S )Nc                 s      | ]
}t |ttfV  qd S r]   rr   rM   r   r   r   r   	<genexpr>      z$convert_enumerate.<locals>.<genexpr>)anyr   r9   rR   Zhas_variabler   r   r   convert_enumerate  s   r   c                  G  s   t dd | D }|rAt| dkrtd| d ddS t| dkr-t| d | d ddS t| dkrAt| d | d | d dS t|  S )Nc                 s  r   r]   rr   r   r   r   r   r     r   z convert_range.<locals>.<genexpr>r   r   r         )r   r   r   r   r   r   r   r   r   convert_range  s   r   c                 C  sj   dd }t | ttfr2t| j}||r0t| }t|D ]\}}|du s)|dk r/|| ||< q|S | jS )z=
    A function representation of the shape of variable.
    c                 S  s   t dd | D S )Nc                 s  s    | ]}|d k V  qdS )r   Nr   r   r   r   r   r     s    z6convert_shape.<locals>.has_negative.<locals>.<genexpr>)r   )Z
list_shaper   r   r   has_negative  s   z#convert_shape.<locals>.has_negativeNr   )r   r   r   r/   r   r   r9   )r   r   valuesZshape_tensorr   rK   r   r   r   convert_shape  s   	

r   c                 C  s2   t | ttfs	J t| jdvrtj| dd} | S )N)boolr   dtype)r   r   r   r   r   r   castr   r   r   r   rm     s   rm   c                 C  s   t | ttfr4t| j}|dv sJ d| j||dv s%J d| ddddd}tj| || d	S |dv s@J d| dt	|| S )
N)r   float16rH   Zfloat64int32r   Zuint8zAThe dtype of var {} is {}, which is not supported in the cast op.)r   intfloatzThe casted target dtype is z), which is not supported in type casting.r   r   rH   r   )
r   r   r   r   r   r   r   r   r   eval)rW   r   Z	src_dtypeZcast_mapr   r   r   convert_var_dtype  s&   





r    c                 C  s>   t | ttfrt| d} ddlm} || S | sJ |dS )zE
    A function representation of a Python ``assert`` statement.
    r   r   )AssertN)r   r   r   r   r   Zpaddle.static.nn.control_flowr   )r@   messager   r   r   r   convert_assert  s
   r    
Fsependfileflushc                 G  s<   |D ]}t |ttfrtj| qt|| |||d dS )z
    A function representing Python ``print`` function. It will print all arguments
    at compile time and only print the Tensor values at runtime.
    r   N)r   r   r   r   r   ZPrintprint)r   r   r   r   objectsobjr   r   r   convert_print  s
   r   c                 G  sJ   t | ttf}|r| jtjjjk}|r|rt| g|R  S t	| g|R  S )a  
    A function representation of a Python pop statement for a list or dict.

    Args:
        target(list|dict|Tensor): A variable to pop item from.
        *args(tuple): index or default value to parse.

    Returns:
        A item poped from target.
    )
r   r   r   r   r	   r   r   r   _run_paddle_pop_run_python_pop)r6   rR   Zis_variableZis_tensor_arrayr   r   r   convert_pop  s   r   TO1r   c                 c  s    ddl m} td | j}tj }|j	}	|
 }
t|
j}t| |||||}d V  t|
j}|	|vr;g ||	< ||	 |||f d S )Nr   r   zopaddle.amp.auto_cast is an experimental features in auto parallel.This will take no effect in normal dy2static.)Zprogram_translatorr   warningswarnr%   Z_amp_recordsr   r   r
   current_block_idxr    r   opsr   r:   )enableZcustom_white_listZcustom_black_listlevelr   Zuse_promoter   Zamp_recordsZmain_programr   r    Zstart_op_idxZamp_optionsZ
end_op_idxr   r   r   r)     s(   	



r)   c                   s   t |dkr	d}n|d }t|tsJ  fdd}fdd}tj |dk r/|  }nddlm} |dgd	|d
}tj|}t	}t
|d|}|d }	ddlm}
 |
|||	|g\}}tj	|d |S )Nr   r   c                   s   t |  S r]   )r   	less_than)r   	new_array)arr_lenr   r   r@   9  s   z_run_paddle_pop.<locals>.condc                   s:   t jj | d}t j|t j|| t | } | |fS )N)arrayr   )r   rI   
array_readZarray_writer   	increment)r   r   r   )r   r   r   rA   <  s   
z_run_paddle_pop.<locals>.body)fill_constantr   r   )r   r   valuerX   )output)r   r   r   r   rI   r   Zpaddle.tensorr   r   Zassign_slice_tensor_arrayrZ   rY   )r   rR   r=   r@   rA   r   Zpop_itemtmpr   r   rY   _r   )r   r   r   r   1  s&   	

r   c                   s8   dd }dd t jjk| fdd}|S )Nc                  S  s   t jd} | S )NrH   )r   rI   rJ   )Z
null_arrayr   r   r   r   ]  s   z$_slice_tensor_array.<locals>.true_fnc                 S  s   t j| |g|gdgd}|S )Nr   )ZstartsZendsZaxes)r   slice)r   r   r   r   r   r   r   r   a  s   z%_slice_tensor_array.<locals>.false_fnc                     s    S r]   r   r   r   r   r   r   r   r   r`   f  r   z%_slice_tensor_array.<locals>.<lambda>)r   r   r   r@   )r   r   r   r   r   r   r   r   r   \  s   r   c                 G  s:   t |dkr|\}}| ||S |r|d nd}| |S )Nr   r   r   )r   pop)r6   rR   r=   defaultr   r   r   r   k  s
   
r   r]   )NN)r   )TNNr   r   T)H
__future__r   r   r   
contextlibr   r   Zpaddle.autograd.py_layerr   Zpaddle.base.data_feederr   Zpaddle.base.dygraph.baser   r   Zpaddle.base.frameworkr   r	   r
   Z
paddle.pirr   Zpaddle.static.amp.fp16_utilsr   Zpy_layerr   r   r   r   r   r   Zvariable_trans_funcr   __all__r   r*   r2   r8   r4   r3   rG   rQ   r>   r?   rj   re   rd   rw   rv   ru   r|   ry   rz   r   r~   r   r   r   r   r   r   r   r   r   r   rm   r   r   r   r   r)   r   r   r   r   r   r   r   <module>   s   
+
)#
#

+L
#1
" +