a
    8Sic                     @  s  d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	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 ddlZddlm  mZ ddlZddlZddlmZ ddlmZmZmZmZm Z  ddl!m"Z" da#d	d
 Z$i Z%ej&dd Z'ej&dd Z(ej&dd Z)ej&dd Z*dddddej+j,ddddddfddZ-dd Z.dd Z/ddddddddZ0d d! Z1d"d# Z2d$dd%d&d'd(Z3d)d* Z4d+d, Z5d-d.d/d0Z6d1d2 Z7dd3d4Z8d5d6 Z9d7d8 Z:d9d: Z;d;d< Z<d=d> Z=d?d@ Z>ej?ej@ejAejBejCejDejEejBiZFdAdB ZGdCdD ZHdEdF ZIdddej+j,dddddf	dGd.dHdIZJdddddej+j,ddddddddfdJdKZKejLjMdfdLdMZNdNdO ZOdPdQ ZPdRdS ZQdddddej+j,ddddddddddfdTdUZRdVdW ZSdXdY ZTdZd[ ZUd\d]d^d_ZVd`dadbdcZWd`dddedfdgZXdhdhd%ddidjdkdlZYdmdn ZZdd.dodpZ[d\dhdqdrdsZ\ej+j,fdd`d\dtdudvdwdxdyZ]dzd{ Z^d|d} Z_d~d Z`dd ZadS )zFunctions to export models into the ONNX IR format.

These models can be loaded with the ONNX library and then
converted to models which run on other deep learning frameworks.
    annotationsN)AnyCallableDictListOptionalTupleUnion)_C)
_constants_patch_torchsymbolic_caffe2symbolic_helpersymbolic_registry)GLOBALSFc                   C  s   t S N)__IN_ONNX_EXPORT r   r   L/var/www/html/django/DPS/env/lib/python3.9/site-packages/torch/onnx/utils.pyis_in_onnx_export&   s    r   c              	   c  s   t | tjjs| j}|d u r2tjj}|r2t	d d}|tjj
ksR|tjjkrr|rrtjdk rnt	dtj d}t| | | z"d V  W t | tjjs| | nt | tjjs| | 0 d S )NaO  You are exporting the model to ONNX while in training mode with 'train' parameter not specified. The model will default to inference mode export. If you wish to export a training amenable ONNX model, specify training=TrainingMode.TRAINING or training=TrainingMode.PRESERVE (to preserve the original model state) in torch.onnx.export().F   zYou are exporting the model in training mode with onnx opset version {}. Opset versions lower than opset 12 will not be able to export nodes such as Dropout and BatchNorm correctly.T)
isinstancetorchjitScriptFunctiontraining_C_onnxTrainingModeEVALwarningswarnTRAININGPRESERVEr   export_onnx_opset_versionformatr   _set_training_modetrain)modelmodeZis_originally_trainingZis_export_trainingr   r   r   select_model_mode_for_export0   s:    



r*   c                 c  s  t | tjjsi }|  D ]h}|j D ]2\}}t|jdkr(||vrNi ||< ||| |< q(||v r|| 	 D ]}|j
| qpqzFd V  W t | tjjs| D ]$\}}| D ]\}}||j|< qqn@t | tjjs
| D ]$\}}| D ]\}}||j|< qq0 d S )NZO2StateDictHook)r   r   r   r   modules_state_dict_hooksitemstype__name__keyspop)r(   Ztmp_mapmodulekvZm_mapr   r   r   disable_apex_o2_state_dict_hook^   s*    r5   c                 c  sJ   t j }|s| rt j  zd V  W |sFt j  n|sDt j  0 d S r   )r   onnxis_onnx_log_enabled
enable_logdisable_log)verboseZis_originally_enabledr   r   r   setup_onnx_loggingy   s    

r;   c              
   c  s   t | |l}t| D}t|}|||fV  W d    n1 s@0    Y  W d    n1 s^0    Y  W d    n1 s|0    Y  d S r   )r*   r5   r;   )r(   r)   r:   Zmode_ctxZapex_ctxZlog_ctxr   r   r   exporter_context   s    r<   Tc                 C  s*   t | |||||||||	|
