U
    Mh';                     @  s  d Z ddlmZ ddlZddlZddlZddlmZmZmZm	Z	m
Z
mZmZmZmZ ddlZddlmZ ddlmZ ddlmZ ddlmZmZ ed	Zd
dhZejG dd dZejddddddddddddZejdddddddddZ ejddddZ!dGd dd!d"d"ddd#d$d%	d&d'Z"ejd(d) Z#ejd*d+d,d-Z$ejd#d.d/d0Z%ejd$dd1d#d2d3d4Z&ejdd#d5d6d7Z'ejdd8d9d:d;Z(ejdd<d=d>d?Z)ejdd#d@dAdBZ*ejdd#d@dCdDZ+ejdd#d@dEdFZ,dS )HzFUtilities for manipulating the torch.Graph object and the torchscript.    )annotationsN)	AnyDictIterableListOptionalSequenceSetTupleUnion)_C)_onnx)GLOBALS)	_beartyperegistrationz^(.+)_(([ifstgz])|(ty))$Zinplaceatenc                   @  s   e Zd ZU dZded< ded< ded< ded	< d
ed< ded< ded< ejedZded< dddddZ	e
jddddddddZe
jddddd d!d"ZeZe
jddddd#d$d%Zd&S )'GraphContexta  Extra context for symbolic functions with all methods from torch.Graph.

    NOTE: This class is not meant for external consumption. Please do not depend on
    it outside of torch.onnx as the interface may evolve.

    Attributes:
        graph: The _C.Graph being constructed.
        block: The current _C.Block being constructed.
        opset: The opset version.
        original_node: Current node that is being converted from.
        params_dict: Mapping from graph initializer name to IValue.
        env: Mapping from Torch domain graph Value to ONNX domain graph Value.
        values_in_env: Set of all values in env, for constant-time lookups.
        new_nodes: List that tracks all new nodes that are added (used to make
            sure metadata is propagated to all new nodes).
    z_C.Graphgraphz_C.Blockblockintopset_C.NodeZoriginal_nodezDict[str, '_C.IValue']params_dictzDict[_C.Value, _C.Value]envzSet[_C.Value]Zvalues_in_env)default_factoryzList[_C.Node]	new_nodesstrr   )namereturnc                 C  s   t | j|S N)getattrr   )selfr    r"   P/var/www/html/venv/lib/python3.8/site-packages/torch/onnx/_internal/jit_utils.py__getattr__6   s    zGraphContext.__getattr__   outputsUnion[torch.Tensor, _C.Value])opnameraw_argsr'   c                O  s   t | |f|d|i|S )a  Creates an ONNX operator "opname", taking "raw_args" as inputs and "kwargs" as attributes.

        The set of operators and the inputs/attributes they take
        is documented at https://github.com/onnx/onnx/blob/master/docs/Operators.md

        Args:
            opname: The ONNX operator name, e.g., `Abs` or `Add`, or an operator qualified
                with a namespace, e.g., `aten::add`.
            raw_args: The inputs to the operator; usually provided
                as arguments to the `symbolic` definition.
            outputs: The number of outputs this operator returns.
                By default an operator is assumed to return a single output.
                If `outputs` is greater than one, this functions returns a tuple
                of output `Value`, representing each output of the ONNX operator
                in order.
            kwargs: The attributes of the ONNX operator, whose keys are named
                according to the following convention: `alpha_f` indicates
                the `alpha` attribute with type `f`.  The valid type specifiers are
                `f` (float), `i` (int), `s` (string) or `t` (Tensor).  An attribute
                specified with type float accepts either a single float, or a
                list of floats (e.g., you would say `dims_i` for a `dims` attribute
                that takes a list of integers).

        Returns:
            The value representing the single output of this operator (see the `outputs`
            keyword argument for multi-return nodes).
        r'   )_add_op)r!   r)   r'   r*   kwargsr"   r"   r#   op9   s    $zGraphContext.op )overload_name)operatorr/   c                O  s   | j d|||d|S )z~Generates an ONNX ATen op node.

        This function is for backward compatibility with the old symbolic functions.
        
