
    sh0                     x   S SK JrJrJr  S SKrS SKJr  S SKJs  Jr	  S SK
JrJr  S SKJr  SSKJrJrJr  / SQrS\S	\\\\   4   4S
 jrS\S	\\S4   4S jrS\S	\\S4   4S jrS\S	\\\\\4   4   4S jrS\S	\\\R                  R<                     \\R                  R<                     4   4S jrS\S	\\\\R@                  \4   4   4S jr!S\S	\\\\R                  R<                     4   4S jr"S\S	\\\4   4S jr#S\S	\\\4   4S jr$S	\4S jr%S	\4S jr&S	\4S jr'S\S	\4S jr(S\S	\4S jr)g)    )AnyCallableUnionN)	_reverse2	_reverse3)Pattern   )BackendConfigBackendPatternConfigDTypeConfig)get_pattern_to_dtype_configsget_qat_module_classesget_fused_module_classes"get_pattern_to_input_type_to_index-get_root_module_to_quantized_reference_moduleget_fuser_method_mappingget_module_to_qat_module&get_fusion_pattern_to_root_node_getter)get_fusion_pattern_to_extra_inputs_getter!remove_boolean_dispatch_from_namepattern_to_human_readableentry_to_pretty_strbackend_configreturnc                 l    0 nU R                   R                  5        H  u  p#UR                  X'   M     U$ N)!_pattern_complex_format_to_configitemsdtype_configs)r   pattern_to_dtype_configspatternconfigs       ~/Users/tiagomarins/Projetos/claudeai/copy_bank/venv/lib/python3.13/site-packages/torch/ao/quantization/backend_config/utils.pyr   r      s=     BD)KKQQS,2,@,@ ) T##    .c                     U R                    Vs/ s H  nUR                  c  M  UR                  PM      nn[        [        U5      5      $ s  snf r   )configs
qat_moduletupleset)r   r"   qat_module_classess      r#   r   r   &   sS     %,,,F 	,  
 '())
   A
A
c                     U R                    Vs/ s H  nUR                  c  M  UR                  PM      nn[        [        U5      5      $ s  snf r   )r&   fused_moduler(   r)   )r   r"   fused_module_classess      r#   r   r   /   sS     %,,,F 	,  
 )*++r+   c                 l    0 nU R                   R                  5        H  u  p#UR                  X'   M     U$ r   )r   r   _input_type_to_index)r   pattern_to_input_type_to_indexr!   r"   s       r#   r   r   8   s=     EG")KKQQS282M2M&/ T))r$   c                     0 nU R                    H9  nUR                  c  M  UR                  c  M!  UR                  XR                  '   M;     U$ r   )r&   root_modulereference_quantized_module)r   mappingr"   s      r#   r   r   A   sN     CEG ((*11=*0*K*KG&&' ) Nr$   c                     0 nU R                   R                  5        H#  u  p#UR                  c  M  [        U5      nXAU'   M%     U$ r   )r   r   fuser_method1_get_fuser_method_in_reversed_nested_tuple_format)r   fuser_method_mappingr!   r"   r7   s        r#   r   r   N   sQ     KM)KKQQS* MVTL,8) T  r$   c                     0 nU R                   R                  5        H"  u  p#UR                  c  M  UR                  X'   M$     U$ r   )r   r   r'   )r   module_to_qat_moduler!   r"   s       r#   r   r   \   sK     BD)KKQQS(,2,=,= ) T  r$   c                     0 nU R                   R                  5        H"  u  p#UR                  c  M  UR                  X'   M$     U$ )a  Get a map from fusion pattern to a function that returns the root node
from the fusion pattern, e.g. the most common one is:
def get_root_node(node_pattern):
    while not isinstance(node_pattern[-1], Node):
        node_pattern = node_pattern[-1]
    return node_pattern[-1]