||||d d S )N)operator_export_typeopset_versiondo_constant_foldingdynamic_axeskeep_initializers_as_inputscustom_opsetsexport_modules_as_functions)_export)r(   argsfexport_paramsr:   r   input_namesoutput_namesr=   r>   r?   r@   rA   rB   rC   r   r   r   export   s"    rJ   c                 C  sN   |   dkrdS |   }|tj r0dS |ttj rJdS d S )Nzprim::ConstantFT)	kindoutputr.   isSubtypeOfr   ListType	ofTensorsOptionalTypeofTensor)nodeoutput_typer   r   r   _is_constant_tensor_list   s    rT   c                 C  s   |  D ]}| D ]}t| | qt|rg }|  D ]4}| |}| | | 	| |
| q<| d|| tj }| 	| | | qd S )Nzprim::ListConstruct)nodesblocks_split_tensor_list_constantsrT   rL   toIValueinsertConstantrR   
moveBeforecopyMetadataappendcreateinsertBeforesetTyper   rN   rO   replaceAllUsesWith)gblockrR   Zsubblockinputsvalinputlcr   r   r   rW      s$    
rW   z_C.Graphz_C_onnx.OperatorExportTypesbool)graphr=   _disable_torch_constant_propfixed_batch_sizec                 C  s  t |  t |  t |  t |  |du r:t |  t| |  t |  t |  t |  t |  t 	| d t 
|  t |  t 	| d t |  t | | t |  t |  t |  t |  t |  tj  t | |t  t r,t | | t tdtd|  t |  tjrp|d u rLg n|}|d u r^i n|}t | || t |  t | |} t |  t |  t | dtj  t |  t !| tj | t |  t "|  t |  t #| } t |  tjrt $| |tj  | S )NFTz                graph(%Pi):
                    %Pq = quantized::nhwc2nchw(%Pi)
                    %Pr = quantized::nchw2nhwc(%Pq)
                    return (%Pr)z<                graph(%Ri):
                    return (%Ri))%r   _jit_pass_inline_jit_pass_inline_fork_wait_jit_pass_lint_jit_pass_lower_all_tuples_jit_pass_constant_propagationrW   _jit_pass_dce&_jit_pass_canonicalize_graph_fuser_ops_jit_pass_peephole_jit_pass_fuse_addmm*_jit_pass_onnx_remove_inplace_ops_for_onnx_jit_pass_onnx_preprocess#_jit_pass_prepare_division_for_onnx_jit_pass_onnx_remove_print _jit_pass_onnx_preprocess_caffe2r   _quantized_opsclear'_jit_pass_onnx_unpack_quantized_weightsis_caffe2_aten_fallback+_jit_pass_onnx_quantization_insert_permutes,_jit_pass_custom_pattern_based_rewrite_graphtextwrapdedent_jit_pass_erase_number_typesr   onnx_shape_inference&_jit_pass_onnx_set_dynamic_input_shape_jit_pass_onnx_lint_jit_pass_onnx#_jit_pass_onnx_scalar_type_analysisr$   _jit_pass_onnx_peephole4_jit_pass_dce_allow_deleting_nodes_with_side_effects_jit_pass_canonicalize)_jit_pass_onnx_graph_shape_type_inference)rh   r=   ri   rj   params_dictr@   rH   r2   r   r   r   _optimize_graph   s~    






























r   c                 C  sr   t | d | d D ]Z\}}t|trLt| t| krld}t| qt|tr||krd}t| qdS )aY  Warns that changes to input dictionaries and strings won't take effect in the traced ONNX graph.

    We accept dictionaries and strings as ONNX inputs, but they should be only for
    configuration use. we detect here if these inputs are modified, and if so we warn
    the user that the changes won't take effect in the traced ONNX graph.
    r      aQ  We detected that you are modifying a dictionary that is an input to your model. Note that dictionaries are allowed as inputs in ONNX but they should be handled with care. Usages of dictionaries is not recommended, and should not be used except for configuration use. Also note that the order and values of the keys must remain the same. zvThe model seems to have string inputs/outputs. Note that strings will not appear as inputs/outputs of the ONNX graph. N)zipr   dictlistr0   r    r!   str)Zinput_statesre   Ztraced_inputwarningr   r   r   warn_on_static_input_changeR  s    
	