aten::ATen)Z
operator_sZoverload_name_s)r1   )r-   )r!   r0   r/   argsr,   r"   r"   r#   aten_op_   s     zGraphContext.aten_op)r*   r'   c                O  sF   |j j d|j }|j j}t||| t| |f|d|i|S )a  Creates an ONNX operator from onnx-script function, taking "raw_args" as inputs and "kwargs" as attributes.

        onnx-script repository: https://github.com/microsoft/onnx-script

        Args:
            onnx_fn: ONNXFunction from onnx-script; An example can be found at
                https://github.com/microsoft/onnx-script#example
            raw_args: The inputs to the operator; usually provided
                as arguments to the `symbolic` definition.
            outputs: The number of outputs this operator returns.
                By default an operator is assumed to return a single output.
                If `outputs` is greater than one, this functions returns a tuple
                of output `Value`, representing each output of the ONNX operator
                in order.
            kwargs: The attributes of the ONNX operator, whose keys are named
                according to the following convention: `alpha_f` indicates
                the `alpha` attribute with type `f`.  The valid type specifiers are
                `f` (float), `i` (int), `s` (string) or `t` (Tensor).  An attribute
                specified with type float accepts either a single float, or a
                list of floats (e.g., you would say `dims_i` for a `dims` attribute
                that takes a list of integers).

        Returns:
            The value representing the single output of this operator (see the `outputs`
            keyword argument for multi-return nodes).
        ::r'   )r   domainr   versionr   Zcustom_onnx_symbolicr+   )r!   Zonnx_fnr'   r*   r,   Zsymbolic_nameopset_versionr"   r"   r#   onnxscript_opq   s    $zGraphContext.onnxscript_opN)__name__
__module____qualname____doc____annotations__dataclassesfieldlistr   r$   r   beartyper-   r3   atr8   r"   r"   r"   r#   r      s&   
%r   r%   )r'   n_blocksr   z_C.Valuer   z-Tuple[Any, Tuple[GraphContext, ...], _C.Node])graph_contextr)   inputsr'   rC   r   c                O  sz   | j |f|d|i|}t|tr2|d  }n| }g }t|D ]$}	| }
tj| |
d}|| qF|t	||fS )aP  Creates an ONNX operator "opname", taking inputs and attributes.

    Args:
        graph_context: The context for the current graph.
        opname: The ONNX operator name, e.g., `Abs` or `Add`, or an operator qualified
            with a namespace, e.g., `aten::add`.
        inputs: The inputs to the operator.
        outputs: The number of outputs this operator returns.
            By default an operator is assumed to return a single output.
            If `outputs` is greater than one, this functions returns a tuple
            of output `Value`, representing each output of the ONNX operator
            in order.
        n_blocks: The number of sub-blocks to create in the node.
        attributes: The attributes of the ONNX operator.

    Returns:
        A tuple of (output_values, new_contexts, node) where:
            output_values: One or more output value of this operator
                (see the `outputs` keyword argument for multi-return nodes).
            new_contexts: A tuple of new graph contexts for each sub-block.
            node: The node representing the operator.
    r'   r   )r   )
r-   
isinstancer   noderangeZaddBlockr>   replaceappendtuple)rD   r)   r'   rC   rE   
attributesZoutput_valuesrG   Znew_contexts_Z	new_blockZnew_contextr"   r"   r#   add_op_with_blocks   s     
rN   r&   r(   )rD   r)   r2   r'   c             
     s|    fdd|D }dd |  D }d|kr4d| }t j||| j j|tjd} j| |dkrp|	 S t
| S )	a@  Creates an ONNX operator "opname", taking "args" as inputs and attributes "kwargs".

    The set of operators and the inputs/attributes they take
    is documented at https://github.com/onnx/onnx/blob/master/docs/Operators.md

    This function is monkey-patched onto Graph.

    Args:
        graph_context: The Torch Graph or Block.
        opname: The ONNX operator name, e.g., `Abs` or `Add`, or an operator qualified
            with a namespace, e.g., `aten::add`.
        args: The inputs to the operator; usually provided
            as arguments to the `symbolic` definition.
        outputs: The number of outputs this operator returns.
            By default an operator is assumed to return a single output.
            If `outputs` is greater than one, this functions returns a tuple
            of output `Value`, representing each output of the ONNX operator
            in order.
        kwargs: The attributes of the ONNX operator, whose keys are named
            according to the following convention: `alpha_f` indicates
            the `alpha` attribute with type `f`.  The valid type specifiers are
            `f` (float), `i` (int), `s` (string) or `t` (Tensor).  An attribute
            specified with type float accepts either a single float, or a
            list of floats (e.g., you would say `dims_i` for a `dims` attribute
            that takes a list of integers).

    Returns:
        (Union[_C.Value, Tuple[_C.Value, ...]])
        The value representing the single output of this operator (see the `outputs`
        keyword argument for multi-return nodes).
    c                   s   g | ]}t  |qS r"   )_const_if_tensor).0argrD   r"   r#   