This can work for all patterns whose root node is the "last node" in the pattern,
e.g. (torch.add, MatchAllNode, (torch.ReLU, torch.Conv2d))
)r   r   _root_node_getter)r   root_node_getter_mappingr!   r"   s       r#   r   r   f   sI     9;)KKQQS##/060H0H$- T $#r$   c                     0 nU R                   R                  5        H"  u  p#UR                  c  M  UR                  X'   M$     U$ )a  Get a map from fusion pattern to a function that returns extra input nodes
from the fusion pattern, in the order required by the root node. This is optional,
if not specified, we will not copy over any extra inputs for the root node.
Example:
# Let's say we have the pattern (torch.add, MatchAllNode, (torch.nn.BatchNorm2d, torch.nn.Conv2d))
# and root node is torch.nn.Conv2d, and the node in MatchAllNode would be an extra
# argument to the fused module, we can unpack the pattern and return the node at
# MatchAllNode here
# we can implement extra_inputs_getter as follows:
def extra_inputs_getter(pattern) -> List[Any]:
    add, extra_input, conv_pattern = pattern
    return [extra_input]
)r   r   _extra_inputs_getter)r   extra_inputs_getter_mappingr!   r"   s       r#   r   r   y   sI      <>)KKQQS&&2393N3N'0 T '&r$   c                 ~   U [         R                  L a  gU [         R                  L a  gU [         R                  L a  gU [         R                  L a  gU [         R
                  L a  gU [         R                  L a  gU [         R                  L a  gU [         R                  L a  gS	[        U 5      ;  d   U  S
3S-   5       eU $ )z
Some ops have a default string representation such as
'<function boolean_dispatch.<locals>.fn at 0x7ff1106bf280>',
this function replaces them with the hardcoded function names.
z)torch.nn.functional.fractional_max_pool2dz)torch.nn.functional.fractional_max_pool3dztorch.nn.functional.max_pool1dztorch.nn.functional.max_pool2dztorch.nn.functional.max_pool3dz'torch.nn.functional.adaptive_max_pool1dz'torch.nn.functional.adaptive_max_pool2dz'torch.nn.functional.adaptive_max_pool3dboolean_dispatchz2 does not have a human readable representation in zquantization documentation)
Ffractional_max_pool2dfractional_max_pool3d
max_pool1d
max_pool2d
max_pool3dadaptive_max_pool1dadaptive_max_pool2dadaptive_max_pool3dstrps    r#   r   r      s     	A###:	
a%%	%:	
all	/	
all	/	
all	/	
a##	#8	
a##	#8	
a##	#8SV+ #?@
&	'+ Hr$   c                     [        U [        5      (       a  [        S U  5       5      $ [        U [        5      (       a  U $ [        U 5      n U $ )Nc              3   8   #    U  H  n[        U5      v   M     g 7fr   )r   ).0inner_ps     r#   	<genexpr>,pattern_to_human_readable.<locals>.<genexpr>   s     IqG.w77qs   )
isinstancer(   rM   r   rN   s    r#   r   r      sA    !UIqIII	As		-a0r$   c                    SnSU ;   a  [        U S   5      nUSU S3-  nSU ;   aE  US-  nU S    H2  nUS-  nUR                  5        H  u  pEUSU S	U S3-  nM     US
-  nM4     US-  nSU ;   a2  US-  nU S   R                  5        H  u  pEUSU SU S3-  nM     US-  n/ SQnU  H  nXv;   a  M
  USU S	X    S3-  nM     US-  nU$ )zc
Given a backend_config_dict entry, returns a string with the human readable
representation of it.
z{
r!   z  'pattern': z,
r   z  'dtype_configs': [
z    {
z      'z': z    },
z  ],
#num_tensor_args_to_observation_typez+  'num_tensor_args_to_observation_type': {
z    z: z  },
)r!   r   rX   z  '})r   r   )entryspattern_strdtype_configkvcustom_handled_fields
field_names           r#   r   r      sA   
 	A E/i0@A	}[M-- %	%%!/2LNA$**,wqcQCs++ -OA	 3
 	
X -5	;;?@FFHDA4s"QCs##A I	X
 
.	s:,c%"3!4C88 
 HAHr$   r"   c                    U R                   b  U R                   $ U R                  c  [        S5      e[        U R                  [        5      (       d  U R                  $ [        U R                  5      S:X  a  U R                  u  pX!4$ [        U R                  5      S:X  a  U R                  u  pnX2U44$ [        SU R                  5      e)a4  
Return the pattern specified in the given config in the reversed nested tuple format
used internally in the quantization pattern matching code.

If the pattern is not a tuple, or the pattern is already specified in the reversed
nested tuple format, return the pattern as is. Otherwise:

For 2-tuples (a, b), return (b, a).
For 3-tuples (a, b, c), return (c, (b, a)).

For example:
    * Given nn.Linear, return nn.Linear
    * Given (nn.Linear, nn.ReLU), return (nn.ReLU, nn.Linear)
    * Given (nn.Conv2d, nn.BatchNorm2d, nn.ReLU), return
      (nn.ReLU, (nn.BatchNorm2d, nn.Conv2d))

For context, the reason why this is needed is the user-facing BackendConfig
API accepts the flat 2-or-3-tuple format in forward order. While this simple
format handles the vast majority of use cases, it does not handle the more
complex ones, and so the internal pattern matching code for quantization uses
the following, more general reversed nested tuple format instead:

    operator = module_type | functional | torch op | native op | MatchAllNode
    Pattern = (operator, Pattern, Pattern, ...) | operator

In the future, we expect to replace the above complex format with the one used
by the subgraph rewriter in torch.fx, so we don't have to maintain our own
complex pattern matching code. Then we won't need this helper function anymore.
z>Either 'pattern' or 'pattern_complex_format' must be specified      ,Expected a tuple with 2 or 3 elements, got: )_pattern_complex_formatr!   
ValueErrorrV   r(   len)r"   abcs       r#   ,_get_pattern_in_reversed_nested_tuple_formatrl      s    @ %%1---~~L
 	
 fnne,,~~ 6>>av	V^^		!NN	qq6{GXXr$   c                    U R                   c   eU R                  b  U R                   $ [        U R                  [        5      (       d  [        SU R                  5      e[        U R                  5      S:X  a  [        U R                   5      $ [        U R                  5      S:X  a  [        U R                   5      $ [        SU R                  5      e)a  
Return the fuser method specified in the given config in the reversed nested
tuple format used internally in the quantization pattern matching code.

If pattern is specified in the reversed nested tuple format, we assume the
fuser method is also specified in this format and simply return it as is.
Otherwise, we convert the fuser method as follows:

    * Given f(is_qat, conv, relu), return f'(is_qat, relu, conv)
    * Given f(is_qat, conv, bn, relu), return f'(is_qat, relu, bn_conv),
      where bn_conv is a 2-tuple (bn, conv)

The first argument of a fuser method is always `is_qat` and is not affected
in the conversion. We currently only support functions with 3 or 4 arguments.
z%Expected pattern to be a tuple, got: rc   rd   re   )	r7   rf   rV   r!   r(   rg   rh   r   r   )r"   s    r#   r8   r8     s    $ ***%%1"""fnne,,@&..QQ 6>>a,,--	V^^		!,,--GXXr$   )*typingr   r   r   torchtorch.nnnntorch.nn.functional
functionalrD   +torch.ao.quantization.fuser_method_mappingsr   r   torch.ao.quantization.utilsr   r   r
   r   r   __all__dictlistr   r(   typer   r   rM   intr   Moduler   
Sequentialr   r   r   r   r   r   r   rl   r8    r$   r#   <module>r~      s   ' '     L / L L $!$	'4$
$%$*= *U49=M *,] ,uT3Y?O ,*!*	'4S>
!"*
!
	$uxx
ehhoo!6
67
 ! 	'501
12  ! 	'4(
() $!$	'8
$&'!'	'8
'.C :	C 	*# *Z1Y 1Y1YhY YYr$   