
    sgTK                        d dl Z d dlZd dlmZmZmZmZmZmZ d dl	Z	d dl
mZmZ d dlmZ d dlmZ d dlmZmZ ddlmZmZ dd	lmZmZ dd
lmZmZmZ e	j<                  j>                  Z dedee   fdZ! G d d      Z" G d de#      Z$ G d dejJ                        Z&dededededeeeef      de&fdZ'dededee(ee   f   dee(   de(f
dZ)dededee   fdZ*	 	 d"dededeee(ee   f      d eee(ee   f      dee(eeef   f   f
d!Z+y)#    N)AnyDictListOptionalSetTuple)FakeQuantizeBaseObserverBase)getattr_from_fqn)GraphModule)GraphNode   )$get_base_name_to_sets_of_related_opsget_unmatchable_types_map)NSNodeTargetType
NSSubgraph) end_node_matches_reversed_fusionget_reversed_fusionsget_type_a_related_to_bgreturnc                 `    | j                   D cg c]  }|j                  dk(  s| c}S c c}w )Noutput)nodesop)r   ns     O/var/www/html/venv/lib/python3.12/site-packages/torch/ao/ns/fx/graph_matcher.py_get_output_nodesr      s%    ww3!!$$("2A333s   ++c            	       l    e Zd ZdZdedee   dee   dee   fdZd Zde	fd	Z
d
eddfdZdedefdZy)"_NSGraphMatchableSubgraphsIteratorz
    Iterates through the graph of gm, starting with the output nodes
    and continuing backwards.
    1. Returns matchable subgraphs, in order. A subgraph is defined by
       (start_node, end_node).
    2. Skips over non-matchable subgraphs
    gmnon_matchable_functionsnon_matchable_modulesnon_matchable_methodsc                     || _         || _        || _        || _        t	               | _        g | _        t        | j                   j                        D ]  }| j                  j                  |        y N)
r"   r#   r$   r%   set
seen_nodesstackr   graphappend)selfr"   r#   r$   r%   
start_nodes         r   __init__z+_NSGraphMatchableSubgraphsIterator.__init__%   sa      ">U$<Q"<Q"%(U!#
+DGGMM: 	*JJJj)	*    c                     | S r'    )r-   s    r   __iter__z+_NSGraphMatchableSubgraphsIterator.__iter__5   s    r0   r   c                    t        | j                        dkD  rm| j                  j                         }|| j                  v rB|}|}t	               D ]  \  }}t        ||| j                  | j                        }|s+t        t        |      dz
        D ]E  }| j                  j                  |       |j                  d   }t        |      dz
  |z
  }||k(  sD|}G  n | j                  j                  |       |j                  D ]  }	| j                  |	        | j                  |      s-|j                  dk(  r<||u r8t        | j                  |j                        }
t!        |
t"        t$        f      rxt'        |||      S t(        )z6
        Returns the next matchable subgraph.
        r   r      call_module)r.   end_nodebase_op_node)lenr*   popr)   r   r   r"   rangeaddargsall_input_nodes"_recursively_add_node_arg_to_stack_is_matchabler   r   target
isinstancer
   r	   r   StopIteration)r-   cur_end_nodecur_start_nodecur_base_op_node_reverse_fusion_opsbase_op_idxis_matchrev_fusion_idxrev_base_op_idxarg	maybe_obss              r   __next__z+_NSGraphMatchableSubgraphsIterator.__next__8   s    $**o!::>>+Lt. *N  , 5I4J 0#[; "5tww */4G0H10L*M >++N; *8)<)<Q)?*-.A*BQ*F*T)_</=,> " OO/%55 =77<= %%&67 -/Nl4R,TWWl6I6IJ	i,8H)IJ)%-  r0   rL   Nc                    t        |t              r| j                  j                  |       yt        |t        j
                  j                  j                        st        |      t        u r|D ]  }| j                  |        yt        |t        j
                  j                  j                        r'|j                         D ]  }| j                  |        yy)z}
        Adds all of the nodes in this arg to the stack, properly navigating
        through list, dicts and tuples.
        N)rB   r   r*   r,   torchfximmutable_collectionsimmutable_listtypetupler?   immutable_dictvalues)r-   rL   	inner_argvalues       r   r?   zE_NSGraphMatchableSubgraphsIterator._recursively_add_node_arg_to_stack~   s    
 c4 JJc"sEHH::IIJCyE!  C	77	BCUXX;;JJK ?77>? Lr0   nodec                 v   |j                   dk(  r|j                  | j                  vS |j                   dk(  r[t        |j                  t              sJ t        | j                  |j                        t        fd| j                  D               S |j                   dk(  r|j                  | j                  vS y)Ncall_functionr6   c              3   6   K   | ]  }t        |        y wr'   )rB   ).0t
target_mods     r   	<genexpr>zC_NSGraphMatchableSubgraphsIterator._is_matchable.<locals>.<genexpr>   s        :q)s   call_methodF)
r   rA   r#   rB   strr   r"   anyr$   r%   )r-   rZ   r`   s     @r   r@   z0_NSGraphMatchableSubgraphsIterator._is_matchable   s    77o%;;d&B&BBBWW%dkk3///)$''4;;?J 33    WW%;;d&@&@@@r0   )__name__
__module____qualname____doc__r   r   r   r/   r3   r   rN   r   r?   r   boolr@   r2   r0   r   r!   r!      s~    ** "%%5!6*  ##34	*
  ##34* D* DL?c ?d ?"$ 4 r0   r!   c                       e Zd ZdZy)GraphMatchingExceptionz=
    Exception raised when two graphs cannot be matched.
    N)re   rf   rg   rh   r2   r0   r   rk   rk      s    r0   rk   c                       e Zd Z ej                         Z ej                         Z ej                         Z ej                         Zy)SubgraphTypeRelationshipN)	re   rf   rg   enumautoEQUALEQUAL_BUT_UKNOWNRELATED_BUT_NOT_EQUALNOT_RELATEDr2   r0   r   rm   rm      s>     DIIKE !tyy{ &DIIK$))+Kr0   rm   