<listcomp>   s     z_add_op.<locals>.<listcomp>c                 S  s   i | ]\}}|d k	r||qS r   r"   )rP   kvr"   r"   r#   
<dictcomp>   s       z_add_op.<locals>.<dictcomp>r4   zonnx::)r   r7   	n_outputsshape_inferencer%   )items_create_noder   r   r   r   Zonnx_shape_inferencer   rJ   outputrK   r'   )rD   r)   r'   r2   r,   rE   rL   rG   r"   rR   r#   r+      s$    '
r+   rR   c                 C  s*   |d kr|S t |tjr|S t| d|dS )Nzonnx::Constant)Zvalue_z)rF   r   Valuer+   )rD   rQ   r"   r"   r#   rO     s
    rO   TzUnion[_C.Graph, _C.Block]r   dictboolr   )	graph_or_block	domain_oprE   rL   r   r7   rW   rX   r   c                 C  s   t | tjr*| }||||}	||	}	n<t | tjrf| }
|
||}	|dkrftd|D ]}|	  qXt	|	
 }t||kst|d}t| D ]"\}}|tkrqt|	|||d q|rt|	|| |	S )z:Creates an node 'domain_op', taking inputs and attributes.r%   zaten::)r   )rF   r   ZGraphcreateZ
insertNodeZBlockZaddNoderH   Z	addOutputrK   r'   lenAssertionError
startswithsortedrY   _SKIP_NODE_ATTRIBUTES_add_attributeZ(_jit_pass_onnx_node_shape_type_inference)r_   r`   rE   rL   r   r7   rW   rX   r   rG   r   rM   Znode_outputsr   keyvaluer"   r"   r#   rZ     s(    

rZ   c                 C  s   t | tot | tttjf S r   )rF   r   r   bytestorchTensor)ri   r"   r"   r#   _is_onnx_list>  s     
rm   ztorch.Tensorxc                 C  s   |   dkst| d S )z,Convert a scalar tensor into a Python value.r%   r   )numelrc   rn   r"   r"   r#   _scalarE  s    rq   )r   c                   C  s   t jtjjkotjS r   )r   Zoperator_export_type_C_onnxZOperatorExportTypesZONNX_ATEN_FALLBACKZ_CAFFE2_ATEN_FALLBACKr"   r"   r"   r#   _is_caffe2_aten_fallbackL  s    rs   r   )rG   rh   ri   r   c                 C  s   t |}|dkr"td| d|d|d }}t|rH|d7 }|rt rt|tjr|	 dkrrtdt
|}t|trd}nd	}t| | d
||S )z7Initializes the right attribute based on type of value.NzInvalid attribute specifier 'z<' names must be suffixed with type, e.g. 'dim_i' or 'dims_i'r%      sz Should not pass tensor attributefirM   )_ATTR_PATTERNmatch
ValueErrorgrouprm   rs   rF   rk   rl   rp   rq   floatr    )rG   rh   ri   r   mr   kindr"   r"   r#   rg   T  s"    



rg   )ro   r   c                 C  s   |   tj S r   )typeZisSubtypeOfr   
TensorTypegetrn   r"   r"   r#   
_is_tensoro  s    r   zOptional[torch.device])ri   r   c                 C  s&   t | sd S ttj|  }| S r   )r   typingcastr   r   r   Zdevice)ri   Ztensor_typer"   r"   r#   get_device_from_valuet  s    r   zTuple[str, str])r~   r   c                 C  sH   d| krt d|  d| dd\}}d|kr@t d|  d||fS )z(Parse node kind into domain and Op name.r4   zNode kind: z& is invalid. '::' is not in node kind.r%   z) is invalid. '::' should only apear once.)rz   split)r~   r5   r)   r"   r"   r#   parse_node_kind|  s    r   )r5   r   c                 C  s   | dkS ) Check if the domain is official.r   r"   r5   r"   r"   r#   is_aten  s    r   c                 C  s   | dkS )r   Zprimr"   r   r"   r"   r#   is_prim  s    r   c                 C  s   | dkS )r   Zonnxr"   r   r"   r"   r#   is_onnx  s    r   )T)-r<   
__future__r   r>   rer   r   r   r   r   r   r   r	   r
   r   rk   r   Ztorch._Cr   rr   Ztorch.onnx._globalsr   Ztorch.onnx._internalr   r   compilerx   rf   	dataclassr   rA   rN   r+   rO   rZ   rm   rq   rs   rg   r   r   r   r   r   r   r"   r"   r"   r#   <module>   s\   ,
 /?  '

