
    ¯wg                   2   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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Zddlmc mZ ddlmZ ddlmZm Z m!Z!m"Z" ddl#m$Z$ ddl%m&Z& dd	l'm(Z( d
Z)ee(ejT                  ejV                  f   Z,eejZ                  j\                  ej^                  j`                  f   Z1eejT                  eedf   f   Z2ee3ef   Z4eee,   ef   Z5 G d dejl                        Z7ejp                   G d d             Z9d Z:d6dZ;d7dZ<d8d7dZ=d9dZ>e)f	 	 	 d:dZ?d;dZ@d<dZA	 	 	 	 	 	 d=dZB	 	 	 	 	 	 d>dZCd ZDd ZE	 	 	 	 d?dZFd ZG	 	 	 	 	 	 	 	 	 	 	 	 d@dZH G d  d!      ZI	 	 	 	 	 	 	 	 	 	 dAd"ZJ	 	 	 	 	 	 	 	 	 	 dBd#ZK	 	 	 	 	 	 	 	 	 	 dBd$ZL	 dC	 	 	 	 	 	 	 dDd%ZM	 	 	 	 	 	 	 	 dEd&ZN	 dC	 	 	 	 	 	 	 dFd'ZOdddddej                  j                  ddd(d(d(ddf	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dGd)ZR	 	 dH	 	 	 	 	 	 	 	 	 	 	 dId*ZS G d+ d,      ZT G d- d.      ZUejp                   G d/ d0             ZVdJd1ZWdKd2ZXdLd3ZYdKd4ZZdej                  j                  ddd(df	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dMd5Z[y)NzFunctions to verify exported ONNX model is functionally equivalent to original PyTorch model.

ONNX Runtime is required, and is used as the ONNX backend for export verification.
    )annotationsN)AnyCallable
CollectionMappingSequenceTupleUnion)_C)
_constants_experimental_exporter_statesutils)GLOBALS)onnx_proto_utils)Number)CPUExecutionProvider.c                      e Zd ZdZdZdZdZy)OnnxBackendz9Enum class for ONNX backend used for export verification.ONNXReferenceEvaluatorr   CUDAExecutionProviderN)__name__
__module____qualname____doc__	REFERENCEONNX_RUNTIME_CPUONNX_RUNTIME_CUDA     \/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/torch/onnx/verification.pyr   r   +   s    C(I-/r    r   c                      e Zd ZU dZdZded<   dZded<   dZded<   dZded<   e	j                  Zded	<   d
Zded<   dZded<   dZded<   dZded<   y)VerificationOptionsa  Options for ONNX export verification.

    Attributes:
        flatten: If True, unpack nested list/tuple/dict inputs into a flattened list of
            Tensors for ONNX. Set this to False if nested structures are to be preserved
            for ONNX, which is usually the case with exporting ScriptModules. Default True.
        ignore_none: Whether to ignore None type in torch output, which is usually the
            case with tracing. Set this to False, if torch output should keep None type,
            which is usually the case with exporting ScriptModules. Default to True.
        check_shape: Whether to check the shapes between PyTorch and ONNX Runtime outputs
            are exactly the same. Set this to False to allow output shape broadcasting.
            Default to True.
        check_dtype: Whether to check the dtypes between PyTorch and ONNX Runtime outputs
            are consistent. Default to True.
        backend: ONNX backend for verification. Default to OnnxBackend.ONNX_RUNTIME_CPU.
        rtol: relative tolerance in comparison between ONNX and PyTorch outputs.
        atol: absolute tolerance in comparison between ONNX and PyTorch outputs.
        remained_onnx_input_idx: If provided, only the specified inputs will be passed
            to the ONNX model. Supply a list when there are unused inputs in the model.
            Since unused inputs will be removed in the exported ONNX model, supplying
            all inputs will cause an error on unexpected inputs. This parameter tells
            the verifier which inputs to pass into the ONNX model.
        acceptable_error_percentage: acceptable percentage of element mismatches in comparison.
            It should be a float of value between 0.0 and 1.0.
    Tboolflattenignore_nonecheck_shapecheck_dtyper   backendgMbP?floatrtolgHz>atolNSequence[int] | Noneremained_onnx_input_idxzfloat | Noneacceptable_error_percentage)r   r   r   r   r%   __annotations__r&   r'   r(   r   r   r)   r+   r,   r.   r/   r   r    r!   r#   r#   3   sl    4 GTKKK&77G[7D%D%4818044r    r#   c                    g }| D ]>  }t        |t              r|j                  t        |             .|j	                  |       @ |S N)
isinstancetupleextend_flatten_tuplesappend)elem	flattenedts      r!   r6   r6   Z   sI    I  a_Q/0Q	 
 r    c                4   t        | t        j                        rV| j                  r,| j	                         j                         j                         S | j                         j                         S t        | t        t        f      r| D cg c]  }t        |       c}S t        | t        t        t        f      rt        j                  |       S t        | t              r3g }| D ]*  }|j!                  t        |      t        | |         g       , |S | S c c}w r2   )r3   torchTensorrequires_graddetachcpunumpylistr4   	_to_numpyr$   intr*   nparraydictr5   )r8   inpr9   ks       r!   rC   rC   e   s    $%;;=$$&,,..88:##%%	D4-	(*./3	#//	D4e,	-xx~	D$		 	AAilId1g,>?@	AK 0s   Dc                z    | D ]5  }t        |t        t        f      s|j                  |      nt	        ||       7 |S r2   )r3   rB   r4   r7   _inline_flatten_list)inputsres_listis      r!   rK   rK   w   s?     1",e}#
#Ax01 Or    Tc                    g }| D ](  }|j                  t        j                  ||             * |D cg c]  }t        |       c}S c c}w )Ncast_onnx_accepted)r5   r   unpack_quantized_tensorrC   )valuesrQ   value_unpackedvaluevs        r!   _unpack_to_numpyrW      sO    N 
))%DVW	

 #11QIaL111s   A	c           
     X   i }|rt        |d   t              r
|d   }|d d }t        t        |            }i }|j	                         D ]  \  }}t        |      ||<    t        |      }t        | d      r(| j                         D cg c]  }|j                   }}n1t        | d      r| j                  }nt        dt        |        d      t        |      D ]7  \  }}|t        |      k(  s||   |v rt        d| d| d| d      ||||   <   9 | j                  d |      }|S c c}w )	N
get_inputsinput_nameszUnknown ONNX backend type: .z(got too many positional inputs. inputs: z. kw_inputs: z. input names: )r3   rG   rW   r6   itemsrC   hasattrrZ   namer[   
ValueErrortype	enumeratelenrun)	onnx_sessionrL   	kw_inputs
ort_inputs
input_nameinputrN   r[   	onnx_outss	            r!   	_run_onnxrk      sZ   I*VBZ.2J	of56FJ&__. 2
E!*5!1
:2vF|\*'3'>'>'@A!qvvAA	}	-"..6tL7I6J!LMMf% +5K  KNj$@:6(-PY{ [  +}A/  &+
;q>"+   z2I Bs   D'c                    	 dd l }|t        }|j                         }d|_        |j                  t        | t              r| n| j                         ||      }|S # t        $ r}t        d      |d }~ww xY w)Nr   z0onnxruntime is required for export verification.   )	providers)	onnxruntimeImportError_ORT_PROVIDERSSessionOptionslog_severity_levelInferenceSessionr3   strgetvalue)modelort_providersro   esession_optionsort_sessions         r!   _ort_sessionr|      s    U &!002O *+O&..E3'U^^-= / K
   ULMSTTUs   A 	A5$A00A5c                    	 dd l }ddl m} t        | t              r|j                  |       n|j                  | j                               }|j                  |      }|S # t        $ r}t        d      |d }~ww xY w)Nr   )	referencez1onnx >= 1.13 is required for reference evaluator.)	onnxr~   rp   r3   ru   loadload_model_from_stringrv   ReferenceEvaluator)rw   r   onnx_referenceexcprotore   s         r!   !_onnx_reference_evaluator_sessionr      s}    X4 eS! 			%(()9: 

 "44U;L  XMNTWWXs   
A 	A9(A44A9c                    |t         j                  k(  rt        |       }|S |t         j                  t         j                  hv rt        | |j                  f      }|S t        d|       )NzUnsupported backend: )r   r   r   r   r   r|   rU   r`   )rw   r)   re   s      r!   _onnx_backend_sessionr      sm    +'''8?
 	 
[11;3P3PQ	Q#EGMM+;<  0	:;;r    c                2   t        |       t        |      k(  s J dt        |        dt        |       d       |j                  }|r|dkD  s|dk  rt        d      t        | |      D ]n  \  }}	 |j                  st        j                  ||      \  }}t        j                  j                  |||j                  |j                  |j                  d       p y # t        $ r3}|rd	t        j                  t        j                  |||j                  |j                  
            t        j                   |j"                        z  z
  }||k  r%t%        j&                  d| d| d| d       Y d }~|j(                  t
        j*                  k(  s|j(                  t
        j,                  k(  rt%        j&                  d       |j(                  t
        j*                  k(  s|j(                  t
        j,                  k(  rt%        j&                  d        d }~ww xY w)Nz(Number of outputs differ ONNX runtime: (z) PyTorch: ()g      ?g        zAIf set, acceptable_error_percentage should be between 0.0 and 1.0T)r+   r,   r(   	equal_nan   )r+   r,   zSuppressed AssertionError:
z.
Error percentage z within acceptable range r\   zONNX output is quantizedzPyTorch output is quantized)rc   r/   r`   zipr'   rE   broadcast_arraysr<   testingassert_closer+   r,   r(   AssertionErrorsumiscloseprodshapewarningswarndtypeuint8int8)rj   pt_outsoptionsr/   ort_outpt_outry   error_percentages           r!   #_compare_onnx_pytorch_outputs_in_npr      s    	I#g,&^	1#i.1AcRYl^[\]^&")"E"E"#c)-H3-NO
 	
 y'2 	&&"$"5"5gv"FMM&&\\\\#// '   	*#$rvvJJwW\\U(GGGMM*(+ $+  $'BBMM6qc :,,<+= >33N2OqR
 }}(GMMRWW,D89||rxx'6<<277+B;<!	s!   .A(C
H#B	H2BHHc                    |j                   r#t        j                  j                  |      \  }}nt	        |gg       }t        |d      }t	        | g       } t        | ||       y)at  
    Compare ONNX and PyTorch outputs.

    Args:
        onnx_outs: outputs from ONNX backend.
        pt_outs: outputs from PyTorch.
        options: options for verification.

    Raises:
        AssertionError: if outputs from ONNX model and PyTorch model are not
            equal up to specified precision.
        ValueError: if arguments provided are invalid.
    FrP   N)r&   r<   jit_flattenrK   rW   r   )rj   r   r   _
pt_outs_nps        r!   _compare_onnx_pytorch_outputsr     sW    $ YY''0
&y"5!'eDJ$Y3I'	:wGr    c                    t        | t        j                  t        f      r| f} t	        j
                  |       } |rt	        j
                  |      }| |fS i }| |fS )a  Prepare input for PyTorch model execution.

    Any future changes/formatting to the input before dispatching to the PyTorch
    model should be made in this function.

    Args:
        args: positional arguments for PyTorch model forward method.
        kwargs: keyword arguments for PyTorch model forward method.

    Returns:
        args: positional arguments for PyTorch model forward method.
        kwargs: keyword arguments for PyTorch model forward method.
    )r3   r<   r=   rG   copydeepcopy)argskwargss     r!   _prepare_input_for_pytorchr   $  s\     $t,-w ==Dv& < <r    c                    t        | |      \  } }|s)t        |       dkD  rt        | d   t              r| i fz   }|S |r| |fz   }|S | }|S )a  Prepare input for ONNX model export.

    Any future changes/formatting to the input before dispatching to the
    :func:`torch.onnx.export` api should be made in this function.

    Args:
        args: positional arguments for PyTorch model forward method.
        kwargs: keyword arguments for PyTorch model forward method.

    Returns:
        onnx_inputs: positional arguments for ONNX model export, as `args` in
            :func:`torch.onnx.export`.
    r   rY   )r   rc   r3   rG   )r   r   onnx_inputss      r!   _prepare_input_for_exportr   >  sg     .dF;LD&c$i!m
48T(BbUl
 	 
fY&  r    c                    t        | |      }|r#t        j                  j                  |      \  }}n|r|d   i k(  r|dd }||D cg c]  }||   	 c}S |S c c}w )ah  Prepare input for ONNX model execution in ONNX backend.

    Any future changes/formatting to the input before dispatching to the ONNX backend
    run should be made in this function.

    Args:
        args: positional arguments for PyTorch model forward method.
        kwargs: keyword arguments for PyTorch model forward method.
        remained_onnx_input_idx: indices of inputs to be used for ONNX model execution.
        flatten: whether to flatten the input before dispatching to the ONNX model execution.

    Returns:
        onnx_inputs: positional arguments for ONNX model execution in ONNX backend.
    rY   N)r   r<   r   r   )r   r   r.   r%   r   r   rN   s          r!   _prepare_input_for_onnxr   V  sl    " ,D&9K++K8Q	RB.!#2&*(?@1A@@ As   Ac                z    	 t        j                  |       S # t        $ r t        j                  d       | cY S w xY w)zHUsed for preserving original model in case forward mutates model states.zHFailed to clone model. Model state might be mutated during verification.)r   r   	Exceptionr   r   )rw   s    r!   _try_clone_modelr   s  s;    }}U## V	
 	s     ::c                |     t        |j                         fd} |||       |r|D ]  } ||i         yy)ap  Compare outputs from ONNX model runs with outputs from PyTorch model runs.

    Args:
        pt_model: PyTorch model.
        onnx_model_f: ONNX model file path or file-like object.
        input_args: positional arguments for PyTorch model forward method.
        input_kwargs: keyword arguments for PyTorch model forward method.
        additional_test_inputs: additional positional arguments for PyTorch model
            forward method.
        options: options for verification.

    Raises:
        AssertionError: if outputs from ONNX model and PyTorch model are not
            equal up to specified precision.
    c                    t        | |      \  }}t        
      } ||i |}t        | |	j                  	j                        }t        |      }t        ||	       y )Nrj   r   r   )r   r   r   r.   r%   rk   r   )
input_argsinput_kwargspt_args	pt_kwargspt_model_copyr   r   rj   re   r   pt_models           r!   %compare_onnx_pytorch_model_with_inputzJ_compare_onnx_pytorch_model.<locals>.compare_onnx_pytorch_model_with_input  si    7
LQ(26I6-g&E&Ew
 lK8	%	
r    N)r   r)   )	r   onnx_model_fr   r   additional_test_inputsr   r   test_input_argsre   s	   `    `  @r!   _compare_onnx_pytorch_modelr   ~  sI    . )wGL
$ **lC5 	GO1/2F	G r    c                  .    e Zd ZdZddZd ZddZd	dZy)

_GraphDiffz7A class to represent the difference between two graphs.c                     || _         || _        y)zConstruct a _GraphDiff object.

        Args:
            graph_a (_C.Graph): First graph to compare.
            graph_b (_C.Graph): Second graph to compare.
        N)graph_agraph_b)selfr   r   s      r!   __init__z_GraphDiff.__init__  s     r    c                "    | j                         S )z!See function :func:`diff_report`.)diff_reportr   s    r!   __str__z_GraphDiff.__str__  s    !!r    c                l    dj                  |j                         D cg c]  }d|z   	 c}      S c c}w )N
	)join
splitlines)r   lineslines      r!   _indentz_GraphDiff._indent  s,    yy%2B2B2DE$$+EFFEs   1c           	        | j                   }| j                  }t        |      }t        |      }||k(  ryt        j                  |j                  d      |j                  d            }d| j                  dj                  |            g}t        j                  |j                         |j                               D ]*  \  }}t        |      t        |      k7  s|j                  d       t        j                  t        |      j                  d      t        |      j                  d            }	d| j                  dj                  |	            g}
|r|j                         nd}|r+|
j                  d| j                  t        |            g       |r|j                         nd}|r+|
j                  d| j                  t        |            g       |j                  |
        n d	j                  |      S )
a)  Return a string representation of the graph difference.

        The report shows the first pair of nodes that diverges. It also shows the source
        location of the pair of nodes.

        Returns:
            graph_diff_report (str): A string representation of the graph difference.
         TzGraph diff:zFirst diverging operator:z
node diff:NzFormer source location:zLatter source location:r   )r   r   ru   difflibndiffr   r   r   	itertoolszip_longestnodesr7   sourceRanger5   )r   r   r   graph_a_strgraph_b_str
graph_diffgraph_diff_reportnode_anode_b	node_diffsource_printoutstack_astack_bs                r!   r   z_GraphDiff.diff_report  s    ,,,,'l'l+%]]""4(+*@*@*F

 +DLL9L,MN'33GMMOW]]_U 	NFF6{c&k)!(()DE#MMK**40#f+2H2H2N	 $0bggi>P1Q"R28&,,.d#**2DLLW4NO 39&,,.d#**2DLLW4NO "((9+	. yy*++r    N)r   _C.Graphr   r   )r   ru   returnru   r   ru   )r   r   r   r   r   r   r   r   r   r    r!   r   r     s    A"G.,r    r   c                    t        |      dk  rt        d      d}|D ]5  \  }} || |||      }||}t        ||      j                         }|s3|c S  y)a  Check if graph produced by `model_to_graph_func` is the same across `test_input_groups`.

    Args:
        model: See :func:`check_export_model_diff`.
        test_input_groups: See :func:`check_export_model_diff`.
        export_options: See :func:`check_export_model_diff`.
        model_to_graph_func: A function to convert a PyTorch model to a JIT IR graph.

    Returns:
        graph_diff_report (str): A string representation of the graph difference.
       z3Need at least two groups of test inputs to compare.Nr   )rc   r`   r   r   )	rw   test_input_groupsexport_optionsmodel_to_graph_funcref_jit_graphr   r   	jit_graphr   s	            r!   _check_graph_diffr     sx    2 !NOOM) %f'tV^L	 %M&}i@LLN$$% r    c                
   |j                   }|j                  }t        j                  | ||      5  t	        ||      }t        j
                  | |      } t        j                  | |      \  }}}}|cddd       S # 1 sw Y   yxY w)az  As part of the ONNX export steps, create a traced JIT graph from a PyTorch model.

    Args:
        model: See :func:`check_export_model_diff`.
        args: See :func:`check_export_model_diff`.
        kwargs: See :func:`check_export_model_diff`.
        export_options: See :func:`check_export_model_diff`.

    Returns:
        jit_graph (_C.Graph): A traced JIT graph.
    N)trainingverboser   exporter_contextr   _pre_trace_quant_model_create_jit_graph)	rw   r   r   r   r   r   export_inputsr   r   s	            r!   _traced_graph_from_modelr     s}    " &&H$$G			x	9 1$?,,UMB"44UMJ	1a	  s   ?A99Bc                   |j                   }|j                  }|j                  }|j                  }|j                  }|j
                  }	|j                  }
|j                  }|t        j                  }t        j                  | |       |st        j                  j                  }|t        _        |t        _        t        j"                  | ||      5  t        j$                  |j&                  ||      }|	i }	t        j(                  |	| |
|       t+        ||      }t        j,                  | |      }t        j.                  | |||
|||||		      \  }}}|cddd       S # 1 sw Y   yxY w)ay  As part of the ONNX export steps, export an ONNX JIT graph from a PyTorch model.

    Args:
        model: See :func:`check_export_model_diff`.
        args: See :func:`check_export_model_diff`.
        kwargs: See :func:`check_export_model_diff`.
        export_options: See :func:`check_export_model_diff`.

    Returns:
        onnx_graph (_C.Graph): An ONNX JIT graph.
    N)r   dynamic_axes)opset_versionoperator_export_typeexport_modules_as_functionsr   r   r   r[   output_namesr   ONNX_DEFAULT_OPSETr   _setup_trace_module_map_C_onnxOperatorExportTypesONNXr   export_onnx_opset_versionr   _decide_constant_foldingdo_constant_folding_validate_dynamic_axesr   _decide_input_format_model_to_graph)rw   r   r   r   r   r   r   r   r   r   r[   r   r  r   
onnx_graphr   s                   r!   _onnx_graph_from_modelr  9  sa   $ #00M)>>"0"L"L&&H$$G!..L ,,K!..L"55	!!%)DE&::??(5G%#7G 			x	9 #<<..0Dh
 L$$\5+|T1$?225-H 00 %


Aq /  s   BEE(c                   |i }|j                   }|j                  xs i }|j                  }|j                  }|j                  }|j
                  xs t        j                  }|t        _	        |t        _         t        j                  |||      }| j                         } t        j                  | ||||      } ||t        j                  j                   k(  r t"        j$                  j'                  | |      }|r?|t        j(                  k\  r,t%        j*                  | ||      }t%        j,                  |        t        j.                  rt%        j0                  | ||       t%        j2                  | |      }|dk  rt%        j4                  |        t%        j6                  |      }t%        j8                  |        t%        j,                  |        |j:                  rt=        d|        | |fS )N)params_dictr   r[   	   zONNX graph: )r   r   r[   r   r  r   r   r  r   r  r   r  r   _optimize_graphr  TrainingModeEVALr<   r   _jit_pass_onnx_eval_peepholeONNX_CONSTANT_FOLDING_MIN_OPSET_jit_pass_onnx_constant_fold4_jit_pass_dce_allow_deleting_nodes_with_side_effectsonnx_shape_inference)_jit_pass_onnx_graph_shape_type_inference%_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_typesr   print)	graphr   r  r   r   r[   r   r  r   s	            r!   _onnx_graph_from_aten_graphr   y  s   
 )>>!..4"L ,,K&&H(<<"00QJ4Q4QM(5G%#7G 8818 JJLE!!!E 8w';';'@'@@hh;;E;O 	ZGGG55e[-X
??F##
44UKW::5+NK q
77>::;GK**51;;EBne$+r    c                b   |j                   xs t        j                  }|j                  xs i }|j                  }t        j                  |j                  ||      }t        j                  d|      }|j                  xs i }| j                  |||d||j                   |||di       \  }	}
}}|	|
fS )NTFr   )r   r   r  r   r   r   _decide_keep_init_as_inputkeep_initializers_as_inputs_decide_add_node_namescustom_opsets_export_onnxr   )r  r   r  r   r   r   val_keep_init_as_ipval_add_node_namesr%  r   
export_mapr   s               r!   _onnx_proto_from_onnx_graphr*    s    
 #00QJ4Q4QM!..4"L)>>::22
 55d<PQ"006BM(55"""

E:q! *r    c                    |t        j                         n|}t        | ||t              }|r|S t        | ||t              S )a  Verify exported model discrepancy between different groups of inputs.

    A graph is exported for each group of inputs. The exported graphs are then compared
    to each other, and discrepancies of first pair of nodes are reported. This function
    first checks the jit graph. If no discrepancies were found, it then checks the onnx
    graph.

    Unless otherwise specified, the jit/ONNX graph is expected to be the same, regardless
    of the inputs used for exporting. A discrepancy implies the graph exported is
    not accurate when run on other groups of inputs, which will typically results in
    runtime errors or mismatching output.

    Args:
        model (torch.nn.Module or torch.jit.ScriptModule): The model to be exported.
        test_input_groups (Sequence[Tuple[Tuple[Any, ...], Mapping[str, Any]]]): A sequence
            of input groups to be used to export the model. Each input group is a pair of
            (args, kwargs).
        export_options (_experimental.ExportOptions, optional): An _experimental.ExportOptions
            object that controls the export behavior.

    Returns:
        str: A string containing the diff of the exported models.
    )r   ExportOptionsr   r   r  )rw   r   r   jit_diff_reports       r!   check_export_model_diffr.    sV    : *8)?##%^  ( .2JO  .2H r    Fc                   |
t               }|t        j                  j                  j                  k(  r| j                          n7|t        j                  j                  j                  k(  r| j                          t        j                         5  t        j                         5 }t        j                         }|rC|j                  t        j                               }t         j"                  j%                  |d      }t'        ||      }t)        |       }t+        j,                  | |||||	||||||
       t/        ||||||       ddd       ddd       y# 1 sw Y   xY w# 1 sw Y   yxY w)a  Verify model export to ONNX against original PyTorch model.

    Args:
        model (torch.nn.Module or torch.jit.ScriptModule): See :func:`torch.onnx.export`.
        input_args (tuple): See :func:`torch.onnx.export`.
        input_kwargs (dict): See :func:`torch.onnx.export`.
        do_constant_folding (bool, optional): See :func:`torch.onnx.export`.
        dynamic_axes (dict, optional): See :func:`torch.onnx.export`.
        input_names (list, optional): See :func:`torch.onnx.export`.
        output_names (list, optional): See :func:`torch.onnx.export`.
        training (torch.onnx.TrainingMode): See :func:`torch.onnx.export`.
        opset_version (int, optional): See :func:`torch.onnx.export`.
        keep_initializers_as_inputs (bool, optional): See :func:`torch.onnx.export`.
        verbose (bool, optional): See :func:`torch.onnx.export`.
        fixed_batch_size (bool, optional): Legacy argument, used only by rnn test cases.
        use_external_data (bool, optional): Explicitly specify whether to export the
            model with external data.
        additional_test_inputs (list, optional): List of tuples. Each tuple is a group of
            input arguments to test. Currently only *args are supported.
        options (_VerificationOptions, optional): A _VerificationOptions object that
            controls the verification behavior.

    Raises:
        AssertionError: if outputs from ONNX model and PyTorch model are not
            equal up to specified precision.
        ValueError: if arguments provided are invalid.
    Nz
model.onnx)	r   r  r#  r   r[   r   fixed_batch_sizer   r   )r   r   r   r   r   r   )r#   r<   r   r  TRAININGtrainr  evalno_grad
contextlib	ExitStackioBytesIOenter_contexttempfileTemporaryDirectoryospathr   r   r   r   _exportr   )rw   r   r   r  r   r[   r   r   r   r#  r   r0  use_external_datar   r   stackmodel_ftmpdir_pathinputs_for_export
model_copys                       r!   verifyrE    s4   Z %'5::**333	UZZ,,11	1

	  
*..0  
E$&JJL--h.I.I.KLKggll;=G5j,O &e,
' 3(C%#%-	
 	$ !%#9	
3 
  
  
  
  
  
s%   E%%B#EE%E"	E%%E.c                (   |
t               }|i }| }| j                         } t        | j                               }t	        |D cg c]  }||	 c}      }|t        |      d  D 	cg c]  }	||	j                             }
}	t        d |
D              sJ t        j                  |      }|t	        |
      z   }t        j                  j                  | |      }t        |t        t        f      s|g}t        | ||      \  } }t        | ||      \  }}t        j                          }t"        j$                  j&                  }t)        j*                  ||||       	 | j                         D 	ch c]  }	|	j                          }}	g }t-        |j                         |      D ])  \  }	}|	j                         |v s|j/                  |       + t	        |      }t1        |i |j2                  |j4                        }t7        ||j8                        }t;        ||      }~	 t=        |||       d | ||fS c c}w c c}	w c c}	w # t>        $ r}|| ||fcY d }~S d }~ww xY w# t@        $ r*}tC        d       tC        d|       tC        d|        |d }~ww xY w)Nc              3  $   K   | ]  }|d u 
 y wr2   r   ).0ws     r!   	<genexpr>z$verify_aten_graph.<locals>.<genexpr>n  s     .q}.s   r   z%Unexpected error during verification.zjit graph: zonnx graph: )"r#   r   rB   rL   r4   rc   	debugNameallr   r<   r   _jit_interpret_graphr3   r   r*  r7  r8  r   ExportTypesPROTOBUF_FILEr   _export_filer   r7   r   r.   r%   r   r)   rk   r   r   r   r  )r  r   r   r  verification_optionsoriginal_jit_graphgraph_inputsarg
jit_inputsrV   weightsjit_input_and_parametersjit_outsonnx_params_dictr   r)  rA  export_typenew_input_namesnew_input_argsr   re   rj   ry   s                           r!   verify_aten_graphr]  [  s    #24JJLE 'LzES_EFJ3?J@Q3RSa{1;;=)SGS.g....z*J)E'N:xx,,U4LMHhu.: :~{E 4~/E: !#

G"..<<K!!%+zJ#27,,.AQ1;;=AA,335zB 	+FAs{{}/%%c*	+ >*
- 88 ((	
 -W6J6R6RSlK8		1)# , UHi//i FS0 B0  	1eXy00	1
  56m/0ne$	ss   H3H3(H8I -H=6I ;A#I I -I =I 	IIII II 	J'%JJc                      e Zd ZU ded<   ded<   ded<   ded<   ded<   ded	<   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 Zy)GraphInfoPrettyPrinterGraphInfo | None
graph_infozGraphInfoPrettyPrinter | Noneupper_printerlower_printerzMapping[int, str]graph_str_lambdasconnector_str_lambdaschildren_str_lambdasc                    || _         |M|j                  A|j                  5t        |j                        | _        t        |j                        | _        y d | _        d | _        y r2   )ra  upper_graph_infolower_graph_infor_  rb  rc  )r   ra  s     r!   r   zGraphInfoPrettyPrinter.__init__  s]    $"++7++7!7
8S8S!TD!7
8S8S!TD!%D!%Dr    c                    | j                   y| j                  rD| j                  r8| j                  j                         | j                  j                         z   dz   S y)Nr   r   )ra  rb  rc  _total_rowsr   s    r!   rk  z"GraphInfoPrettyPrinter._total_rows  sV    ??"$"4"4""..043E3E3Q3Q3SSVWW r    c                   | j                   y| j                   j                         }| j                   j                         }|dk(  r.|r,d| j                   j                         j	                          dnd}| d|rdn
t        d       d| S )	N...r   (r   r    Xi'  )ra  essential_node_counthas_mismatchessential_node_kindspopchr)r   
node_countrr  error_node_kinds       r!   _node_count_segment_strz.GraphInfoPrettyPrinter._node_count_segment_str  s    ??"__99;
335 Q< 446::<=Q? 	 QlsFDAoEVWWr    c                N    | j                   yd| j                   j                   S )Nr   zid: )ra  idr   s    r!   _graph_id_segment_strz,GraphInfoPrettyPrinter._graph_id_segment_str  s'    ??"doo(()**r    c                p    t        t        t        | j                         | j	                         f            S r2   )maxmaprc   rx  r{  r   s    r!   _max_segment_columnsz+GraphInfoPrettyPrinter._max_segment_columns  s0    d224d6P6P6RST
 	
r    c                F   |dk(  r4| j                         }|d| j                         t        |      z
  z  z  }|S |dk(  r4| j                         }|d| j                         t        |      z
  z  z  }|S d|cxk  r| j	                         k  rn yd| j                         z  S y)zEGet the string representation of the graph segment at the given line.r   ro  r   r   )rx  r  rc   r{  rk  )r   r   
result_strs      r!   _graph_segment_str_at_linez1GraphInfoPrettyPrinter._graph_segment_str_at_line  s    19557J#!:!:!<s:!NOOJ19335J#!:!:!<s:!NOOJ)t'')) 22444r    c                   | j                   | j                  y| j                   r| j                   j                         nd}| j                  r| j                  j                         nd}|dk(  ry||dz   k  ry||dz   k(  ry|||z   dz   k  ryy)z3Get the connector segment string at the given line.r   r   r   z  __z |  z |__z    )rb  rc  rk  r   r   upper_total_rowslower_total_rowss       r!   _connector_segment_str_at_linez5GraphInfoPrettyPrinter._connector_segment_str_at_line  s    %$*<*<*D?C?Q?Q4--99;WX?C?Q?Q4--99;WX19$q((%))$'77!;;r    c                   | j                   | j                  y| j                   r| j                   j                         nd}| j                  r| j                  j                         nd}d|cxk  r|k  r,n n)| j                   r| j                   j                  |      S dS ||cxk  r||z   dz   k  r2n y| j                  r!| j                  j                  ||z
  dz
        S dS y)zGet the string representation of the children at the given line.

        Recursively calls `_str_at_line` on children nodes.
        r   r   r   rm  )rb  rc  rk  _str_at_liner  s       r!   _children_str_at_linez,GraphInfoPrettyPrinter._children_str_at_line  s    
 %$*<*<*D?C?Q?Q4--99;WX?C?Q?Q4--99;WX'''9=9K9K""//5QV N'7:J'JQ'NN  %% ""//7G0G!0KL 
 r    c                l    | j                  |      | j                  |      z   | j                  |      z   S )z=Get the string representation of the graph at the given line.)r  r  r  )r   r   s     r!   r  z#GraphInfoPrettyPrinter._str_at_line  s=     ++D111$78((./	