r   c                 C  s2   ||j ur.tjr.|du r*td| |  d}|S )zVResolves the arguments that are ignored when export_type != operator_export_type.ONNX.Tz`{}' can be set to True only when 'operator_export_type' is `ONNX`. Since 'operator_export_type' is not set to 'ONNX', `{}` argument will be ignored.F)ONNXr   _CAFFE2_ATEN_FALLBACKr    r!   r%   )arg_name	arg_valuer=   r   r   r   _resolve_args_by_export_typeo  s    r   zOptional[bool]int)rA   r=   r>   c                 C  sJ   |dk r| du rt d dS | du r*dn| }| du rF|tjju rFd}|S )ae  Decides whether the initializers in the graph should be listed as ONNX graph inputs.

    This method encapsulates the logic to decide whether the initializers in the graph
    should be listed as ONNX graph inputs (i.e., whether to choose ONNX IR v3 or v4).
    If keep_initializers_as_inputs is not specified (None), then we decide whether to keep
    initializers as graph inputs (val_keep_init_as_ip) based on export type. If export type
    is ONNX, then do not keep initializers as input (val_keep_init_as_ip=False). For all other
    export types keep initializers as input (val_keep_init_as_ip=True).
    If keep_initializers_as_inputs is specified, then respect it. Unless opset version <= 8,
    in which case it must be ignored because for opset version <= 8, all initializers MUST be
    part of graph input (only ONNX IR v3 is allowed), i.e. val_keep_init_as_ip=True.

    Special handling is needed for opset version 8 or lower, because irrespective
    of user input for keep_initializers_as_inputs, the graph must follow ONNX IR v3
    semantics, i.e. all initializers must be listed as ONNX graph input.
    	   Fa  Setting 'keep_initializers_as_inputs=False' for opset version8 or lower would lead to an invalid ONNX graph. Therefore, 'keep_initializers_as_inputs=False' is ignored during export.Exported model will have initializers as graph inputs (compliant  to ONNX IR v3).TN)r    r!   r   OperatorExportTypesr   )rA   r=   r>   val_keep_init_as_ipr   r   r   _decide_keep_init_as_input  s    
r   c                 C  s   t d| |S )Nadd_node_names)r   )r   r=   r   r   r   _decide_add_node_names  s    r   c                 C  s2   t d| |} | r.|d ur.|tjjur.td | S )Nr?   a  It is recommended that constant folding be turned off ('do_constant_folding=False') when exporting the model in training-amenable mode, i.e. with 'training=TrainingMode.TRAIN' or 'training=TrainingMode.PRESERVE' (when model is in training mode). Otherwise, some learnable model parameters may not translate correctly in the exported ONNX model because constant folding mutates model parameters. Please consider turning off constant folding or setting the training=TrainingMode.EVAL.)r   r   r   r   r    r!   )r?   r=   r   r   r   r   _decide_constant_folding  s    
r   zinspect.Signature)returnc                 C  s*   t | d| }t|rt|S tdd S )Nforwardz/model has no forward method and is not callable)getattrcallableinspect	signature
ValueError)r(   Zshould_be_callabler   r   r   
_signature  s    
r   c           
   
   C  s  zt | }W n6 tyB } ztd|  |W  Y d }~S d }~0 0 zt|j }|d dkrl|dd  }i }t|tr|}nt|trt|}n|g}t|d t	r|d }|d d }t
|}||d  D ]>}||v r|||  q|j| }	|	j|	jkr||	j qt|tr |nt|}W nX tyH   td Y n< ty } z"td|jd  W Y d }~n
d }~0 0 |S )Nz!%s, skipping _decide_input_formatr   selfr   z,No input args, skipping _decide_input_formatz!Skipping _decide_input_format
 {})r   r   r    r!   r   
parametersr0   r   tupler   lenr\   defaultempty
IndexError	Exceptionr%   rE   )
r(   rE   sigeZordered_list_keys	args_dict	args_listZn_nonkeywordZoptional_argparamr   r   r   _decide_input_format  s>    



,r   c                 C  sT   t |tjr|f}tjj| |dddd\}}}t| t||i d}|rP||fS |S )NFTstrict_force_outplace_return_inputs_states)r   )r   r   Tensorr   _get_trace_graphr   r   )funcrE   r=   Zreturn_outstrace_graph	torch_outinputs_statesr   r   r   _trace  s    
r   c                 C  sX   t j|  }t jj| |dddd\}}}t| |t j|  krPtd||fS )NFTr   zXstate_dict changed after running the tracer; something weird is happening in your model!)r   r   _unique_state_dictr0   r   r   RuntimeError)r(   rE   Zorig_state_dict_keysr   r   r   r   r   r   _trace_and_get_graph_from_model   s    
r   c                 C  s^   g }t |  |D ]F\}}dt| v rJtj|\}}|t| q||d u q|S )NZPackedParams)	r   rc   r   r.   r   r   _flattenr\   r   )method_graphargs_paramsparam_count_listinput_Zarg_params_in_vars_r   r   r   _get_param_count_list  s    r   c                   sL    fdd t  | }t|t| }|dks4J |rHtd| ddS )zAtorch.jit._flatten removes None. Check if it did so in this case.c                 3  sf   t | ttfr.| D ]} |D ]
}|V  qqn4t | tr\|  D ]} |D ]
}|V  qLq@n| V  d S r   )r   r   r   r   values)xinneryflattenr   r   r   "  s    
z._check_flatten_did_not_remove.<locals>.flattenr   zargs contained z None's after flattening. When exporting a ScriptModule or ScriptFunction, no args may be None because that breaks type propagation.N)r   r   r   )originalZjit_flattenedZflattened_with_noneZnum_noner   r   r   _check_flatten_did_not_remove  s    
r   c              
   C  s  d }t | tjjtjjfr<ttjt|d }t|| t | tjjrz| jj	}W n. t
y } ztd|W Y d }~n
d }~0 0 t| tj| jdd}t|\}}|dj	}	t|t| }
t|	|
}tj|
\}}t|	t||dd}||||fS t | tjjrTd}| j	}t| t||}t|||dd}|||d fS t| |\}}t| tj| }t| }t| }t|t| }t| }t|D ]&\}}||kr||||   qt| |||d fS d S )Nr   z('forward' method must be a script methodT)ZpreserveParametersr   Fr   )r   r   r   r   ScriptModuler   r   r   r   rh   AttributeErrorr   r   $_jit_pass_onnx_function_substitution_freeze_module_c_jit_onnx_list_model_parameters_get_methodr   "_propagate_and_assign_input_shapesr   r   r   r   r   rc   r   r0   	enumeratesetDebugName)r(   rE   r   Zflattened_argsrh   r   Z	freezed_mr2   paramsr   r   r   r   r   
state_dictgraph_inputsZuser_input_numparam_namesiinpr   r   r   _create_jit_graph9  sR    
 







r   c                 C  s<   dd |   D }|t|t| d  }tt||}|S )Nc                 S  s   g | ]}|  qS r   	debugName).0rd   r   r   r   
<listcomp>i      z)_get_named_param_dict.<locals>.<listcomp>)rc   r   r   r   )rh   r   Zinput_and_param_namesr   _params_dictr   r   r   _get_named_param_dicth  s    r   c                 C  sh   t |}i }|r4t|d tr4|d }|d d }| |i |}t|trT|g}nt|tsd|f}|S )Nr   )copydeepcopyr   r   r   r   )r(   rE   
input_argsZinput_kwargsexample_outputsr   r   r   _get_example_outputso  s    


r   c                 C  sx   t | tjrn| jtv rn|  }tj|  tjd}tj| 	 tj
d}|| | }|jt| j d}|||fS | fS d S )N)dtype)r   r   r   r   _qtype_vtype_map
dequantizetensorq_scaledoubleq_zero_pointint64to)valueZq_value_dequantizer   r   Zq_valuer   r   r   unpack_quantized_tensor  s    
r   c                 C  sD   t dd t| ddd  D s2t dd |D r@tj| |S | S )zReturns `torch.jit.trace(model, args)` if model is quantized. Otherwise do nothing and return
    original model.

    This is due to https://github.com/pytorch/pytorch/issues/75761.
    c                 s  s   | ]}t |d V  qdS )_packed_paramsN)hasattr)r   mr   r   r   	<genexpr>  s   z)_pre_trace_quant_model.<locals>.<genexpr>r+   c                   S  s   g S r   r   r   r   r   r   <lambda>  r   z(_pre_trace_quant_model.<locals>.<lambda>c                 s  s   | ]}t |d dV  qdS is_quantizedFNr   )r   argr   r   r   r    r   )anyr   r   r   trace)r(   rE   r   r   r   _pre_trace_quant_model  s    r	  c                   s$   dd  fdd  | | | S )a  Takes in ONNX graph, and mapping from _C.Node to node name in exported ONNX ModelProto.

    Returns:
        graph (_C.Graph): A TorchScript IR Graph with ONNX nodes, where each _C.Node gets its name
        in exported ONNX ModelProto assigned as attribute ``onnx_name``.
    c                 S  s4   |   D ]}||| q| |v r0| d||   d S )NZ	onnx_name)rV   s_)nb_fn
node_namesbr   r   r   n_fn  s    z$_assign_onnx_node_name.<locals>.n_fnc                   s   |   D ]}| | qd S r   )rU   )r  r  r  r  r  r   r   r    s    z$_assign_onnx_node_name.<locals>.b_fnr   )rh   r  r   r  r   _assign_onnx_node_name  s    
r  zpTuple[_C.Graph, Dict[str, torch.Tensor], Optional[Union[torch.Tensor, Tuple[torch.Tensor], List[torch.Tensor]]]]c              
   C  s  t |tjtttfr|f}t| |} t| |\}}}}t||}zt	||||||
||d}W n4 t
y } ztjd|  W Y d}~n
d}~0 0 t | tjjtjjf}|rt| |}d}|D ]}|t|7 }qtj|\}}t|||tj| nVt |ttfs|g}n|}tt|\}}tdd |D sLt|||tj| t||| t||}|	du sz|	tjjkrt||}|rtj t!j"v rt#||tj }t$| tjrt%||tj  t&||}tj dk rt'| t(|}t)| t*|| |||fS )a  Converts model into an ONNX graph.

    Returns:
        graph: A TorchScript IR Graph with ONNX nodes.
        params_dict: Dict from input param name to param value.
        torch_out: The output tensors resulting from the trace of ``model``.
            If ``model`` is a :class:`torch.jit.ScriptModule` or :class:`torch.jit.ScriptFunction`,
            this will be None, since we are not doing any tracing.
    )ri   rj   r   r@   rH   r2   zTorch IR graph at exception: Nr   c                 s  s   | ]}t |d dV  qdS r  r  )r   outr   r   r   r     r   z"_model_to_graph.<locals>.<genexpr>r   )+r   r   r   r   floatrg   r	  r   r   r   r   r6   logr   r   r   r   r   r   r   "_jit_pass_onnx_assign_output_shaper   r   r   r   _jit_flattenr  _set_input_and_output_namesr   r   r   _jit_pass_onnx_eval_peepholer$   r   onnx_constant_folding_opsets_jit_pass_onnx_constant_foldr   r   %_jit_pass_onnx_eliminate_unused_items,_jit_pass_onnx_cast_all_constant_to_floating%_jit_pass_filter_non_tensor_arguments#_jit_decay_packed_param_input_types_apply_friendly_debug_names)r(   rE   r:   rH   rI   r=   r?   ri   rj   r   r@   rh   r   r   r2   r   r   Z	is_scriptr   Zexample_outputs_finalexample_outputout_varsdescZoutput_wrappedoutput_tensorsZout_descr   r   r   _model_to_graph  s    











r$  c                 C  s   |
d u rt j}
|d u ri }t|
 t| td t| ||t t|||
}t||}t	|||}t
| |}t| ||||||||d	\}}}|||
d||	|||W  d    S 1 s0    Y  d S )NT)r   r@   F)r   onnx_default_opsetr   _set_opset_version_set_operator_export_type_set_onnx_shape_inferencer<   r   r   r   r   r$  _pretty_print_onnx)r(   rE   rG   r:   r   rH   rI   r=   export_typeZgoogle_printerr>   rA   rB   r   r?   r@   r   val_add_node_namesval_do_constant_foldingrh   r   r   r   r   r   export_to_pretty_string.  sN    



r-  c           
      C  s   |pt j}t| t| |d2 t| |}t| |tjj	d\}}}W d   n1 sX0    Y  t
 }d}| D ](}	|	 dd |vrt||	  qt||fS )aa  
    Converts the model with operator_export_type set to
    torch.onnx.OperatorExportTypes.ONNX_FALLTHROUGH once in order to get a list of
    all the ops that are not supported/implemented by the exporter.

    Args:
        model: Same as corresponding arg to torch.onnx.export.
        args: Same as corresponding arg to torch.onnx.export.
        training: Same as corresponding arg to torch.onnx.export.
        opset_version: Same as corresponding arg to torch.onnx.export.

    Returns:
        Tuple[torch._C.Graph, List[str]], where the list includes the names
        of the unconvertible ops.
    F)r=   N)r6   prim	quantized:r   )r   r%  r   r&  r<   r   r$  r   r   ONNX_FALLTHROUGHr   rU   rK   splitr\   )
r(   rE   r   r>   rh   r   r   Zunsupported_opsZsupported_namespacesrR   r   r   r   unconvertible_opsl  s    


*r3  c                   s   fdd}fdd}t |tr@|r@| }dd | D }n@t |tr|t|dkr|dd	  | } fd
d|D }|}nd }|r|  |S )Nc                    s    dd    D } | tjj_| S )Nc                 S  s   i | ]}|t t|qS r   )r   typenamer.   )r   _mr   r   r   
<dictcomp>  r   zM_setup_trace_module_map.<locals>.__setup_trace_module_map.<locals>.<dictcomp>)r+   r   r   r   _trace_module_map)trace_module_mapr(   r   r   __setup_trace_module_map  s    
z9_setup_trace_module_map.<locals>.__setup_trace_module_mapc                    sB   d  fdd}  fdd}  D ]}|| ||  q$d S )NZ_onnx_attrsc                   s   t |  t|  d S r   )setattr_get_module_attributes)r2   re   	attr_namer   r   )_track_module_attributes_forward_pre_hook  s    zm_setup_trace_module_map.<locals>.__register_attribute_hook.<locals>._track_module_attributes_forward_pre_hookc                   sJ   t  }|sd S | }i }t|  r:t|  }t|   t || d S r   )r   _get_tracing_staterh   r   r   delattr%_jit_pass_onnx_track_scope_attributes)r2   re   rL   tracing_staterh   Z
onnx_attrsr=  r   r   %_track_module_attributes_forward_hook  s    


zi_setup_trace_module_map.<locals>.__register_attribute_hook.<locals>._track_module_attributes_forward_hook)r+   register_forward_hookregister_forward_pre_hook)r?  rD  r   r9  r=  r   __register_attribute_hook  s    
z:_setup_trace_module_map.<locals>.__register_attribute_hookc                 S  s   h | ]\}}|qS r   r   )r   r3   r4   r   r   r   	<setcomp>  r   z*_setup_trace_module_map.<locals>.<setcomp>r   c                 S  s*   t | trt| S tdt| j d S )NznOnly type of the `nn.Module` should be passed in the set for argument `export_modules_as_functions`. Got `%s`.)r   r.   r   r4  r   r/   )r4   r   r   r   _find_typename  s    

z/_setup_trace_module_map.<locals>._find_typenamec                   s   h | ]} |qS r   r   )r   r4   )rI  r   r   rH    r   )r   rg   r-   setr   )r(   rC   r:  rG  r8  Zmodule_typenamesr   )rI  r(   r   _setup_trace_module_map  s"    

rK  c                   C  s   d t jj_t  d S r   )r   r   r   r7  r   "_jit_pass_onnx_clear_scope_recordsr   r   r   r   _reset_trace_module_map  s    
rM  c                   s@   t t t tjj} fdd|D  fdd D S )Nc                   s   g | ]}  |d qS r   )r1   r   r3   r   r   r   r     r   z*_get_module_attributes.<locals>.<listcomp>c                   s   i | ]}|t  |qS r   r  rN  )r2   r   r   r6    r   z*_get_module_attributes.<locals>.<dictcomp>)typingget_type_hintsr.   r   nnModule)r2   Zbase_m_annotationsr   )r   r2   r   r<    s    r<  c           (      C  s  |	d u rt jjj}	t| t jjr(tdtdu s4J daz>t	
| |
d u rTtj}
|rh|
dk rhtdt| |}|stjrtjj}ntjj}t	|
 t	| t| || t|||
}t||}t|||}t|tr|}nt }t| |}|d u ri }t|| || t| |||||||||d
\}}}|	t jjju}|d u rNi }t| i }|rxt||t |! }t"||t#| dd}|r|$||
|||| |||||\}}}}n(|$i |
|d|| |||||\}}}}|r t j%dt&|| |	t jjjkr`t'|d	ks"J t j()|d
} | *| W d    n1 sR0    Y  n|	t jjj+t jjj,fv r|	t jjj,krt-j.nt-j/}!t-j0|d|!d@}"|"1t jj2| |3 D ]\}#}$|"1|#|$ qW d    n1 s0    Y  n|	t jjj4krt5j67|r,t5j68|s6J n
t59| t5j6:|t jj2}%t j()|%d
} | *| W d    n1 sx0    Y  |3 D ]R\}#}$t5j6:||#}&t j()|&d
} | *|$ W d    n1 s0    Y  qnt;d|tjju rB|sBztj<|dd W n2 t;y@ }' zt j=|'W Y d }'~'n
d }'~'0 0 W d    n1 sX0    Y  W tsnJ dat>  ntsJ dat>  0 |S )Nztorch.nn.DataParallel is not supported by ONNX exporter, please use 'attribute' module to unwrap model from torch.nn.DataParallel. Try torch.onnx.export(model.module, ...)FT   z`export_modules_as_functions` is not supported for `opset_version` < 15.This is because `opset_version` < 15 implies IR version < 8, which means no local function support. )rj   r   r@   r   zExported graph: r   wbw)compressionzUnknown export type)Z
full_check)?r   r6   ExportTypesPROTOBUF_FILEr   rQ  DataParallelr   r   r   r(  r   r%  rK  r   r   r   ONNX_ATEN_FALLBACKr   r&  r'  r<   r   r   r   r   r   _validate_dynamic_axesr$  r   r   "_jit_pass_onnx_function_extractionr   r0   '_jit_pass_onnx_deduplicate_initializersr   _export_onnxr  r  r   serialization_open_file_likewriteZIP_ARCHIVECOMPRESSED_ZIP_ARCHIVEzipfileZIP_DEFLATED
ZIP_STOREDZipFilewritestrONNX_ARCHIVE_MODEL_PROTO_NAMEr-   	DIRECTORYospathexistsisdirmakedirsjoinr   _check_onnx_protoCheckerErrorrM  )(r(   rE   rF   rG   r:   r   rH   rI   r=   r*  r>   r?   r@   rA   rj   rB   r   r   rC   r   r+  r,  Zmodel_file_locationrh   r   r   Zdefer_weight_exportZnode_attr_to_nameprotoZ
export_mapZval_use_external_data_formatr  opened_filerV  zr3   r4   Zmodel_proto_fileZweight_proto_filer   r   r   r   rD     s>   










.
2
*0D

rD   c                 C  sp   |   D ]b}| D ]T}| }|t| kr2q|  d|  }|| ||v r||||< qqd S )Nr   )rU   rc   r   r   uniquerK   r   r1   )rh   r   r  r4   old_namenew_namer   r   r   r    s    
r  c                   s8    fdd}|t   |d |t   |d d S )Nc                   s   |d u rd S t |t | kr8td|t ||t | f t }tt|| D ]\}\}}|dkr||v r d}||  || |	 
|    ||	  |	 }|| | |krL|| qLd S )Nz<number of %s names provided (%d) exceeded number of %ss (%d)rL   zonnx::Identity)r   r   rJ  r   r   r]   insertAfterrR   addInputrL   r_   r.   return_nodereplaceInputaddr   r   )	node_list	name_list
descriptorZoutput_node_setr   namerR   identity_noderh   r   r   	set_names  s*    


