
    sg0                     l   d dl mZmZmZmZmZmZmZ d dlZd dl	m
Z
 d dlm
c mZ d dlmZmZ d dlmZ ddlmZmZmZ g dZded	eeee   f   fd
Zded	eedf   fdZded	eedf   fdZded	eeeeef   f   fdZded	eeej                  j>                     eej                  j>                     f   fdZ ded	eeee
jB                  ef   f   fdZ"ded	eeeej                  j>                     f   fdZ#ded	eeef   fdZ$ded	eeef   fdZ%d	efdZ&d	efdZ'd	efdZ(ded	efdZ)ded	efdZ*y)    )AnyCallableDictListTupleType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    i }| j                   j                         D ]  \  }}|j                  ||<    |S N)!_pattern_complex_format_to_configitemsdtype_configs)r   pattern_to_dtype_configspatternconfigs       ]/var/www/html/venv/lib/python3.12/site-packages/torch/ao/quantization/backend_config/utils.pyr   r      sG     BD)KKQQS A,2,@,@ )A##    .c                     g }| j                   D ]*  }|j                  |j                  |j                         , t        t	        |            S r    )configs
qat_moduleappendtupleset)r   qat_module_classesr&   s      r'   r   r   &   sP     (( 9(%%f&7&789 '())r(   c                     g }| j                   D ]*  }|j                  |j                  |j                         , t        t	        |            S r    )r*   fused_moduler,   r-   r.   )r   fused_module_classesr&   s      r'   r   r   .   sP     (( =* ''(;(;<= )*++r(   c                 l    i }| j                   j                         D ]  \  }}|j                  ||<    |S r    )r!   r"   _input_type_to_index)r   pattern_to_input_type_to_indexr%   r&   s       r'   r   r   6   sG     EG")KKQQS N282M2M&w/N))r(   c                     i }| j                   D ]5  }|j                  |j                  |j                  ||j                  <   7 |S r    )r*   root_modulereference_quantized_module)r   mappingr&   s      r'   r   r   ?   sW     CEG (( L*11=*0*K*KGF&&'L Nr(   c                     i }| j                   j                         D ]"  \  }}|j                  t        |      }|||<   $ |S r    )r!   r"   fuser_method1_get_fuser_method_in_reversed_nested_tuple_format)r   fuser_method_mappingr%   r&   r;   s        r'   r   r   L   sZ     KM)KKQQS 9* MVTL,8 )9  r(   c                     i }| j                   j                         D ]!  \  }}|j                  |j                  ||<   # |S r    )r!   r"   r+   )r   module_to_qat_moduler%   r&   s       r'   r   r   Z   sS     BD)KKQQS >(,2,=,= )>  r(   c                     i }| j                   j                         D ]!  \  }}|j                  |j                  ||<   # |S )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   d   sS     9;)KKQQS I##/060H0H$W-I $#r(   c                     i }| j                   j                         D ]!  \  }}|j                  |j                  ||<   # |S )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   w   sS      <>)KKQQS O&&2393N3N'0O '&r(   c                 j   | t         j                  u ry| t         j                  u ry| t         j                  u ry| t         j                  u ry| t         j
                  u ry| t         j                  u ry| t         j                  u ry| t         j                  u ryd	t        |       vsJ |  d
dz          | S )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                     t        | t              rt        d | D              S t        | t              r| S t        |       } | S )Nc              3   2   K   | ]  }t        |        y wr    )r   ).0inner_ps     r'   	<genexpr>z,pattern_to_human_readable.<locals>.<genexpr>   s     IG.w7Is   )
isinstancer-   rQ   r   rR   s    r'   r   r      s;    !UIqIII	As	-a0r(   c                 ~   d}d| v rt        | d         }|d| dz  }d| v rB|dz  }| d   D ]0  }|dz  }|j                         D ]  \  }}|d| d	| dz  } |d
z  }2 |dz  }d| v r1|dz  }| d   j                         D ]  \  }}|d| d| dz  } |dz  }g d}| D ]  }||v r|d| d	| |    dz  } |dz  }|S )zo
    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#   r[   z  '})r   r"   )entryspattern_strdtype_configkvcustom_handled_fields
field_names           r'   r   r      s]   
 	A E/i0@A	}[M-- %	%%!/2 	LNA$**, ,1wqcQCs++,OA		
 	
X -5	;;?@FFH 	$DAq4s"QCs##A	$	X
  9
..	s:,c%
"3!4C889
 HAHr(   r&   c                    | j                   | j                   S | j                  t        d      t        | j                  t              s| j                  S t        | j                        dk(  r| j                  \  }}||fS t        | j                        dk(  r| j                  \  }}}|||ffS t        d| j                        )a  
    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%   
ValueErrorrY   r-   len)r&   abcs       r'   ,_get_pattern_in_reversed_nested_tuple_formatro      s    @ %%1---~~L
 	
 fnne,~~ 6>>aA1v	V^^		!NN	AqAq6{GXXr(   c                    | j                   J | j                  | j                   S t        | j                  t              st        d| j                        t        | j                        dk(  rt        | j                         S t        | j                        dk(  rt        | j                         S t        d| j                        )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: rf   rg   rh   )	r;   ri   rY   r%   r-   rj   rk   r
   r   )r&   s    r'   r<   r<     s    $ ***%%1"""fnne,@&..QQ 6>>a,,--	V^^		!,,--GXXr(   )+typingr   r   r   r   r   r   r	   torchtorch.nnnntorch.nn.functional
functionalrH   +torch.ao.quantization.fuser_method_mappingsr
   r   torch.ao.quantization.utilsr   r   r   r   r   __all__r   typer   r   rQ   intr   Moduler   
Sequentialr   r   r   r   r   r   r   ro   r<    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(   