r    c                8   | j                   t        d        y t        dj                  dd             | j                         }t	        |      D ]*  }t        | j                  |      j                                , | j                   j                         rt        dj                  dd             t        | j                   j                         D cg c]  }|j                   c}       i }| j                   j                         D ]I  }|j                         }t        |      dk(  s"|j                         }|j                  |d      dz   ||<   K t        dj                  dd             t        |       y t        dj                  dd             y c c}w )	Nz Tree: P   =z Mismatch leaf subgraphs: r   r   z Mismatch node kinds: z No mismatch found. )ra  r  centerrk  ranger  rstriprr  all_mismatch_leaf_graph_inforz  rs  rc   rt  get)r   
total_rowsr   ra  mismatch_node_kinds
node_kinds	node_kinds          r!   pretty_printz#GraphInfoPrettyPrinter.pretty_print  se   ??"$Kir3'(%%'
*% 	4D$##D)0023	4??'').55b#>? '+oo&R&R&T" MM 35"ooJJL 
'<<>
z?a' * 0I+//	1=A (	2	 *11"c:;%&(//C89#s   FN)ra  r`  r   rD   r   )r   rD   r   ru   )r   r   r   r0   r   rk  rx  r{  r  r  r  r  r  r  r   r    r!   r_  r_    sY      0000((,,++&X+


 *
:r    r_  c                  :    e Zd Zd Ze	 d	 	 	 	 	 dd       ZddZy)OnnxTestCaseReproc                b    || _         t        j                  |      \  | _        | _        | _        y r2   )	repro_dirr   load_test_caser   rL   outputs)r   r  s     r!   r   zOnnxTestCaseRepro.__init__<  s)    "0@0O0O1
-
DKr    Nc                    |-t         j                   j                         j                  d      }t        j                  |t        |      t        |      ||      S )u3  Create a repro under "{dir}/test_{name}" for an ONNX test case.

        The test case contains the model and the inputs/outputs data. The directory
        structure is as follows:

        dir
        ├── test_<name>
        │   ├── model.onnx
        │   └── test_data_set_0
        │       ├── input_0.pb
        │       ├── input_1.pb
        │       ├── output_0.pb
        │       └── output_1.pb

        Args:
            proto: ONNX model proto.
            inputs: Inputs to the model.
            outputs: Outputs of the model.
            dir: Directory to save the repro.
            name: Name of the test case. If not specified, a name based on current time
                will be generated.
        Returns:
            Path to the repro.
        z%Y_%m_%d_%H_%M_%S_%f)datetimenowstrftimer   export_as_test_caserC   )clsr   rL   r  dirr_   s         r!   create_test_case_reproz(OnnxTestCaseRepro.create_test_case_reproB  sU    8 <$$((*334JKD33fg
 	
r    c                   t        t        j                  | j                        |j                        }|j                  d| j                        }t        |d      r(|j                         D cg c]  }|j                   }}n0t        |d      r|j                  }nt        dt        |             |D cg c]  }| j                  |    }}t        |||       yc c}w c c}w )a2  Run the ONNX test case with options.backend, and compare with the expected outputs.

        Args:
            options: Options for validation.

        Raise:
            AssertionError: if outputs from options.backend and expected outputs are not
                equal up to specified precision.
        Nget_outputsr   zUnknown onnx session type: )r   r7  r8  r   r)   rd   rL   r^   r  r_   r   r`   ra   r  r   )r   r   re   run_outputsor   r_   expected_outss           r!   validatezOnnxTestCaseRepro.validateh  s     -RZZ

-CW__U"&&tT[[9</,8,D,D,FGqAFFGLG\>2'44L:4;M:NOPP8DEd+EE+KP H
 Fs   .C8C#r2   )r   bytesr  ru   r_   
str | None)r   r#   )r   r   r   r   classmethodr  r  r   r    r!   r  r  ;  s=    
 IM#
#
14#
<F#
 #
JQr    r  c                     e Zd ZU dZded<   ded<   ded<    ej                  ej                        Z	d	ed
<    ej                  dd      Z
ded<    ej                  dd      Zded<    ej                  dd      Zded<    ej                  dd      Zded<    ej                  d      Zded<    ej                  dd      Zded<    eh d      Zded<   d Zd  Zd1d2d!Zd3d"Zd4d#Zd5d$Zd6d%Zd7d&Z	 d8	 	 	 	 	 d9d'Zd4d(Zd:d)Zd:d*Z	 	 	 	 	 	 	 	 	 	 	 	 d;d+Z	 	 	 	 	 	 	 	 d<d,Zd- Z 	 	 	 	 	 	 	 	 d=d.Z!	 	 	 	 d>d/Z"	 d?	 d@d0Z#y)A	GraphInfoz^GraphInfo contains validation information of a TorchScript graph and its converted ONNX graph.torch.Graphr  tuple[Any, ...]r   dict[str, Any]r  )default_factory_experimental.ExportOptionsr   NF)defaultinitzAssertionError | Nonemismatch_errorzSequence[_NumericType] | Noner   r`  rh  ri  r   )r  ru   rz  )r  r  ztorch.Graph | None_onnx_graph>   prim::Constantprim::ListConstructaten::ScalarImplicitzfrozenset[str]_EXCLUDED_NODE_KINDSc                J    d| _         d| _        d| _        d| _        d| _        y)z2Clear states and results of previous verification.N)r  r   r  rh  ri  r   s    r!   clearzGraphInfo.clear  s)    " $ $r    c                6    t        |       j                          y)u  Pretty print `GraphInfo` tree.

        Each node represents a subgraph, showing the number of nodes in the subgraph and
        a check mark if the subgraph has output mismatch between torch and ONNX.

        The id of the subgraph is shown under the node. The `GraphInfo` object for any
        subgraph can be retrieved by calling `graph_info.find_partition(id)`.

        Example::

            ==================================== Tree: =====================================
            5 X   __2 X    __1 ✓
            id:  |  id: 0 |  id: 00
                 |        |
                 |        |__1 X (aten::relu)
                 |           id: 01
                 |
                 |__3 X    __1 ✓
                    id: 1 |  id: 10
                          |
                          |__2 X     __1 X (aten::relu)
                             id: 11 |  id: 110
                                    |
                                    |__1 ✓
                                       id: 111
            =========================== Mismatch leaf subgraphs: ===========================
            ['01', '110']
            ============================= Mismatch node kinds: =============================
            {'aten::relu': 2}

        N)r_  r  r   s    r!   pretty_print_treezGraphInfo.pretty_print_tree  s    @ 	t$113r    c                   t        d| j                   dj                  dd             |rlt        dj                  dd             t        | j                         | j                  0t        dj                  dd             t        | j                         | j                         r1t        dj                  dd             t        | j                         yt        d	j                  dd             y)