z._set_input_and_output_names.<locals>.set_namesre   rL   )r   rc   outputs)rh   rH   rI   r  r   r  r   r    s    r  c              
   C  sT   z|| g|R  W S  t yN } z$d|jd |f|_ W Y d}~n
d}~0 0 dS )z\
    This trampoline function gets invoked for every symbolic method
    call from C++.
    z!{} (occurred when translating {})r   N)	TypeErrorr%   rE   )ra   op_namesymbolic_fnrE   r   r   r   r   _run_symbolic_method  s
    r  z_C.NoderR   c                 C  s   |   S r   )addBlockr  r   r   r   
_add_block  s    r  z_C.Blockrb   c                 C  s   |   S r   )addInputToBlockr  r   r   r   _add_input_to_block  s    r  z_C.Value)rb   r   c                 C  s   |  |}|S r   )registerOutput)rb   r   
new_outputr   r   r   _add_output_to_block  s    
r  r   zOptional[Callable])domainr  r>   r=   r   c                 C  s,   t || |s|tjjkrdS t || |S )aT  Looks up for the symbolic function in the registry.

    Args:
        domain: The domain of the symbolic function.
        op_name: The name of the op.
        opset_version: Currect opset used.
        operator_export_type: An enum in _C_onnx.OperatorExportTypes.

    Returns:
        The symbolic function if found, None otherwise.
    N)r   is_registered_opr   r   r1  Zget_registered_op)r  r  r>   r=   r   r   r   _find_symbolic_in_registry  s    r  c                 C  s4   t |d|}|tjjk}|tjjk}|p2| o2|S )N )r   r  r   r   	ONNX_ATENrZ  )nsr  r>   r=   Zis_exportable_aten_opZis_onnx_aten_exportZis_aten_fallback_exportr   r   r   _should_aten_fallback  s    
