ó
    Eñi«—  ã                   ó 
  • % S SK r S SKrS SKrS SKrS SKJr  S SKJr  S SKJ	r	  S SK
Jr  S SKrS SKJr  S SKJrJr  S SKJr  S SKJrJr  S S	KJrJrJr  S S
KJrJrJr  S SKJ r   S SK!J"r"  S SK#J$r$J%r%  S SK&J'r'J(r(  S SK)J*r*J+r+  SSK,J-r-  SSK.J/r/  / SQr0\R                  Rb                  Rd                  \R                  Rb                  Rf                  \R                  Rb                  Rh                  1r5\	 " S S5      5       r6S\+S\S\74S jr8S\+S\S\74S jr9S\:\\:\;\;4   4   S\<\   4S jr=S r>S\S\4S jr?S \@S\4S! jrAS\+S\<\+   S-  4S" jrBS#\'S$\<\+   S\'4S% jrC\Rˆ                  S&\R                  RŠ                  S\4S' j5       rF S]S&\R                  RŠ                  S(\*S \@S)\S*\RŽ                  S-  S\+4S+ jjrHS\+S,\:\@\R                  RŠ                  4   S-\:\+\74   S\74S. jrIS\+S\<\J   4S/ jrKS0\<\J   S\\+/\<\J   4   4S1 jrL\" S2S35      rM\M" S4S55      \Rn                  \L" S/5      \N\L" S6/5      0\M" S4S75      \J\K0\M" S4S85      \J\K0\M" S4S95      \J\K0\M" S4S:5      \J\L" S/5      0\M" S4S;5      \J\K0\M" S4\Rž                  5      \J\K0\M" S4S<5      \J\L" S/5      0\M" S4S=5      \J\L" S/5      0\M" S4\R                   5      \J\L" S/5      0\M" S4S>5      \J\K00rQ\:\M\:\;\R¤                  -  \\+/\<\J   4   4   4   \SS?'   0 rT\:\;\R¤                  -  \\+/\<\J   4   4   \SS@'   S\+S\:\;\R¤                  -  \\+/\<\J   4   4   4SA jrU  S^S\+S,\:\@\RŠ                  4   SB\;\RŠ                     S-  SC\S\+S-  4
SD jjrVSE\*SF\W\SG4   SH\+S\+4SI jrXSJ\/SK\7S\W\<\@   \<\;\      4   4SL jrY  S^S\+SM\:\@\R                  RŠ                  4   SN\SO\S-  S\74
SP jjrZ  S^S\+SM\:\@\R                  RŠ                  4   SN\SO\S-  S\74
SQ jjr[S\+SM\:\@\R                  RŠ                  4   S\R                  RŠ                  S-  4SR jr\S\+SS\R                  RŠ                  SM\:\@\R                  RŠ                  4   S(\*S\+4
ST jr]S\+SS\R                  RŠ                  SM\:\@\R                  RŠ                  4   S(\*S\+4
SU jr^S\+SM\:\@\R                  RŠ                  4   S\+S-  4SV jr_S(\*4SW jr`SX\\-  S\4SY jra S_SN\SZ\S[\7S\74S\ jjrbg)`é    N)Ú
namedtuple)ÚCallable)Ú	dataclass)ÚAny)Ú
QConfigAnyÚ	QuantType)ÚDTypeWithConstraints)ÚFakeQuantizeBaseÚFixedQParamsFakeQuantize)Ú_is_activation_post_processÚFixedQParamsObserverÚObserverBase)Úfloat16_dynamic_qconfigÚfloat16_static_qconfigÚqconfig_equals)ÚQConfigMapping)ÚDeQuantStub)Ú_assert_and_get_unique_deviceÚ"activation_is_statically_quantized)ÚGraphModuleÚmap_arg)ÚGraphÚNodeé   )Úquantized_decomposed_lib)ÚPrepareCustomConfig)Úall_node_args_except_firstÚall_node_args_have_no_tensorsÚassert_and_get_unique_deviceÚcollect_producer_nodesÚcreate_getattr_from_valueÚ'create_node_from_old_node_preserve_metaÚEMPTY_ARG_DICTÚget_custom_module_class_keysÚget_linear_prepack_op_for_dtypeÚget_new_attr_name_with_prefixÚ(get_non_observable_arg_indexes_and_typesÚget_qconv_prepack_opÚ#get_skipped_module_name_and_classesÚ graph_module_from_producer_nodesÚmaybe_get_next_moduleÚNodeInfoÚnode_arg_is_biasÚnode_arg_is_weightÚNON_OBSERVABLE_ARG_DICTÚNON_QUANTIZABLE_WEIGHT_OPSÚreturn_arg_listÚObservedGraphModuleAttrsc                   óÌ   • \ rS rSr% \\\4   \S'   \\\\\	4   4   \S'   \
\S'   \\\4   \S'   \\S'   \\S'   \\   \S'   S	r\\S
'   Sr\\   S-  \S'   Sr\\   S-  \S'   Srg)r2   éL   Únode_name_to_qconfigÚnode_name_to_scopeÚprepare_custom_configÚ!equalization_node_name_to_qconfigÚqconfig_mappingÚis_qatÚobserved_node_namesFÚis_observed_standalone_moduleNÚ&standalone_module_input_quantized_idxsÚ'standalone_module_output_quantized_idxs© )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__ÚdictÚstrr   Ú__annotations__ÚtupleÚtyper   r   r   ÚboolÚsetr<   r=   ÚlistÚintr>   Ú__static_attributes__r?   ó    Ú[/home/mande/repo/quber/.venv/lib/python3.13/site-packages/torch/ao/quantization/fx/utils.pyr2   r2   L   s†   ‡ à˜s J˜Ñ/Ó/Ø˜S %¨¨T¨	Ñ"2Ð2Ñ3Ó3Ø.Ó.Ø'+¨C°¨H¡~Ó5Ø#Ó#ØƒLØ˜S™Ó!Ø*/Ð! 4Ó/Ø?CÐ*¨D°©I¸Ñ,<ÓCØ@DÐ+¨T°#©Y¸Ñ-=ÖDrN   r2   ÚnodeÚargÚreturnc                 óü   • SnSU R                   ;   a  U R                   S   R                  SS5      nUb,  U[        U R                  5      :  a  U R                  U   UL a  gU R                  R                  S5      UL $ )zReturns if node arg is weightNÚtarget_dtype_infoÚweight_indexTÚweight©ÚmetaÚgetÚlenÚargsÚkwargs)rP   rQ   rU   s      rO   r.   r.   Z   sq   € à€LØ˜dŸi™iÓ'Ø—y‘yÐ!4Ñ5×9Ñ9¸.È$ÓOˆàÑ Øœ3˜tŸy™y›>Ó)Ø�I‰I�lÑ# sÒ*àØ�;‰;�?‰?˜8Ó$¨Ð+Ð+rN   c                 óü   • SnSU R                   ;   a  U R                   S   R                  SS5      nUb,  U[        U R                  5      :  a  U R                  U   UL a  gU R                  R                  S5      UL $ )zReturns if node arg is biasNrT   Ú
bias_indexTÚbiasrW   )rP   rQ   r^   s      rO   r-   r-   h   sq   € à€JØ˜dŸi™iÓ'Ø—Y‘YÐ2Ñ3×7Ñ7¸ÀdÓKˆ
àÑØœ˜TŸY™Y›Ó'Ø�I‰I�jÑ! SÒ(àØ�;‰;�?‰?˜6Ó" cÐ)Ð)rN   Úcustom_module_mappingc                 óö   • [        5       n[        R                  [        R                  [        R                  4 H2  nU R                  U0 5      n[        UR                  5       5      nX-  nM4     [        U5      $ )aÊ  Get all the unique custom module keys in the custom config dict
e.g.
Input:
{
    QuantType.STATIC: {
        CustomModule1: ObservedCustomModule
    },
    QuantType.DYNAMIC: {
        CustomModule2: DynamicObservedCustomModule
    },
    QuantType.WEIGHT_ONLY: {
        CustomModule3: WeightOnlyObservedCustomModule
    },
}