zPretty print details of the mismatch between torch and ONNX.

        Args:
            graph: If True, print the ATen JIT graph and ONNX graph.
        z# Mismatch info for graph partition : r  r  z ATen JIT graph Nz ONNX graph z Mismatch error z No mismatch )r  rz  r  r  r  rr  r  )r   r  s     r!   pretty_print_mismatchzGraphInfo.pretty_print_mismatch  s     	3DGG9B?FFr3OP$++B45 $**+n++B45d&&'$++B45$%%&/((S12r    c                    | j                   duS )zGReturn True if the subgraph has output mismatch between torch and ONNX.N)r  r   s    r!   rr  zGraphInfo.has_mismatch  s    ""$..r    c                \     t         fd j                  j                         D              S )zUReturn the number of nodes in the subgraph excluding those in `_EXCLUDED_NODE_KINDS`.c              3  \   K   | ]#  }|j                         j                  vs d  % yw)r   N)kindr  )rH  nr   s     r!   rJ  z1GraphInfo.essential_node_count.<locals>.<genexpr>  s)      
QVVXT=V=V-VA
s   !,,)r   r  r   r   s   `r!   rq  zGraphInfo.essential_node_count  s*     
zz'')
 
 	
r    c                    | j                   j                         D ch c].  }|j                         | j                  vr|j                         0 c}S c c}w )zWReturn the set of node kinds in the subgraph excluding those in `_EXCLUDED_NODE_KINDS`.)r  r   r  r  )r   r  s     r!   rs  zGraphInfo.essential_node_kinds  sK     ZZ%%'
vvxt888 FFH
 	
 
s   3Ac                   | j                         sg S | j                  du xs | j                  j                          xr+ | j                  du xs | j                  j                          }|r| gS g }| j                  || j                  j                         z  }| j                  || j                  j                         z  }|S )zAReturn a list of all leaf `GraphInfo` objects that have mismatch.N)rr  rh  ri  r  )r   no_mismatch_childrenresultss      r!   r  z&GraphInfo.all_mismatch_leaf_graph_info  s      "I !!T)U1F1F1S1S1U-U 
 !!T)U1F1F1S1S1U-U 	  6M  ,t,,IIKKG  ,t,,IIKKGr    c                (   || j                   k(  r| S t        | j                         }t        |      |kD  r^||   dk(  r'| j                  | j                  j                  |      S ||   dk(  r'| j                  | j                  j                  |      S y)z.Find the `GraphInfo` object with the given id.0N1)rz  rc   rh  find_partitionri  )r   rz  current_lengths      r!   r  zGraphInfo.find_partition  s    =KTWWr7^#.!S(T-B-B-N,,;;B??N#s*t/D/D/P,,;;B??r    c                X   |t        j                         }t         j                  j                  |d      }t	        | j
                  | j                  | j                        \  }}t        || j                  |      \  }}t        j                  || j                  | j                  ||      S )u  Export the subgraph to ONNX along with the input/output data for repro.

        The repro directory will contain the following files::

            dir
            ├── test_<name>
            │   ├── model.onnx
            │   └── test_data_set_0
            │       ├── input_0.pb
            │       ├── input_1.pb
            │       ├── output_0.pb
            │       └── output_1.pb

        Args:
            repro_dir: The directory to export the repro files to. Defaults to current
                working directory if None.
            name: An optional name for the test case folder: "test_{name}".

        Returns:
            The path to the exported repro directory.
        
onnx_debug)r<  getcwdr=  r   r   r  r   r  r*  r  r  r   r   )r   r  r_   r  rY  r   r   s          r!   export_reprozGraphInfo.export_repro  s    2 		IGGLLL9	'BJJ++T-=-=(
$
$ /++-=
q !774??DLL)T
 	
r    c                
   t        | j                  j                               D cg c]#  \  }}|j                         | j                  vr|% }}}t        |      dz  dz
  }|dk\  rt        |      |kD  r||   dz   S yc c}}w )a  Find the pivot index to partition the graph.

        The pivot is the node that splits the graph into two parts. Each part should
        have the similar amount of nodes, excluding non essential ops, defined in
        `_EXCLUDED_NODE_KINDS`, such as `prim::Constant`.
        If the graph has an odd number of nodes, the upper part will have one more node.
        If the graph does not have any node that can be partitioned, return -1.

        Returns:
            The index of the pivot node.
        r   r   r   rY   )rb   r  r   r  r  rc   )r   rN   r  included_node_indiceshalf_idxs        r!   _graph_partition_pivotz GraphInfo._graph_partition_pivot/  s     "$**"2"2"45!
1vvxt888 !
 !

 ,-2Q6q=S!67(B(2Q66!
s   (A?c           
        | j                         }|dk(  rt        j                         S | j                  j	                         }t        |j                               }	 	 	 	 	 	 dd}g }t        j                  ||      }| j                  |||      \  }}}	}t        |      D ]  }|j                  d        |D ]  }
|j                  |
        t        |      D ]  }|j                           t        t        t        t        |j                                                 D ])  \  }}t!        ||	      r||vs	 |j#                  |       + |S # t$        $ r}t'        ||       |d }~ww xY w)NrY   c                (    | j                  |       |S r2   )r7   )new_outputsbridge_values     r!   _process_bridge_value_for_upperzIGraphInfo._partition_upper_graph.<locals>._process_bridge_value_for_upperL  s     |,r    r   )r  zlist[torch.Value]r  torch.Valuer   r  )r  r<   Graphr  r   rB   r  	functoolspartial_partition_nodesrb   eraseOutputregisterOutputreverseddestroyrL   _has_uses_by_nodes
eraseInputRuntimeErrorr  )r   pivotr  original_outputsr  r  process_bridge_value_for_upperr   dropped_nodescomplete_upper_nodes_setoutputnoderN   ri   ry   s                  r!   _partition_upper_graphz GraphInfo._partition_upper_graphE  s   ++-B;;;= 

!0	 *	 :E	 	  *,)2):):+[*
& 9=8M8M589
5=2A +, 	!Aa 	!! 	)F  (	) ]+ 	DLLN	 !iU\\^0D&E!FG 		HAu&u.FG,$$Q'		 	 $ %'Gs   =E	E.E))E.c                f   | j                         }|dk(  rt        j                         S | j                  j	                         }t        |j                               }t        |j                               }g }	 	 	 	 	 	 dd}t        j                  ||      }| j                  |||      \  }}	}
}|D ]   }t        ||	      s|j                  |       " t        |      D ]  }
|j                  d        |D ]  }|j                  |        |D ]A  }t!        ||      s|j#                         }|j%                  |       |j'                  |       C t)        |      D ]  }||vs	 |j+                           |D ]  }
|j1                  d        |S # t,        $ r}t/        ||       |d }~ww xY w)NrY   c                j    | j                         }|j                  |       |j                  |       |S r2   )addInputreplaceAllUsesWithcopyMetadata)r  r  	new_inputs      r!   _process_bridge_value_for_lowerzIGraphInfo._partition_lower_graph.<locals>._process_bridge_value_for_lowerz  s2     (I++I6""<0r    r   )r  r  r  r  r   r  )r  r<   r  r  r   rB   r  rL   r  r  r  _produced_byr7   rb   r  r  r  r  r  r  r  r  r  r  r  )r   r  r  r  original_inputsr  r  process_bridge_value_for_lowerupper_nodeslower_nodesr   complete_lower_nodes_setr  ri   r  r  ry   s                    r!   _partition_lower_graphz GraphInfo._partition_lower_graphp  s   ++-B;;;= 

!0u||~.		.9		 *3):):+U*
& AE@U@U58A
=[!%= ' 	+FFK0""6*	+ +, 	!Aa 	!! 	)F  (	) % 	.E!%)AB!NN,	((3&&u-		. [) 	D33LLN	 ! 	 AQ	   $ $&Gs   (F	F0F++F0c           	        ||v ry t        ||      rv|j                         | j                  v rZ|j                  t	        |g             |j                         D ]+  }||v r| j                  |j                         |||||       - y |j                         D ]/  }||v rt        ||      s||v s|j                   ||             1 y r2   )_node_has_uses_byr  r  update
_all_nodesrL   _partition_noder  r  r  add)	r   r  r  r  original_graph_outputscovered_bridge_valuesprocess_bridge_valueri   r  s	            r!   r  zGraphInfo._partition_node  s     ++ d$<=		t888$++Jv,>? 
11$$JJL,,*)(
 ,,. L22&v/GH!77)--.B6.JKLr    c           	        t        |j                               }|d | }||d  }t        |      }t        |      }t        |j	                               }	t        |j                               }
|D ]  }| j                  ||||	|
|        ||||fS r2   )rB   r   r  setr  rL   r  )r   r  r  r  r   r   r  r  r  r
  r  r  s               r!   r  zGraphInfo._partition_nodes  s     U[[]#FUmEFm $.k#: #-k#: !$U]]_!5 !$ELLN 3 	D  ((&%$	 $$	
 	
r    c                T   | j                   }t        | j                  j                               }|J t	        |      t	        |      k(  s+J t	        |       dt	        |       d| j                          t        ||      D ci c]  \  }}|j                         | c}}S c c}}w )N vs z
Graph: )r   rB   r  r  rc   r   rK  )r   r   graph_outputsrV   r  s        r!   _bridge_kwargszGraphInfo._bridge_kwargs  s    ,,TZZ//12"""=!S&
 
 	J- !c'l^9TZZLI	J 
 .1-HITQq IIIs   B$c                   |j                         D cg c]  }|j                          }}t        fd|D              }|t        fd|D              z  }|D ci c]  }||v s|||    }	}t        |      t        |	      z   t        |      k(  s-J t        |       dt        |	       dt        |       d|        ||	fS c c}w c c}w )Nc              3  2   K   | ]  }|v s|     y wr2   r   )rH  rI   bridge_kwargss     r!   rJ  zAGraphInfo._args_and_params_for_partition_graph.<locals>.<genexpr>  s     Q!a=>P]1%Q   	
c              3  2   K   | ]  }|v s|     y wr2   r   )rH  rI   full_kwargss     r!   rJ  zAGraphInfo._args_and_params_for_partition_graph.<locals>.<genexpr>  s     NQ+=Mk!nNr   + r  r  )rL   rK  r4   rc   )
r   r  r  r  full_paramsri   r[   r   rI   paramss
     ``      r!   $_args_and_params_for_partition_graphz.GraphInfo._args_and_params_for_partition_graph  s     7<llnEUu(EEQ{QQNkNNN-8MA<L![^#MM4y3v;&#+
 
 	O$i[CK=S-=,>bN	O 
 V| F Ns   C	C
'C
c                r    t        | j                  | j                  | j                  | j                  |      S )a  
        Verify the export from TorchScript IR graph to ONNX.

        Export the TorchScript IR graph to ONNX, with the inputs, parameters and export
        options recorded in this object. Then verify the exported ONNX graph against
        the original TorchScript IR graph under the provided verification options.

        Args:
            options: The verification options.

        Returns:
            error: The AssertionError raised during the verification. Returns None if no
            error is raised.
            onnx_graph: The exported ONNX graph in TorchScript IR format.
            onnx_outs: The outputs from running exported ONNX model under the onnx
            backend in `options`.
            pt_outs: The outputs from running the TorchScript IR graph.
        )r   r  r   rQ  )r]  r  r   r  r   )r   r   s     r!   verify_exportzGraphInfo.verify_export  s4    * !JJ((..!(
 	
r    c           	        | j                          |
t               }| j                  j                  rt	        | j
                         t        t        | j
                  j                                     dk(  ryt        | j                        t        | j                        z   t        t        | j
                  j                                     k(  saJ dt        t        | j
                  j                                      dt        | j                         dt        | j                         d       | j                  |      \  | _        | _        | _        }| j                  y| j!                         dk  ryt#        | j
                  j                         | j                        D ci c]  \  }}|j%                         | }}}| j                  }| j'                         }| j)                  |i ||      \  }}	t+        |||	| j                  | j,                  dz   	      | _        | j.                  j1                  |       | j.                  j3                         }
| j5                         }| j)                  ||
||      \  }}t+        |||| j                  | j,                  d
z   	      | _        | j6                  j1                  |       yc c}}w )a  
        Find all mismatches between the TorchScript IR graph and the exported onnx model.

        Binary searches the model graph to find the minimal subgraph that exhibits the
        mismatch. A `GraphInfo` object is created for each subgraph, recording the test
        inputs and export options, as well as the validation results.

        Args:
            options: The verification options.
        Nr   zNumber of graph inputs(z/) does not match the provided tensor arguments(r  z).r   r  )rz  r  )r  r#   r   r   r  r  rc   rB   r  r   r  rL   r  r  r  r   rq  r   rK  r  r  r  rz  rh  find_mismatchr  r  ri  )r   r   r   rI   rV   r  r  upper_graph
upper_argsupper_paramsr  lower_graph
lower_argslower_paramss                 r!   r   zGraphInfo.find_mismatch)  s    	

?)+G&&$**tDJJ&&()*a/4??#c$*:*:&;;s""$%@
 
 	
 &c$tzz/@/@/B*C&D%E F--0-A,B#c$JZJZF[E\\^`	
 
 BFASASB