subgraph_a
subgraph_bgm_agm_btype_a_related_to_bc                    | j                   }|j                   }|j                  |j                  k7  r,|j                  dv r|j                  dv st        j                  S |j                  dv r|j                  |j                  f}||vr9|j                  |j                  k(  rt        j
                  S t        j                  S |j                  |j                  k(  r~| j                   | j                  k(  }|j                   |j                  k(  }	|r|	st        j                  S |s|	rt        j                  S |s|	st        j                  S t        j                  S ||v rt        j                  S t        j                  S |j                  dk(  r%| j                   | j                  k(  r|j                   |j                  k(  sJ d       t        |j                  t              sJ t        ||j                        }
t        |j                  t              sJ t        ||j                        }t        |
      t        |      f}||vr7t        |
      t        |      k(  rt        j
                  S t        j                  S t        |
      t        |      k(  rt        j                  S t        j                  S t        j                  S )Nr\   rb   r6   zSMatching call_module patterns where base_op_node != start_node is not supported yet)r8   r   rm   rs   rA   rq   r.   rr   rp   rB   rc   r   rT   )rt   ru   rv   rw   rx   node_anode_bkeynode_a_has_prevnode_b_has_prevmod_amod_bs               r   _get_subgraph_relationship_typer      sO    $$F$$F yyFIIII99		==+777yy44}}fmm,))}}-/@@@/;;; ==FMM)(559N9NNO(559N9NNO/EEE%?/EEE%/555 0555%%+AAA+777	m	###z'<'<<'':+@+@@	a a	aA &----- v}}5&----- v}}5E{DK())E{d5k)/@@@/;;;%[DK'+111+AAA#///r0    base_name_to_sets_of_related_opsexisting_namesc                    t        | j                  |      }d}|j                         D ]  \  }}||v s|} dt        |      z   }d}	|dz   t        |	      z   }
|
|v r|	dz  }	|dz   t        |	      z   }
|
|v r|j	                  |
       |