Output:
# extract the keys across all inner STATIC, DYNAMIC, and WEIGHT_ONLY dicts
[CustomModule1, CustomModule2, CustomModule3]
)rJ   r   ÚSTATICÚDYNAMICÚWEIGHT_ONLYrY   ÚkeysrK   )r`   Úfloat_custom_module_classesÚ
quant_modeÚquant_mode_custom_module_configÚ quant_mode_custom_module_classess        rO   r$   r$   v   sp   € ô. -0«EÐÜ ×'Ñ'¬×):Ñ):¼I×<QÑ<QÓRˆ
Ø*?×*CÑ*CÀJÐPRÓ*SÐ'Ü+.Ð/N×/SÑ/SÓ/UÓ+VÐ(Ø#ÑGÒ#ñ Sô Ð+Ó,Ð,rN   c                 óú   • U [         R                  :X  a$  [         R                  R                  R                  $ U [         R
                  :X  a$  [         R                  R                  R                  $ [        SU 5      e)Nz&can't get linear prepack op for dtype:)ÚtorchÚfloat16ÚopsÚ	quantizedÚlinear_prepack_fp16Úqint8Úlinear_prepackÚ	Exception)Údtypes    rO   r%   r%   •   sT   € Ø”—‘ÓÜ�y‰y×"Ñ"×6Ñ6Ð6Ø	”%—+‘+Ó	Ü�y‰y×"Ñ"×1Ñ1Ð1äÐ@À%ÓHÐHrN   Úconv_opc                 ó–  • [         R                  R                  R                  [         R                  R
                  R                  [         R                  R                  R                  [         R                  R
                  R                  [         R                  R                  R                  [         R                  R
                  R                  [         R                  R                  R                  [         R                  R
                  R                  [         R                  R                  R                  [         R                  R
                  R                  [         R                  R                  R                  [         R                  R
                  R                   0nUR#                  U 5      nUc  [%        SU  35      eU$ )NzDidn't find prepack op for )rk   ÚnnÚ
functionalÚconv1drm   rn   Úconv1d_prepackÚconv2dÚconv2d_prepackÚconv3dÚconv3d_prepackÚconv_transpose1dÚconv_transpose1d_prepackÚconv_transpose2dÚconv_transpose2d_prepackÚconv_transpose3dÚconv_transpose3d_prepackrY   ÚAssertionError)rt   Úprepack_opsÚ
prepack_ops      rO   r(   r(   ž   s  € ä�‰×Ñ×"Ñ"¤E§I¡I×$7Ñ$7×$FÑ$FÜ�‰×Ñ×"Ñ"¤E§I¡I×$7Ñ$7×$FÑ$FÜ�‰×Ñ×"Ñ"¤E§I¡I×$7Ñ$7×$FÑ$FÜ�‰×Ñ×,Ñ,¬e¯i©i×.AÑ.A×.ZÑ.ZÜ�‰×Ñ×,Ñ,¬e¯i©i×.AÑ.A×.ZÑ.ZÜ�‰×Ñ×,Ñ,¬e¯i©i×.AÑ.A×.ZÑ.Zð€Kð —‘ Ó)€JØÑÜÐ:¸7¸)ÐDÓEÐEØÐrN   Úprefixc                 óp   ^ • T R                  SS5      m S[        R                  R                  4U 4S jjnU$ )NÚ.Ú_Úmodulec                 ó–   >• S[         4U4S jjnSnU" U5      n[        X5      (       a  US-  nU" U5      n[        X5      (       a  M  U$ )NÚic                 ó    >• T[        U 5      -   $ ©N)rE   )r�   r‡   s    €rO   Úget_attr_nameÚOget_new_attr_name_with_prefix.<locals>.get_new_attr_name.<locals>.get_attr_name¶   s   ø€ ØœC ›F‘?Ð"rN   r   r   )rL   Úhasattr)r‹   r�   r�   Ú	attr_namer‡   s       €rO   Úget_new_attr_nameÚ8get_new_attr_name_with_prefix.<locals>.get_new_attr_nameµ   sS   ø€ ð	#œS÷ 	#ð ˆÙ! !Ó$ˆ	Ü�f×(Ñ(Ø�‰FˆAÙ% aÓ(ˆIô �f×(Ó(ð ÐrN   )Úreplacerk   rv   ÚModule)r‡   r”   s   ` rO   r&   r&   ²   s/   ø€ Ø�^‰^˜C Ó%€Fð	¤%§(¡(§/¡/÷ 	ð ÐrN   c                 ó¶  • U /nU /nU(       aË  UR                  5       n [        U R                  5      [        U R                  R	                  5       5      -   nU Hs  n[        U[        5      (       d  M  UR                  S:X  a    gUR                  U5        UR                  S:X  a  UR                  [        L a  Mb  UR                  U5        Mu     U(       a  MË  U$ )añ  Starting from a target node, trace back until we hit input or
getattr node. This is used to extract the chain of operators
starting from getattr to the target node, for example::

    def forward(self, x):
        observed = self.observer(self.weight)
        return F.linear(x, observed)

collect_producer_nodes(observed) will either return a list of nodes that
produces the observed node or None if we can't extract a self contained
graph without free variables(inputs of the forward function).
ÚplaceholderNÚcall_function)ÚpoprK   r[   r\   ÚvaluesÚ
isinstancer   ÚopÚappendÚtargetÚgetattr)rP   ÚnodesÚfrontierÚall_argsrQ   s        rO   r    r    Ã   sª   € ð ˆF€EØˆv€HÞ
Ø�|‰|‹~ˆÜ˜Ÿ	™	“?¤T¨$¯+©+×*<Ñ*<Ó*>Ó%?Ñ?ˆÛˆCÜ˜c¤4×(Ñ(ÙØ�v‰v˜Ó&áØ�L‰L˜ÔØ—F‘F˜oÓ-°#·*±*ÄÔ2GØ—‘ Ö$ñ ÷ ˆ(ð €LrN   ÚrootÚproducer_nodesc                 ó  ^• [        U5      S:X  a  [        S5      eUR                  5         [        5       n0 mU4S jnU H  nUR	                  XC5      TU'   M     UR                  U" US   5      5        [        X5      nU$ )a  Construct a graph module from extracted producer nodes
from `collect_producer_nodes` function
Args:
  root: the root module for the original graph
  producer_nodes: a list of nodes we use to construct the graph
Return:
  A graph module constructed from the producer nodes
r   z'list of producer nodes can not be emptyc                 ó$   >• [        U U4S j5      $ )Nc                 ó   >• TU    $ r�   r?   )rP   Úenvs    €rO   Ú<lambda>ÚDgraph_module_from_producer_nodes.<locals>.load_arg.<locals>.<lambda>ô   s	   ø€  s¨4¢yrN   )r   )Úarª   s    €rO   Úload_argÚ2graph_module_from_producer_nodes.<locals>.load_argó   s   ø€ Ü�qÔ0Ó1Ð1rN   éÿÿÿÿ)rZ   r„   Úreverser   Ú	node_copyÚoutputr   )r¥   r¦   Úgraphr®   Úproducer_nodeÚgraph_modulerª   s         @rO   r*   r*   á   s€   ø€ ô ˆ>Ó˜aÓÜÐFÓGÐGà×ÑÔÜ‹G€EØ€Cõ2ó (ˆØ"Ÿ_™_¨]ÓEˆˆMÓñ (à	‡L�L‘˜.¨Ñ,Ó-Ô.Ü˜tÓ+€LØÐrN   r‹   c                 ó   • [        U 5      $ )zz
Returns the unique device for a module, or None if no device is found.
Throws an error if multiple devices are detected.
)r   )r‹   s    rO   r   r   þ   s   € ô )¨Ó0Ð0rN   r´   ÚvalueÚdevicec                 ó0  • [        U5      nU" U 5      nUc  [        U 5      n[        U[        R                  5      (       a  UR                  5       R                  5       O[        R                  " X4S9nU R                  Xg5        UR                  SU5      nU$ )z�
Given a value of any type, creates a getattr node corresponding to the value and
registers the value as a buffer to the module.
)r¹   Úget_attr)
r&   r   r�   rk   ÚTensorÚdetachÚcloneÚtensorÚregister_bufferÚcreate_node)	r‹   r´   r‡   r¸   r¹   r”   r“   Ú	new_valueÚ	attr_nodes	            rO   r!   r!     sˆ   € ô 6°fÓ=ÐÙ! &Ó)€IØ�~Ü-¨fÓ5ˆô �eœUŸ\™\×*Ñ*ð 	�‰‹×ÑÔä�\Š\˜%Ñ/ð ð
 ×Ñ˜9Ô0à×!Ñ! *¨iÓ8€IØÐrN   ÚmodulesÚcachec                 óÞ  • U(       a	  X;   a  X    $ Sn[        U [        5      (       d  SnGO6U R                  S:X  a  SnGO"U R                  S:X  aa  [        U R                  [        5      (       d  [        S5      e[        XR                     5      (       a  [        U R                  S   X5      nGO±U R                  S:X  a  SnGO�U R                  S:X  a8  U R                  [        R                  L a  [        U R                  S   X5      nGOUU R                  S:X  a  SnGOAU R                  [        L a  U R                  S	   S
;   a  SnGOU R                  S:X  a  U R                  S:X  a  SnOôSnU R                   Hâ  n[        U[        5      (       a\  U HU  n[        U[        5      (       d  M  [        XaU5      nU=(       d    U(       + nU(       d  M?  U(       + nU(       a  X2U '   Us  s  $    Og[        U[        5      (       a  OQ[        U[        5      (       a:  [        XQU5      nU=(       d    U(       + nU(       a  U(       + nU(       a  X2U '   Us  $ OSnU(       + nMä     U(       a  X2U '   U$ )z¾
If we know for sure that all of this node's args have no
tensors (are primitives), return True.  If we either
find a tensor or are not sure, return False. Note: this
function is not exact.
FTr™   Úcall_modulez2node.target must be a string for call_module nodesr   rš   r»   r   )ÚndimÚshapeÚcall_methodÚsize)r�   r   rž   r    rE   r„   r   r   r[   ÚoperatorÚgetitemr¡   rK   rL   )	rP   rÄ   rÅ   ÚresultÚfound_one_tensorrQ   Úlist_elÚ!this_list_el_args_have_no_tensorsÚthis_arg_args_have_no_tensorss	            rO   r   r   !  s  € ö �“Ø‰{Ðà€FÜ�dœD×!Ñ!ØŠØ	�‰�MÓ	!ØŠØ	�‰�MÓ	!Ü˜$Ÿ+™+¤s×+Ñ+Ü Ð!UÓVÐVÜ& w¯{©{Ñ';×<Ñ<Ü2°4·9±9¸Q±<ÀÓPˆFùØ	�‰�MÓ	!ØŠØ	�‰�OÓ	#¨¯©´x×7GÑ7GÒ(GÜ.¨t¯y©y¸©|¸WÓLŠØ	�‰�JÓ	ØŠØ	�‰œÒ	 D§I¡I¨a¡LÐ4EÓ$EàŠØ	�‰�MÓ	! d§k¡k°VÓ&;à‰à ÐØ—9”9ˆCÜ˜#œt×$Ñ$Û"�GÜ! '¬4×0Ó0ä9¸'ÈEÓRð :ð ,<÷ ,Ø AÔAð )÷ ,Ð+Ø)9Ô%9˜FÞ$Ø.4 d¡Ø#)œMò#  #ô$ ˜C¤×%Ñ%Øä˜c¤4×(Ñ(Ü4QØ eó5Ð1ð (8÷ (Ø9Ô9ð %ö (Ø%5Ô!5˜Þ Ø*0 $™KØ%šð	 (ð (,Ð$Ø)Ô)ŠFñU öV Øˆd‰Ø€MrN   c                 óR   • [        [        S[        U R                  5      5      5      $ )z*
Returns all node arg indices after first
r   )rK   ÚrangerZ   r[   )rP   s    rO   r   r   u  s   € ô ”�aœ˜TŸY™Y›Ó(Ó)Ð)rN   Úarg_indicesc                 ó>   ^ • S[         S[        [           4U 4S jjnU$ )zi
Constructs a function that takes a node as arg and returns the arg_indices
that are valid for node.args
rP   rR   c                 óh   >• T Vs/ s H  o[        U R                  5      :  d  M  UPM!     sn$ s  snf r�   )rZ   r[   )rP   r�   rÕ   s     €rO   Úarg_indices_funcÚ)return_arg_list.<locals>.arg_indices_func‚  s(   ø€ Ù&Ó=š;�a¬c°$·)±)«nÑ*<—™;Ñ=Ð=ùÒ=s   †/¦/)r   rK   rL   )rÕ   rØ   s   ` rO   r1   r1   |  s"   ø€ ð>œtð >¬¬S©	÷ >ð ÐrN   r,   z	op targetrÊ   Úmasked_fillé   ÚpermuteÚrepeatÚreshaperË   Ú	transposeÚ	unsqueezeÚ
unsqueeze_Úviewr/   r#   c                 óv   • [        U R                  U R                  5      n[        R	                  U[
        5      $ )zœ
Returns a dict with of non float tensor types as keys and values which correspond to a
function to retrieve the list (which takes the node as an argument)
)r,   rž   r    r/   rY   r#   )rP   Úinfos     rO   r'   r'   ¤  s+   € ô �D—G‘G˜TŸ[™[Ó)€Dä"×&Ñ& t¬^Ó<Ð<rN   Útarget_module_typeÚtarget_functional_typec                 óü   • U R                    Hl  nUR                  S:X  a.  Ub+  [        U[        UR                  5         U5      (       a  Us  $ UR                  S:X  d  MS  Uc  MX  UR                  U:X  d  Mj  Us  $    g)a  Gets the next module that matches what is needed in
is_target_module_type if it exists

Args:
    node: The node whose users we want to look at
    target_module_type: Module type that we want to check
    target_functional_type: Functional type that we want to check
rÇ   Nrš   )Úusersrž   r�   rE   r    )rP   rÄ   rå   ræ   Úusers        rO   r+   r+   °  sn   € ð —
”
ˆà�G‰G�}Ó$Ø"Ñ.Ü˜7¤3 t§{¡{Ó#3Ñ4Ð6H×IÑIàŠKà�G‰G�Õ&Ø&Ó2Ø—‘Ð5Õ5àŠKñ ð rN   Úquantized_graphÚcreate_node_args.Úold_nodec                 óF   • U R                   " U6 nUR                  Ul        U$ )zM
Creates `new_node` and copies the necessary metadata to it from `old_node`.
)rÁ   Ústack_trace)rê   rë   rì   Únew_nodes       rO   r"   r"   Ð  s(   € ð ×*Ò*Ð,<Ð=€HØ#×/Ñ/€HÔØ€OrN   r7   Úis_standalone_modulec                 ó^  • [         R                   " U R                  5      n[         R                   " U R                  5      nU(       dd  U[        U R                  R                  5       5      -  nU[        U R                  R                  5       5      -  nU[        U R                  5      -  nX#4$ r�   )	ÚcopyÚnon_traceable_module_namesÚnon_traceable_module_classesrK   Ústandalone_module_namesre   Ústandalone_module_classesr$   Úfloat_to_observed_mapping)r7   rð   Úskipped_module_namesÚskipped_module_classess       rO   r)   r)   Ý  sª   € ô  Ÿ9š9Ð%:×%UÑ%UÓVÐÜ!ŸYšYØ×:Ñ:óÐö  à¤Ø!×9Ñ9×>Ñ>Ó@ó!
ñ 	
Ðð 	¤$Ø!×;Ñ;×@Ñ@ÓBó#
ñ 	
Ðð 	Ô">Ø!×;Ñ;ó#
ñ 	
Ðð  Ð7Ð7rN   Únamed_modulesÚqconfigÚqhandlerc                 óÒ  • [        X5      nUb¢  UbŸ  [        U[        R                  R                  R
                  R                  R                  5      (       d  [        S5      e[        U[        R                  R                  5      =(       a"    [        U5      =(       a    UR                  5       $ [        U[        R                  R                  R                  R                  5      $ )z<
Return whether this refers to the custom module LSTM flow.
ú0qhandler must be a QuantizeHandler when provided)Ú_get_moduler�   rk   ÚaoÚquantizationÚfxÚquantize_handlerÚQuantizeHandlerr„   rv   ÚLSTMr   Úis_custom_moduleÚquantizable©rP   rú   rû   rü   Úmods        rO   Ú_is_custom_module_lstmr
  ó  s­   € ô �dÓ
*€CØÑ˜xÑ3ÜØ”e—h‘h×+Ñ+×.Ñ.×?Ñ?×OÑO÷
ñ 
ô !Ð!SÓTÐTä�sœEŸH™HŸM™MÓ*÷ ,Ü2°7Ó;÷,à×)Ñ)Ó+ð	
ô ˜#œuŸx™xŸ{™{×6Ñ6×;Ñ;Ó<Ð<rN   c                 óÒ  • [        X5      nUb¢  UbŸ  [        U[        R                  R                  R
                  R                  R                  5      (       d  [        S5      e[        U[        R                  R                  5      =(       a"    [        U5      =(       a    UR                  5       $ [        U[        R                  R                  R                  R                  5      $ )zJ
Return whether this refers to the custom module MultiheadAttention flow.
rþ   )rÿ   r�   rk   r   r  r  r  r  r„   rv   ÚMultiheadAttentionr   r  r  r  s        rO   Ú_is_custom_module_mhar    s¯   € ô �dÓ
*€CØÑ˜xÑ3ÜØ”e—h‘h×+Ñ+×.Ñ.×?Ñ?×OÑO÷
ñ 
ô !Ð!SÓTÐTä�sœEŸH™H×7Ñ7Ó8÷ ,Ü2°7Ó;÷,à×)Ñ)Ó+ð	
ô ˜#œuŸx™xŸ{™{×6Ñ6×IÑIÓJÐJrN   c                 ó†   • U R                   S:X  a1  [        U R                  5      U;   a  U[        U R                  5         $ g)zG
If `node` refers to a call_module node, return the module, else None.
rÇ   N)rž   rE   r    )rP   rú   s     rO   rÿ   rÿ   %  s7   € ð ‡w�w�-Ó¤C¨¯©Ó$4¸Ó$EØœS §¡Ó-Ñ.Ð.àrN   Úmodelc                 óÜ   • Sn[        U5      nU" U5      n[        5       n[        XU5        XrU'   UR                  U 5         UR	                  X`45      sSSS5        $ ! , (       d  f       g= f)z•
Attach a `DeQuantStub` to the model and create a node that calls this
`DeQuantStub` on the output of `node`, similar to how observers are inserted.
Údequant_stub_N)r&   r   ÚsetattrÚinserting_afterrÇ   )rP   r  rú   r´   r‡   Úget_new_dequant_stub_nameÚdequant_stub_nameÚdequant_stubs           rO   Ú_insert_dequant_stubr  1  sd   € ð €FÜ =¸fÓ EÐÙ1°%Ó8ÐÜ“=€LÜˆE lÔ3Ø'3Ð#Ñ$Ø	×	Ñ	˜tÕ	$Ø× Ñ Ð!2°GÓ<÷ 
%×	$×	$ús   ÁAÁ
A+c                 óv  • UR                  U 5         UR                  [        R                  U S45      n[	        XAX#5      nSSS5        UR                  W5         UR                  [        R                  U S45      nSSS5        UR                  W5         UR                  [        R                  US45      n[	        XqX#5      nSSS5        UR                  W5         UR                  [        R                  US45      n	[	        X‘X#5      n
SSS5        UR                  W
5         UR                  [
        XŠ/45      nSSS5        UR                  W5         UR                  [
        X[/45      nSSS5        [        U R                  R                  5       5       H$  nUW:w  d  M  XÖ:w  d  M  UR                  U W5        M&     [        U5        W$ ! , (       d  f       GN—= f! , (       d  f       GNm= f! , (       d  f       GN7= f! , (       d  f       GN= f! , (       d  f       Nà= f! , (       d  f       N¿= f)al  
Insert DeQuantStubs after each internal output node of custom module LSTM.

Custom module LSTM outputs are nested tuples of the structure (output, (hidden0, hidden1)),
Since we cannot dequantize a tuple as a whole, we must first break down the tuple into its
components through `getitem`. This function transforms the graph as follows:

  (1) Split the LSTM node into (output, (hidden0, hidden1))
  (2) Insert a DeQuantStub after each internal node
  (3) Recombine the DeQuantStubs into the same structure as before
  (4) Reroute all consumers of the original LSTM node and its sub-nodes
      (e.g. lstm[0])

Before:
               lstm_output
                    |
                    v
              original_user(s)
After:
               lstm_output
              /           \
             /  (getitem)  \
            /               \
           v                 v
         output            hidden
           |               /   \
     (DeQuantStub)        (getitem)
           |             /       \
           v            v         v
       output_dq     hidden0    hidden1
           |            |         |
           |    (DeQuantStub) (DeQuantStub)
           |            |         |
           |            v         v
           |      hidden0_dq  hidden1_dq
           |            \       /
           |              (tuple)
           |              \   /
           |               v  v
           |             hidden_dq
           \               /
            \   (tuple)   /
             v            v
             lstm_output_dq
                   |
                   v
            original_user(s)

For step (4), reroute all users of the original LSTM node(s) as follows:
  lstm_output -> lstm_output_dq
  lstm_output[0] -> output_dq
  lstm_output[1] -> hidden_dq
  lstm_output[1][0] -> hidden0_dq
  lstm_output[1][1] -> hidden1_dq

Return the node `lstm_output_dq`.
r   Nr   )r  rš   rÌ   rÍ   r  rG   rK   rè   re   Úreplace_input_withÚ_reroute_tuple_getitem_pattern)rP   r  rú   r´   r³   Ú	output_dqÚhiddenÚhidden0Ú
hidden0_dqÚhidden1Ú
hidden1_dqÚ	hidden_dqÚlstm_output_dqré   s                 rO   Ú3_insert_dequant_stubs_for_custom_module_lstm_outputr#  E  sº  € ðB 
×	Ñ	˜tÕ	$Ø×$Ñ$¤X×%5Ñ%5¸¸a°yÓAˆÜ(¨¸ÓMˆ	÷ 
%ð 
×	Ñ	˜yÕ	)Ø×$Ñ$¤X×%5Ñ%5¸¸a°yÓAˆ÷ 
*à	×	Ñ	˜vÕ	&Ø×%Ñ%¤h×&6Ñ&6¸À¸ÓDˆÜ)¨'¸-ÓOˆ
÷ 
'ð 
×	Ñ	˜zÕ	*Ø×%Ñ%¤h×&6Ñ&6¸À¸ÓDˆÜ)¨'¸-ÓOˆ
÷ 
+ð
 
×	Ñ	˜zÕ	*Ø×'Ñ'¬°Ð0HÐ/JÓKˆ	÷ 
+à	×	Ñ	˜yÕ	)Ø×,Ñ,¬U°iÐ5KÐ4MÓNˆ÷ 
*ô �T—Z‘Z—_‘_Ó&Ö'ˆØ�6�>˜d�nØ×#Ñ# D¨.Ö9ñ (ô # 5Ô)ØÐ÷7 
%Ö	$ú÷ 
*Ö	)úç	&Ö	&ú÷ 
+Ö	*ú÷
 
+Õ	*úç	)Õ	)úsG   ’/GÁ#G#Â/G5Ã/HÄ&HÅH*Ç
G Ç#
G2Ç5
HÈ
HÈ
H'È*
H8c                 ó¼   ^ ^^	• U4S jnU4S jnS nS m	S[         [           S[        S-  4U U	4S jjnX$U/T	X$XC/X$XC/T	X$U//nU H  nU" U5      nUc  M  Us  $    g)	aÿ  
Given an argument of a node, if the argument refers to the path through which the node
is a consumer of custom module LSTM, return the custom module LSTM node, or None otherwise.

This is used to determine whether a node is a consumer of custom module LSTM, and, if so,
skip inserting input observers for this node. This is because custom module LSTM produces
quantized outputs, so inserting an input observer for the consumer of custom module LSTM
would unnecessarily quantize the outputs again.

  lstm -> consumer

In practice, however, custom module LSTM outputs a tuple (output, (hidden0, hidden1)) with
DeQuantStubs attached to each internal node (see `_insert_dequant_stubs_for_custom_module_lstm_output`).
This tuple can be consumed in one of four ways:

  lstm -> getitem -> DeQuantStub -> consumer                       # consume lstm[0]
  lstm -> getitem -> getitem -> DeQuantStub -> tuple -> consumer   # consume lstm[1]
  lstm -> getitem -> getitem -> DeQuantStub -> consumer            # consume lstm[1][0] or lstm[1][1]
  lstm -> getitem -> DeQuantStub -> tuple -> consumer              # consume lstm

Thus, we must match against the above patterns instead of simply checking the parent node
to determine whether this node is a consumer of a custom module LSTM.
c                 ó8   >• [        [        U T5      [        5      $ r�   )r�   rÿ   r   ©r­   rú   s    €rO   Úmatch_dqÚ=_maybe_get_custom_module_lstm_from_node_arg.<locals>.match_dqÀ  s   ø€ Üœ+ a¨Ó7¼ÓEÐErN   c                 ó   >• [        U T5      $ r�   )r
  r&  s    €rO   Ú
match_lstmÚ?_maybe_get_custom_module_lstm_from_node_arg.<locals>.match_lstmÃ  s   ø€ Ü% a¨Ó7Ð7rN   c                 óf   • U R                   S:H  =(       a    U R                  [        R                  L $ ©Nrš   )rž   r    rÌ   rÍ   ©r­   s    rO   Úmatch_getitemÚB_maybe_get_custom_module_lstm_from_node_arg.<locals>.match_getitemÆ  s%   € Ø�t‰t�Ñ&×G¨1¯8©8´x×7GÑ7GÐ+GÐGrN   c                 óR   • U R                   S:H  =(       a    U R                  [        L $ r-  )rž   r    rG   r.  s    rO   Úmatch_tupleÚ@_maybe_get_custom_module_lstm_from_node_arg.<locals>.match_tupleÉ  s   € Ø�t‰t�Ñ&×<¨1¯8©8´uÐ+<Ð<rN   Úmatch_patternrR   Nc                 óÊ   >• Tn[        U 5       HP  u  p#U" U5      (       d    gU[        U 5      S-
  :  d  M(  UTL a  UR                  S   S   nMA  UR                  S   nMR     U$ )z|
Traverse up the graph and match the args one by one.
If there is a match, return the last matched node, or None otherwise.
Nr   r   )Ú	enumeraterZ   r[   )r4  r­   r�   ÚmatchrQ   r2  s       €€rO   Ú_match_patternÚC_maybe_get_custom_module_lstm_from_node_arg.<locals>._match_patternÌ  sf   ø€ ð
 ˆä! -Ö0‰HˆAÙ˜—8‘8Ùà”3�}Ó%¨Ñ)Õ)Ø˜KÒ'ØŸ™˜q™	 !™’AàŸ™˜q™	’Añ 1ð ˆrN   )rK   r   r   )
rQ   rú   r'  r*  r/  r8  Úall_match_patternsÚpÚmatched_noder2  s
   ``       @rO   Ú+_maybe_get_custom_module_lstm_from_node_argr=  ¤  sŽ   ú€ õ8Fõ8òHò=ð¤d¬8¡nð ¼À¹÷ ð ð( 
 *Ð-Ø	�h¨}ÐIØ	 -Ð<Ø	�h¨zÐ:ð	Ðó  ˆÙ% aÓ(ˆØÓ#ØÒñ  ð rN   c                 óÂ  ^
• S[         S[        [           S[        [            S[        [        [               S[        [        [         [        [        S4   4      4
U
4S jjm
/ n[        5       nU R
                   H  nT
" U/ / X5        M     U HÏ  nUS   nUS	   nUR                  S
:X  a  UR                  [        L d  [        S5      eUR                  S
:X  a  UR                  [        R                  L d  [        S5      eUR                  S   nUR                  S   U   n[        UR                  R                  5       5       H  n	U	R                  Xh5        M     MÑ     g)aË  
Search for patterns where N consecutive `tuple` call_function nodes are followed by
N consecutive `getitem` call_function nodes that are "reverses" of the `tuple` nodes.
If we find this pattern, reroute the consumers of the last `getitem` to skip these
N `tuple` and `getitem` nodes.

Before:

    a   b     c
    |   \   /
    \   tuple
     \   /
      tuple
        |
    getitem(1)
        |
    getitem(0)
        |
        d

After:

    b
    |
    d
rP   Úindex_stackÚcurrent_patternÚmatched_patternsÚseen.c           	      ó  >• [        U5      S:X  aD  [        U5      S:”  a5  UR                  [        R                  " U5      5        UR                  5         U [	        U5      4nXT;   a  gUR                  U5        U R                   GH  nUR                  S:X  ai  UR                  [        L aV  [        UR                  S   5       H8  u  pxX€:X  d  M  UR                  U5        UR                  U5        T	" XaX#U5        M:     M}  UR                  S:X  d  M�  UR                  [        R                  L d  M®  [        U5      S:”  d  M¿  UR                  S   US   :X  d  M×  UR                  5         UR                  U5        T	" XaX#U5        GM     U$ )a  
Traverse the graph recursively to match for the N-tuple - N-getitem patterns,
starting at the given node.

We use a stack to keep track of the expected `getitem` indices, since these are
reversed from the `tuple` indices. In the above example, the stack after
(b -> tuple -> tuple) will be [0, 1], which will be popped by getitem(1) first
and then by getitem(0).

TODO: traverse upwards from the output and handle the case when tuple is not a
separate node, e.g. graph.call_function(operator.getitem, args=(a, (b, c)))
r   Nrš   r   r°   )rZ   rŸ   rò   ÚclearrG   Úaddrè   rž   r    r6  r[   rÌ   rÍ   r›   )
rP   r?  r@  rA  rB  Ústateré   r�   Úuser_argÚfind_patternss
            €rO   rH  Ú5_reroute_tuple_getitem_pattern.<locals>.find_patterns	  sG  ø€ ô& ˆ{Ó˜qÓ ¤S¨Ó%9¸AÓ%=Ø×#Ñ#¤D§I¢I¨oÓ$>Ô?Ø×!Ñ!Ô#ð ”u˜[Ó)Ð*ˆØ‹=ØØ�‰�Œð —J•JˆDØ�w‰w˜/Ó)¨d¯k©k¼UÒ.BÜ#,¨T¯Y©Y°q©\Ö#:‘K�AØÕ'Ø#×*Ñ*¨1Ô-Ø'×.Ñ.¨tÔ4Ù%Ø ¨ÐRVöó	 $;ð —‘˜OÕ+°·±¼x×?OÑ?OÔ0OÜ�{Ó# aÕ'Ø—y‘y ‘| {°2¡Õ6Ø#Ÿ™Ô)Ø'×.Ñ.¨tÔ4Ù%Ø ¨ÐRV÷ñ ð"  ÐrN   r   r°   rš   z:first tuple node must be a call_function with target tuplezFlast getitem node must be a call_function with target operator.getitemr   N)r   rK   rL   rJ   rG   r¢   rž   r    r„   rÌ   rÍ   r[   rè   re   r  )r´   rA  rB  rP   ÚpatternÚfirst_tupleÚlast_getitemÚlast_getitem_indexÚ	new_inputré   rH  s             @rO   r  r  í  sY  ø€ ð8/ Üð/ äœ#‘Yð/ ô œd™ð/ ô œt¤D™zÑ*ð	/ ô
 ”%œœe¤C¨ H™oÐ-Ñ.Ñ/÷/ ðd *,ÐÜ.1«e€DØ—”ˆÙ�d˜B Ð$4Ö;ñ ó
 $ˆØ˜a‘jˆØ˜r‘{ˆØ—‘ /Ó1°k×6HÑ6HÌEÒ6QÜ ØLóð ð �O‰O˜Ó.Ø×#Ñ#¤x×'7Ñ'7Ò7ä ØXóð ð *×.Ñ.¨qÑ1ÐØ×$Ñ$ QÑ'Ð(:Ñ;ˆ	Ü˜×+Ñ+×0Ñ0Ó2Ö3ˆDØ×#Ñ# LÖ<ó 4ò! $rN   Úactivation_post_processc                 óˆ   • [        U [        5      (       a  U $ [        U [        5      (       d  [        S5      eU R                  $ )z’
If `activation_post_process` is an observer, return the observer.
If `activation_post_process` is a fake quantize, return the internal observer.
zCactivation_post_process must be an ObserverBase or FakeQuantizeBase)r�   r   r
   r„   rO  )rO  s    rO   Ú*_get_observer_from_activation_post_processrQ  V  sE   € ô Ð)¬<×8Ñ8Ø&Ð&äÐ1Ô3C×DÑDÜ ØUóð ð '×>Ñ>Ð>rN   Údtype_with_constraintsÚis_activationc                 ób  ^ • S[         [        -  S[        S[        S[        4U 4S jjnT b  UR
                  c  gU(       a  T R                  OT R                  nU(       a  SOSnSnUbF  U" 5       n[        U5      (       d  [        S	5      eUR
                  UR
                  :w  a  gU" XqU5      nU$ )
a„  
Return whether `qconfig` satisfies the following constraints from the backend,
specified through the activation and weight DTypeWithConstraints.

    1. QConfig specified a quantization range that falls within the backend's, if any
    2. QConfig specified a min scale value that is >= the backend's, if any
    3. QConfig specified a FixedQParamsObserver or FixedQParamsFakeQuantize that has
       scale and zero point that match the backend's, if any

If `is_activation` is True, we check `qconfig.activation`, else we check `qconfig.weight`.
If `qconfig` or `dtype_with_constraints.dtype` is None, or the dtypes do not match, return True.
rO  rR  Údebug_stringrR   c                 óÈ  >• [        U 5      n[        USS 5      n[        USS 5      n[        USS 5      nUR                  nUR                  nUR                  n	UR
                  n
UR                  nUbW  UbT  Ub  Uc  [        R                  " SU ST 3SS9  gXG:  d  XX:”  a(  [        R                  " SU S	U S
U SU S
U ST 3SS9  gU	bF  Uc  [        R                  " SU ST 3SS9  gXi:  a"  [        R                  " SU SU SU	 ST 3SS9  gU
bÍ  UbÊ  [        [        4 H  n[        TU5      (       d  M    g   Sn[        U [        5      (       d1  [        U [        5      (       d  [        R                  " ST SU 3SS9  gUR                  U
:w  d  UR                   U:w  a<  [        R                  " SUR                   SUR                    SU
 SU ST SU 3SS9  gg)NÚ	quant_minÚ	quant_maxÚepszQConfig z4 must specify 'quant_min' and 'quant_max', ignoring rÛ   )Ú
stacklevelFzE quantization range must fall within the backend's:
QConfig range = (z, z), BackendConfig range = (z), ignoring z must specify 'eps', ignoring z eps (zB) must be greater than or equal to the backend's min scale value (TzúPlease use torch.ao.quantization.get_default_qconfig_mapping or torch.ao.quantization.get_default_qat_qconfig_mapping. Example:
    qconfig_mapping = get_default_qconfig_mapping("fbgemm")
    model = prepare_fx(model, qconfig_mapping, example_inputs)zjQConfig must specify a FixedQParamsObserver or a FixedQParamsFakeQuantize for fixed qparams ops, ignoring z.
zQConfig fixed scale (z) and zero point (z) do not match the backend's (z and )rQ  r¡   Úquant_min_lower_boundÚquant_max_upper_boundÚscale_min_lower_boundÚscale_exact_matchÚzero_point_exact_matchÚwarningsÚwarnr   r   r   r�   r   r   ÚscaleÚ
zero_point)rO  rR  rU  ÚobserverÚapp_quant_minÚapp_quant_maxÚapp_scale_minÚbackend_quant_minÚbackend_quant_maxÚbackend_scale_minÚbackend_scale_exact_matchÚbackend_zero_point_exact_matchÚaccepted_qconfigÚsuggestion_strrû   s                 €rO   Ú;_activation_post_process_satisfies_dtype_config_constraintsÚp_qconfig_satisfies_dtype_config_constraints.<locals>._activation_post_process_satisfies_dtype_config_constraintsz  s‹  ø€ ô
 >Ð>UÓVˆÜ ¨+°tÓ<ˆÜ ¨+°tÓ<ˆô   ¨%°Ó6ˆØ2×HÑHÐØ2×HÑHÐØ2×HÑHÐØ$:×$LÑ$LÐ!Ø)?×)VÑ)VÐ&àÑ(Ð->Ñ-JØÑ$¨Ñ(=Ü—’Ø˜|˜nÐ,`ÐahÐ`iÐjØ òð ØÓ2°mÓ6WÜ—’Ø˜|˜nð -(Ø(5 °b¸¸ð H.Ø.?Ð-@ÀÐCTÐBUð V Ø '˜yð*ð  !òð àÑ(ØÑ$Ü—’Ø˜|˜nÐ,JÈ7È)ÐTØ òð ØÓ0Ü—’Ø˜|˜n¨F°=°/ð B6Ø6GÐ5HÈÐU\ÐT]ð_à òð
 ð &Ñ1Ø.Ñ:ô &<Ô=TÓ$UÐ Ü! 'Ð+;×<Ó<Ùñ %VðQð ô Ø'Ô)=÷ñ ä Ð!8Ô:R×SÑSÜ—’ð7Ø7>°i¸sÀ>ÐBRðTà òð
 à—‘Ð";Ó;Ø×&Ñ&Ð*HÓHä—’Ø+¨H¯N©NÐ+;Ð;MÈh×NaÑNaÐMbð c3Ø3LÐ2MÈUÐSqÐRrð s Ø '˜y¨¨NÐ+;ð=ð  !ò	ð ØrN   TÚ
activationrV   z:activation_post_process must be an activation post process)
r   r
   r	   rE   rI   rs   rq  rV   r   r„   )rû   rR  rS  ro  Úactivation_post_process_ctrrU  Úsatisfies_constraintsrO  s   `       rO   Ú+_qconfig_satisfies_dtype_config_constraintsrt  g  sÖ   ø€ ð&TÜ!-Ô0@Ñ!@ðTä 4ðTô ðTô 
÷	Tðl �Ð0×6Ñ6Ñ>Øö ,ˆ×Ò°·±ð  ö $1‘<°h€LØ ÐØ"Ñ.Ù"=Ó"?ÐÜ*Ð+B×CÑCÜ ØLóð ð #×(Ñ(Ð,B×,HÑ,HÓHØáGØ'Àóð 	ð
 !Ð rN   r�   )NN)T)crò   Ú	functoolsrÌ   r`  Úcollectionsr   Úcollections.abcr   Údataclassesr   Útypingr   rk   Útorch.nnrv   Útorch.ao.quantizationr   r   Ú$torch.ao.quantization.backend_configr	   Ú#torch.ao.quantization.fake_quantizer
   r   Útorch.ao.quantization.observerr   r   r   Útorch.ao.quantization.qconfigr   r   r   Ú%torch.ao.quantization.qconfig_mappingr   Útorch.ao.quantization.stubsr   Útorch.ao.quantization.utilsr   r   Útorch.fxr   r   Útorch.fx.graphr   r   Ú_decomposedr   Úcustom_configr   Ú__all__rw   Ú
layer_normÚ
group_normÚinstance_normr0   r2   rI   r.   r-   rD   rH   rK   r$   r%   r(   rE   r&   r    r*   rÅ   r—   r   r¹   r!   r   rL   r   r1   r,   Úfloatrß   rà   r/   rs   rF   r#   r'   r+   rG   r"   r)   r
  r  rÿ   r  r#  r=  r  rQ  rt  r?   rN   rO   Ú<module>rŒ     s)  ðä Û Û Û Ý "Ý $Ý !Ý ã Ý ß 7Ý E÷÷ñ ÷
ñ õ
 AÝ 3÷÷ *ß &õ 2Ý .ò€ð4 
‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×"Ñ"Ø	‡H�H×Ñ×%Ñ%ðÐ ð ÷
Eð 
Eó ð
Eð,˜Tð ,¨ð ,°ô ,ð*˜4ð * cð *¨dô *ð-Ø 	¨4°°d°
Ñ+;Ð ;Ñ<ð-à	ˆ#�Yô-ò>Ið (ð ¨xô ð(¨#ð °(ô ð" ð ¨$¨t©*°tÑ*;ô ð<Ø
ðØ'+¨D¡zðàôð: ‡�ð1¨¯©¯©ð 1¸Só 1ó ð1ð #'ñØ�H‰H�O‰Oðàðð ðð ð	ð
 �L‰L˜4Ñðð 
õð4QØ
ðQØ˜c 5§8¡8§?¡?Ð2Ñ3ðQØ<@ÀÀtÀÑ<LðQà	ôQðh* Tð *¨d°3©iô *ð	  c¡ð 	¨x¸¸ÀÀSÁ	Ð8IÑ/Jô 	ñ �j +Ó.€ñ ˆ]˜MÓ*Ø�
‰
‘O Q CÓ(Ø‰ ˜sÓ#ð-ñ ˆ]˜IÓ&¨Ð.HÐ(IÙˆ]˜HÓ%¨Ð-GÐ'HÙˆ]˜IÓ&¨Ð.HÐ(IÙˆ]˜FÓ# c©?¸A¸3Ó+?Ð%@Ùˆ]˜KÓ(¨3Ð0JÐ*KÙˆ]˜EŸO™OÓ,¨sÐ4NÐ.OÙˆ]˜KÓ(¨3±ÀÀÓ0DÐ*EÙˆ]˜LÓ)¨C±À!ÀÓ1EÐ+FÙˆ]˜EŸO™OÓ,¨s±OÀQÀCÓ4HÐ.IÙˆ]˜FÓ# cÐ+EÐ%Fðð ˜Øˆd�4˜%Ÿ+™+Ñ% x°°¸¸S¹	Ð0AÑ'BÐBÑCÐCñó ð& IK€��T˜EŸK™KÑ'¨°4°&¸$¸s¹)Ð2CÑ)DÐDÑEÓ Jð	=Ø
ð	=à	ˆ$�—‘Ñ
˜h¨ v¨t°C©yÐ'8Ñ9Ð
9Ñ:ô	=ð 26Ø"&ñ	Ø
ðà�#�r—y‘y�.Ñ!ðð ˜RŸY™Y™¨$Ñ.ðð  ð	ð
 
ˆD�[õð@
Øð
à˜C ˜H‘oð
ð ð
ð 
ô	
ð8Ø.ð8ØFJð8à
ˆ4�‰9�d˜4 ™9‘oÐ%Ñ&ô8ð2 àñ=Ø
ð=à˜˜UŸX™XŸ_™_Ð,Ñ-ð=ð ð=ð
 �D‰jð=ð 
õ=ð8 àñKØ
ðKà˜˜UŸX™XŸ_™_Ð,Ñ-ðKð ðKð
 �D‰jðKð 
õKð2	Ø
ð	Ø# C¨¯©¯©Ð$8Ñ9ð	à
‡X�X‡_�_�tÑô	ð=Ø
ð=à�8‰8�?‰?ð=ð ˜˜UŸX™XŸ_™_Ð,Ñ-ð=ð ð	=ð
 
ô=ð(\Ø
ð\à�8‰8�?‰?ð\ð ˜˜UŸX™XŸ_™_Ð,Ñ-ð\ð ð	\ð
 
ô\ð~FØ	ðFà˜˜UŸX™XŸ_™_Ð,Ñ-ðFð 
ˆD�[ôFðRf=¨%ô f=ðR?Ø)Ð,<Ñ<ð?àô?ð( ñ!Øð!à0ð!ð ð!ð 
ö	!rN   