>T-t|Q &$$&!+ *-TZZ->->-@$//)R
!%AAKKM1
 
 &&113#'#L#L[+$
 
L !*ww}!
 	++G4--<<>113#'#L#L[$
 
L !*ww}!
 	++G4A
s   (K	)F)r  r$   )r   r$   r  )r   zset[str])r   zlist[GraphInfo])rz  ru   r   r`  NN)r  r  r_   r  r   ru   )r   r  )r  
torch.Noder  set[torch.Node]r  r)  r
  set[torch.Value]r  r*  r  $Callable[[torch.Value], torch.Value])r  r  r  rD   r  r+  r   zKtuple[list[torch.Node], list[torch.Node], set[torch.Node], set[torch.Node]])r  r  r  z3Mapping[str, _NumericType | Sequence[_NumericType]]r  Mapping[str, torch.Tensor]r  r,  )r   r#   r   Etuple[AssertionError | None, torch.Graph, _OutputsType, _OutputsType]r2   )r   VerificationOptions | None)$r   r   r   r   r0   dataclassesfieldr   r,  r   r  r   rh  ri  rz  r  	frozensetr  r  r  r  rr  rq  rs  r  r  r  r  r  r  r  r  r  r  r  r   r   r    r!   r  r  ~  s   h2C+2C2C%333N/  ->K,=,=dQV,WN)W->[->->tRW-XG*X):):):4e)T&T):):):4e)T&Tk+B+&7k&7&7UD&QK#Q+4I,. % 4D3,/

,
 @D&
#&
2<&
	&
P,)V4l$L$L #2$L #2	$L
 !1$L  0$L C$LL%
%
 %
 C	%

 
U%
NJ K 0	
 0 
*
	N
> /3L5+L5r    r  c           
         t        |       }| D ]H  }|j                         D ]3  }|j                  t        t	        |j                                            5 J |S r2   )r  blocksr  r  rB   r   )r   	all_nodesr  bs       r!   r  r  x  sT    E
I : 	:AZQWWY89	:: r    c                H    t        fd| j                         D              S )Nc              3  :   K   | ]  }|j                   v   y wr2   )user)rH  user   s     r!   rJ  z%_has_uses_by_nodes.<locals>.<genexpr>  s     9Ssxx5 9s   )anyusesrU   r   s    `r!   r  r    s    9EJJL999r    c                J    | j                         D ]  }t        ||      s y y)NTF)r  r  )r  r   r  s      r!   r  r    s)    ,,. fe, r    c                &    | j                         |v S r2   )r  r<  s     r!   r  r    s    ::<5  r    c                "   |
t               }|t        j                  }	 |t        j                  j
                  j                  k(  r| j                          n7|t        j                  j
                  j                  k(  r| j                          t        j                         5  t        |i       }t        j                  | |      }	t        j                  | |	      } t        j                  | |	      \  }
}}}t        j                   |
|      }t        j"                  |
|       t%        |
||t'        j(                  |||||            }|j+                  |       |j-                          |j/                          |cddd       S # 1 sw Y   yxY w)a  Find all mismatches between the original model and the exported model.

    Experimental. The API is subject to change.

    This tool helps debug the mismatch between the original PyTorch model and exported
    ONNX model. It binary searches the model graph to find the minimal subgraph that
    exhibits the mismatch.

    Args:
        model: The model to be exported.
        input_args: The input arguments to the model.
        do_constant_folding: Same as `do_constant_folding` in :func:`torch.onnx.export`.
        training: Same as `training` in :func:`torch.onnx.export`.
        opset_version: Same as `opset_version` in :func:`torch.onnx.export`.
        keep_initializers_as_inputs: Same as `keep_initializers_as_inputs` in :func:`torch.onnx.export`.
        verbose: Same as `verbose` in :func:`torch.onnx.export`.
        options: The options for the mismatch verification.

    Returns:
        A GraphInfo object that contains the mismatch information.

    Example::

        >>> import torch
        >>> import torch.onnx.verification
        >>> torch.manual_seed(0)
        >>> opset_version = 15
        >>> # Define a custom symbolic function for aten::relu.
        >>> # The custom symbolic function is incorrect, which will result in mismatches.
        >>> def incorrect_relu_symbolic_function(g, self):
        ...     return self
        >>> torch.onnx.register_custom_op_symbolic(
        ...     "aten::relu",
        ...     incorrect_relu_symbolic_function,
        ...     opset_version=opset_version,
        ... )
        >>> class Model(torch.nn.Module):
        ...     def __init__(self) -> None:
        ...         super().__init__()
        ...         self.layers = torch.nn.Sequential(
        ...             torch.nn.Linear(3, 4),
        ...             torch.nn.ReLU(),
        ...             torch.nn.Linear(4, 5),
        ...             torch.nn.ReLU(),
        ...             torch.nn.Linear(5, 6),
        ...         )
        ...     def forward(self, x):
        ...         return self.layers(x)
        >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_ONNX)
        >>> graph_info = torch.onnx.verification.find_mismatch(
        ...     Model(),
        ...     (torch.randn(2, 3),),
        ...     opset_version=opset_version,
        ... )
        ===================== Mismatch info for graph partition : ======================
        ================================ Mismatch error ================================
        Tensor-likes are not close!
        Mismatched elements: 12 / 12 (100.0%)
        Greatest absolute difference: 0.2328854203224182 at index (1, 2) (up to 1e-07 allowed)
        Greatest relative difference: 0.699536174352349 at index (1, 3) (up to 0.001 allowed)
        ==================================== Tree: =====================================
        5 X   __2 X    __1 \u2713
        id:  |  id: 0 |  id: 00
             |        |
             |        |__1 X (aten::relu)
             |           id: 01
             |
             |__3 X    __1 \u2713
                id: 1 |  id: 10
                      |
                      |__2 X     __1 X (aten::relu)
                         id: 11 |  id: 110
                                |
                                |__1 \u2713
                                   id: 111
        =========================== Mismatch leaf subgraphs: ===========================
        ['01', '110']
        ============================= Mismatch node kinds: =============================
        {'aten::relu': 2}

    N)r  r   r   r#  r   )r#   r   r  r<   r   r  r1  r2  r  r3  r4  r   r   r
  r   r   _get_named_param_dict_apply_friendly_debug_namesr  r   r,  r   r  r  )rw   r   r  r   r   r#  r   r   rC  r   r  r  	torch_outmoduler  ra  s                   r!   r   r     sP   v %'"55c5::**333	UZZ,,11	1

	 5j"E))%1BC,,UD9+0+B+B5$+O(vy&11%@))%=''$7!+,G	

 	  )((*$$&5  s   #CFF)r   zlist | np.ndarray)r   rB   )T)r   _OutputsType)rw   str | io.BytesIOrx   zSequence[str])rw   rE  )rw   rE  r)   r   )rj   rD  r   rD  r   r#   )rj   rD  r   r   r   r#   )r.   r-   r%   r$   )r   
_ModelTyper   rE  r   _InputArgsTyper   _InputKwargsType | Noner   Sequence[_InputArgsType] | Noner   r#   )
rw   (torch.nn.Module | torch.jit.ScriptModuler   3Sequence[tuple[tuple[Any, ...], Mapping[str, Any]]]r   r  r   zfCallable[[torch.nn.Module, tuple[Any, ...], Mapping[str, Any], _experimental.ExportOptions], _C.Graph]r   ru   )
rw   rJ  r   r  r   zMapping[str, Any]r   r  r   r   r2   )r  r  r   r  r  dict[str, Any] | Noner   z"tuple[torch.Graph, dict[str, Any]])r  r  r   r  r  r  r   z!tuple[bytes, Mapping[str, bytes]])rw   rJ  r   rK  r   z"_experimental.ExportOptions | Noner   ru   )rw   rF  r   rG  r   rH  r  r$   r   zDMapping[str, Mapping[int, str] | Mapping[str, Sequence[int]]] | Noner[   Sequence[str] | Noner   rM  r   _C_onnx.TrainingModer   
int | Noner#  r$   r   r$   r0  r$   r?  r$   r   rI  r   r.  r'  )r  r  r   r  r   r  r  rL  rQ  r.  r   r-  )r   Collection[torch.Node]r   r)  )rU   r  r   rP  r   r$   )r  r(  r   rP  r   r$   )rw   rJ  r   r  r  r$   r   rN  r   rO  r#  r$   r   r$   r   r.  r   r  )\r   
__future__r   r5  r   r/  r  r   enumr  r7  r   r<  r:  r   typingr   r   r   r   r   r	   r
   rA   rE   r<   torch._C._onnxr   _onnxr  
torch.onnxr   r   r   r   torch.onnx._globalsr   torch.onnx._internalr   torch.typesr   rq   r=   ndarray_NumericTypennModuler   ScriptModulerF  rG  ru   _InputKwargsTyperD  Enumr   	dataclassr#   r6   rC   rK   rW   rk   r|   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r*  r.  r  r  rE  r]  r_  r  r  r  r  r  r  r   r   r    r!   <module>rb     s&  
 #        	  	   M M M        I I ' 1  +VU\\2::56588??EII$:$::;
u||U38_4538$ Xl+X560$)) 0 #5 #5 #5L$2> =K,9. ... !.bHHH !H840+?JN:/G/G"/G /G *	/G
 </G !/GdB, B,J&3&J& 0&	& 	&R3
  0	
 6=3=
= = 0	=
 =F *.<</< '< (	<~/   '	H :>(3(J( 7( 		(\ -1 $(,)-%,%9%9%>%> $(,"#>B*.!T
T
T
 *T
 	T

T
 &T
 'T
 #T
 T
 "&T
 T
 T
 T
 <T
  (!T
v *.7;KKK 0K '	K
 5K KK\O: O:d@Q @QF v5 v5 v5r:! !%%,%9%9%>%> $(,*.3  #	
  "&  ( r    