S )a;  
    Returns a unique name for a subgraph. This name is based on two things:
    1. the name of the set containing the underlying type of the base op in the
       subgraph (i.e. 'torch.nn.functional.linear' if this is related to a linear op)
    2. the number of previous subgraphs with related underlying type of the base op

    For example, in the graph

    linear0 -> relu0 -> linear1 -> relu1

    The subgraphs are (linear0, relu0) and (linear1, relu1).  If we iterate
    from the output node backwards, the name given to (linear1, relu1) will be
    `base_op_torch.nn.functional.linear_0`, and the name given to (linear0, relu0)
    will be `base_op_torch.nn.functional.linear_1`.

    Why are we not just using the node name? Answer: because of two requirements:
    A. fusions must be supported
    B. some Numeric Suite APIs can be called without having all of the models in memory

    For example, let's say we need to match nodes of

    (1) ... -> linear0 -> relu0 -> ...

    And

    (2) ... -> linear_relu0 -> ...

    Without being able to inspect them together. With the current naming scheme, if
    we iterate through both of these graphs in the same order, and assuming the rest
    of the graphs match, both of these subgraphs will get the same name without
    (1) and (2) knowing anything about each other.
    Nbase_op_r   _r   )_get_node_target_typer8   itemsrc   r<   )rt   rv   r   r   target_typetarget_base_type	base_namesets_of_related_opstarget_base_namecounterproposed_names              r   _get_name_for_subgraphr      s    L (
(?(?FK*J*P*P*R )&	&--() "C(8$99G$s*S\9M
>
)1(3.W= >
) }%r0   rZ   r"   c                     | j                   dv r| j                  S | j                   dk(  r=t        | j                  t              sJ t	        || j                        }t        |      S y )Nrz   r6   )r   rA   rB   rc   r   rT   )rZ   r"   mods      r   r   r   /  sV    ww22{{	M	!$++s+++r4;;/Cyr0   unmatchable_types_mapc           	         |
t               }|d   }|d   }|d   }t        | |||      }t        ||||      }t        j                         }	|
t	               }t        |      }
t               }t               }	 d\  }}	 t        |      }	 t        |      }d\  }}|t        |j                  |       }|t        |j                  |      }||t        ||| ||
      }|t        j                  k(  rd| d| d| d| d	}t        |      |t        j                  k(  rt!        || ||      }t!        ||||      }||k(  sJ d	| d
| d       ||f|	|<   ||nd| d| d| d| d	}t        |      t        j                  t#        t%        |	j'                                           }	|	S # t        $ r Y .w xY w# t        $ r Y 2w xY w)a(	  
    Matches matchable subgraphs of graph_a to graph_b.

    For a node, "matchable" is defined as a node which is not an observer,
    fake_quants, quant or dequant.

    A subgraph can contain one or more nodes.  A subgraph is matchable if
    at least one node inside of it is matchable.  Currently, all nodes in
    a subgraph must be matchable (because we assume no observers will be
    inserted in the middle of a fusion).

    A subgraph is defined by (start_node, end_node).  We assume that only
    start_node and end_node are linked with the surrounding graph, all other
    nodes in a subgraph are self-contained.

    A pair of nodes is "related" if both nodes represent the same mathematical
    operation across different quantization flavors. For example,
    `F.linear` and `torch.ops.quantized.linear` are related, and
    `F.linear` and `torch.nn.Conv` are not related.

    For each matchable pair of nodes node_a and node_b, they will match
    if node_a and node_b are related.

    For graphs A and B, they will match iff:
    1. the number of matchable subgraphs in A and B is equivalent
    2. when iterating through the matchable subgraphs of A and B in the same order, each
       corresponding pair of base nodes is related.

    This enables us to find the corresponding subgraphs between
    graphs of related models.  For example, if we had two graphs such as:

    graph_a: x0 -> conv_0 (type: nn.Conv2d) -> obs_0 -> x1
             w  -/
             b  -/

    graph_b: x0 -> quant_0 -> qconv_0 (type: nnq.Conv2d) -> dequant_0 -> x1
           packed_params_0 -/

    This function will return the following result:
    {
        'conv_0': (  # the name of the node in graph_b
          (conv_0, conv_0),  # (start_node_a, end_node_a)
          (qconv_0, qconv_0),  # (start_node_b, end_node_b)
        ),
    }

    Or, if we have a fusion pattern,

    graph_a: x0 -> linear_0 -> relu_0 -> obs_0 -> x1
             w  -/
             b  -/

    graph_b: x0 -> quant_0 -> linear_relu_0 -> dequant_0 -> x1
           packed_params_0 -/

    This function will return the following result:
    {
        'linear_relu_0': (  # the name of the node in graph_b
          (linear_0, relu_0),  # (start_node_a, end_node_a)
          (linear_relu_0, linear_relu_0),  # (start_node_b, end_node_b)
        ),
    }
    funs_unmatchablemods_unmatchablemeths_unmatchableNNz
The subgraphs
(z, z) and
(z)
are not related. Please ensure that the two models you pass in have the same number
of subgraphs, and each pair of subgraphs is related to each other.zSubgraph names z and z do not matchz
Attempting to match
(zj),
one of which is empty. Please ensure that the two models you pass in have the same number
of subgraphs.)r   r!   collectionsOrderedDictr   r   r(   nextrC   r   r.   r   rm   rs   rk   rq   r   reversedlistr   )rv   rw   r   r   r#   r$   r%   graph_a_iteratorgraph_b_iteratorresultsrx   existing_names_aexisting_names_bcur_subgraph_acur_subgraph_btype_start_atype_start_bsubgraph_relationshipmsg
key_name_a
key_name_bs                        r   get_matching_subgraph_pairsr   9  s   J $ 9 ;34FG12DE12EF9%'<>S :%'<>S %%'G'/+O+Q(12RS!$!$
)3&	!"23N	!"23N
 &0"l%01J1JDQL%01J1JDQL %.*D
 %Dd<O%! %(@(L(LLL> "L> "CF -S11&*B*S*SS/&FHXJ 0&FHXJ j(L E*]KL(#1>"BGJ#(>L> "L> "C )--
 %%htGMMO/D&EFGN  		  		s$   >F+ 
F; +	F87F8;	GGr   ),r   rn   typingr   r   r   r   r   r   rP   torch.ao.quantizationr	   r
   torch.ao.quantization.utilsr   torch.fxr   torch.fx.graphr   r   mappingsr   r   ns_typesr   r   pattern_utilsr   r   r   ops	quantizedtoqr   r!   	Exceptionrk   Enumrm   r   rc   r   r   r   r2   r0   r   <module>r      s     8 8  @ 8   & U 2  ii4 44: 4@ @FY tyy D0D0D0 D0 	D0
 U#35E#EFGD0 D0N22
2 '+34D0E+E&F2 H	2
 	2j + (CS:T  TXHL	]
]
] '/tC=M9N4N/O&P] $Dc2B.C)C$DE	]
 
#uZ+,
,-]r0   