r  c                 C  sR   t t| j }|sdS |d j}t| }||vr<dS || }t|t	j
jS )z^Checks if the first argument to symbolic_fn is annotated as type `torch.onnx.SymbolicContext`.Fr   )r   r   r   r   r   r  rO  rP  
issubclassr   r6   SymbolicContext)r  r   Zfirst_param_name
type_hints
param_typer   r   r   _need_symbolic_context-  s    

r  )r  r   c                 C  s*   |   }|drt rdS t|jS )Nzaten::r  )schema
startswithr   r|   r   parse_schemaoverload_name)r  r  r   r   r   _get_aten_op_overload_name<  s    r  r   zDict[_C.Value, _C.Value]z/Optional[Union[_C.Value, Tuple[_C.Value, ...]]])ra   rb   r  rc   envr   c              
     s  t j}tjt_  dr.  dd }n  }|d\}}	ztd| t rp|dkrpt	
d| |dkr~d}
n|d	krt rd}
n|}
t|	|
|r<t|
|	||}|dusJ  fd
d  D }t|rtjt| |}||| g|R i |W S |	dkr$ g|R }|| g|R i |W S |dkr fdd  D }| j|	g|R i |d  iW S t||	||rڇ fdd  D }  }||d< | j|	g|R dt i|W S t|
|	|W n tyf   |tjjkrY dS |tjjkr`t s` fdd  D }| j|	g|R dt i| Y S  Y nB ty } z(|jd  d|	 df|_ W Y d}~n
d}~0 0 dS )zRuns a symbolic function.

    The function is used in C++ to export the node to ONNX.

    Returns:
        A single or a tuple of Values.
        None when the node gets cloned as is into the new graph.
    r   Nr   ::r  r   Zcaffe2atenr/  c                   s   i | ]}| | qS r   r   rN  r  r   r   r6  v  r   z*_run_symbolic_function.<locals>.<dictcomp>ZPythonOpr6   c                   s(   i | ] }|d    |d   | qS r   r   kindOfrN  r  r   r   r6    r   r  c                   s(   i | ] }|d    |d   | qS r  r  rN  r  r   r   r6    r   r  c                   s(   i | ] }|d    |d   | qS r  r  rN  r  r   r   r6    r   r   z 
(Occurred when translating z).) r   r$   r   r|   rK   endswithr2  r   Zregister_versionr   Zregister_quantized_opsr  r  attributeNamesr  r   r6   r  r   opoutputsSizer  atr  ZUnsupportedOperatorErrorr   r   r   r1  rZ  r  rE   )ra   rb   r  rc   r  r=   r>   Z
ns_op_namer  r  r  r  attrsctxr  r   r   r  r   _run_symbolic_functionE  s    


&

r  c                 C  s`   t td| s td|  d| d\}}|dkrLtd|  d| d|dkrXd	}||fS )
Nz+^[a-zA-Z0-9-_]*::[a-zA-Z-_]+[a-zA-Z0-9-_]*$zFailed to register operator z.The symbolic name must match the format Domain::Name, and should start with a letter and contain only alphanumerical charactersr  r6   z. z domain cannot be modified.r  r  )rg   rematchr   r2  )symbolic_namer  r  r   r   r   get_ns_op_name_from_custom_op  s    

r  c                 C  s@   t | \}}ttjtjgD ]}||krt|||| qdS )av  Registers a symbolic function for a custom operator.

    When the user registers symbolic for custom/contrib ops,
    it is highly recommended to add shape inference for that operator via setType API,
    otherwise the exported graph may have incorrect shape inference in some extreme cases.
    An example of setType is `test_aten_embedding_2` in `test_operators.py`.
    N)r  	itertoolschainr   onnx_stable_opsetsonnx_main_opsetr   Zregister_op)r  r  r>   r  r  versionr   r   r   register_custom_op_symbolic  s    
r  c                 C  s>   t | \}}ttjtjgD ]}||krt||| qd S r   )r  r  r  r   r  r  r   Zunregister_op)r  r>   r  r  r  r   r   r   unregister_custom_op_symbolic  s    
r  c           
      C  s0  t | dkrdS t|drj|du s.t |dkrBdd |j D }|du sVt |dkrjdd |j D }t|prg |pxg  }|  D ]\}}||vrtd	| t
|trtd	| i }t|D ]T\}}	t
|	tstd	|	|v rtd
	|	| qt|d t|d  ||	< q|| |< qdS )z=Ensures dynamic axes argument is follows the expected format.r   Nrh   c                 S  s   g | ]}|  qS r   r   )r   r   r   r   r   r     r   z*_validate_dynamic_axes.<locals>.<listcomp>c                 S  s   g | ]}|  qS r   r   )r   r   r   r   r   r     r   zAProvided key {} for dynamic axes is not a valid input/output namezNo names were found for specified dynamic axes of provided input.Automatically generated names will be applied to each dynamic axes of input {}z3The type of axis index is expected to be an integerz:Duplicate dynamic axis index {} was provided for input {}.Z_dynamic_axes_r   )r   r   rh   rc   r  rJ  r-   r    r!   r%   r   r   r   r   r   r   )
r@   r(   rH   rI   valid_nameskeyr   
value_dictr   r   r   r   r   r[    sF    



r[  )FFNNNN)F)b__doc__
__future__r   
contextlibr   r   r  rk  r  r   rO  r    rd  r   r   r   r   r   r	   r
   r   Ztorch._C._onnxr   _onnxr   torch.jit._traceZtorch.serialization
torch.onnxr   r   r   r   r   torch.onnx._globalsr   r   r   r   contextmanagerr*   r5   r;   r<   r   r   rJ   rT   rW   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   quint8uint8qint8int8qint32int32quint4x2r   r   r	  r  r$  r-  r   r   r3  rK  rM  r<  rD   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r[  r   r   r   r   <module>   s  $
-



%      x+'
/{
?
(;
 [_
