§
    kŠtjÿ?  ã                  óØ   — d dl mZ d dlZd dlZd dlmZ d dlZddlmZm	Z	m
Z
 ddlmZ ddlmZmZ dd	lmZ d
dlmZ d
dlmZ 	 	 	 	 	 	 	 	 	 	 d1d2d#„Zd3d'„Z G d(„ d)¦  «        Z	 	 d4d5d0„ZdS )6é    )ÚannotationsN)ÚPathé   )Úfix_output_shapesÚmake_input_shape_fixedÚoptimize_model)Úremove_initializer_from_inputé   )Ú
FusionGeluÚFusionLayerNormalization)Ú	ONNXModelé   )ÚFusionLpNormalization)ÚFusionSpaceToDepthFé   Úmodel_inputústr | Path | onnx.ModelProtoÚmodel_outputú
str | PathÚexclude_initializer_from_inputÚboolÚfuse_layernormÚsave_as_external_dataÚall_tensors_to_one_fileÚexternal_data_locationú
str | NoneÚexternal_data_size_thresholdÚintÚexternal_data_convert_attributeÚinputs_to_make_channel_lastúlist[str] | NoneÚoutputs_to_make_channel_lastÚdynamic_input_shapesúlist[tuple[str, str]] | NoneÚreturnc           	     ó  — d}t          | t          j        ¦  «        r| nt          j        | ¦  «        }t	          |d¬¦  «        }t          |¦  «        }|r`|D ]G\  }}d„ |                     d¦  «        D ¦   «         }t          |                     ¦   «         ||¦  «         ŒHt          |j
        ¦  «         d}|r|t          |j
        ¦  «        z  }t          |¦  «        }|                     ¦   «         rd}t          |¦  «        }|                     ¦   «         rd}t          |¦  «        }|                     ¦   «         rd}|rlt!          d„ |j        D ¦   «         ¦  «        }|j        dk     rt'          j        d|j        › d	�¦  «         n%t+          |¦  «        }|                     ¦   «         rd}|	s|
r5d
}|                     |¦  «        dz   }t/          |j
        |	|
||¬¦  «         d}d}|                     |¦  «        dz   }|j
        j        j        D ]H}|j        dk    r;|j        s4|› |›�}|dz  }||_        d}t'          j        d|j        › d|› d�¦  «         ŒI|r/|                     ¦   «          t          j        |||||||¬¦  «         |S )aÑ  
    If necessary, this method creates a new "pre-processed" model in preparation for
    quantization of a model to be used in QNN EP. Returns true if a new model was created.

    This method perfoms the following operations:
    - Fuse Erf sequence into a single Gelu node.
    - Fuse ReduceL2 sequence into a single LpNormalization node (p == 2).
    - (Optional) Fuse ReduceMean sequence into a single LayerNormalization node.

    Args:
        model_input: Path to the input model file or ModelProto.
        model_output: Path the output model file, which is only created if this method returns True.
        exclude_initializer_from_input: A bool specifying whether to exclude initializer from input.
            Defaults to False.
        fuse_layernorm: True if ReduceMean sequences should be fused into LayerNormalization nodes.
            Defaults to False.
        save_as_external_data: True if output model should be saved with external data. Defaults to false.
        all_tensors_to_one_file: Effective only if save_as_external_data is true. Defaults to false.
            If true, save all tensors to one external file specified by external_data_location.
            If false, save each tensor to a file named with the tensor name.
        external_data_location: Effective only if save_as_external_data is true. Defaults to None.
            Specify the external file to which all tensors are saved. Path is relative
            to the model path. If not specified, the model's name is used.
        external_data_size_threshold: Effective only if save_as_external_data is true. Defaults to 1024.
            Tensors with a data size >= external_data_size_threshold are converted to external data.
            To convert every tensor with raw data to external data, set to 0.
        external_data_convert_attribute: Effective only if save_as_external_data is true. Defaults to false.
            If true, convert all tensors to external data.
            If false, convert only non-attribute tensors to external data.
        inputs_to_make_channel_last: List of graph input names to transpose to be "channel-last". For example,
            if "input0" originally has the shape (N, C, D1, D2, ..., Dn), the resulting model will change input0's
            shape to (N, D1, D2, ..., Dn, C) and add a transpose node after it.

            Original:
                input0 (N, C, D1, D2, ..., Dn) --> <Nodes>

            Updated:
                input0 (N, D1, D2, ..., Dn, C) --> Transpose --> input0_chanfirst (N, C, D1, D2, ..., Dn) --> <Nodes>

            This can potentially improve inference latency for QDQ models running on QNN EP because the
            additional transpose node may allow other transpose nodes inserted during ORT layout transformation
            to cancel out.
        outputs_to_make_channel_last: List of graph output names to transpose to be "channel-last". For example,
            if "output0" originally has the shape (N, C, D1, D2, ..., Dn), the resulting model will change output0's
            shape to (N, D1, D2, ..., Dn, C) and add a transpose node before it.

            Original:
                <Nodes> --> output0 (N, C, D1, D2, ..., Dn)

            Updated:
                <Nodes> --> output0_chanfirst (N, C, D1, D2, ..., Dn) --> Transpose --> output0 (N, D1, D2, ..., Dn, C)

            This can potentially improve inference latency for QDQ models running on QNN EP because the
            additional transpose node may allow other transpose nodes inserted during ORT layout transformation
            to cancel out.
        dynamic_input_shapes: A list of tuples specifying model input name to and its static shape in comma seprated
            format, for example: [('input', '1,3,256,256')]. Defaults to None.
    FT)Úshape_inferc                ó,   — g | ]}t          |¦  «        ‘ŒS © )r   )Ú.0Úis     úy/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/onnxruntime/quantization/execution_providers/qnn/preprocess.pyú
<listcomp>z(qnn_preprocess_model.<locals>.<listcomp>f   s   € ÐFÐFÐF a�3˜q™6œ6ÐFÐFÐFó    ú,c              3  óF   K  — | ]}|j         d k    s|j         dk    ¯|V — ŒdS )Ú zai.onnxN)Údomain)r*   Úxs     r,   ú	<genexpr>z'qnn_preprocess_model.<locals>.<genexpr>€   s9   è è € ÐcÐc ¸1¼8Àrº>¸>ÈQÌXÐYbÒMbÐMb˜!ÐMbÐMbÐMbÐMbÐcÐcr.   é   zœUnable to fuse ReduceMean sequence into a LayerNormalization node. ONNX model must use an opset >= 17 in order to use LayerNormalization, but found version z9. Please use onnx.version_converter to update your model.ÚTranspose_channel_r   )Útranspose_node_name_prefixÚ transpose_node_name_start_suffixÚqnn_preproc_node_ÚConstantzNode of type z" does not have a name. Renamed to ú.)r   r   ÚlocationÚsize_thresholdÚconvert_attribute)Ú
isinstanceÚonnxÚ
ModelProtoÚ
load_modelÚsave_and_reload_optimize_modelr   Úsplitr   Úgraphr   Úmodelr	   r   Úapplyr   r   ÚnextÚopset_importÚversionÚloggingÚwarningr   Úget_largest_node_name_suffixÚupdate_io_to_channel_lastÚnodeÚop_typeÚnameÚtopological_sortÚ
save_model)r   r   r   r   r   r   r   r   r   r    r"   r#   ÚmodifiedrF   Ú
onnx_modelÚ
input_nameÚinput_shape_strÚinput_shapeÚfusion_geluÚfusion_lpnormÚ
fusion_s2dÚ
onnx_opsetÚfusion_layernormÚtranspose_node_prefixÚtranspose_node_suffixÚunnamed_node_prefixÚavailable_suffixrO   Únew_node_names                                r,   Úqnn_preprocess_modelrc      sK  € ðP €HÝ% kµ4´?ÑCÔCÐeˆKˆKÍÌÐYdÑIeÔIe€EÝ*¨5¸dÐCÑCÔC€EÝ˜5Ñ!Ô!€Jð ð Ø+?ð 	Pð 	PÑ'ˆJ˜ØFÐF¨?×+@Ò+@ÀÑ+EÔ+EÐFÑFÔFˆKÝ" :×#3Ò#3Ñ#5Ô#5°zÀ;ÑOÔOÐOÐOÝ˜*Ô*Ñ+Ô+Ð+Øˆð &ð DØÕ1°*Ô2BÑCÔCÑCˆõ ˜ZÑ(Ô(€KØ×ÒÑÔð Øˆõ *¨*Ñ5Ô5€MØ×ÒÑÔð Øˆõ $ JÑ/Ô/€JØ×ÒÑÔð Øˆð ð  ÝÐcÐc UÔ%7ÐcÑcÔcÑcÔcˆ
ð Ô Ò"Ð"ÝŒOðsà%/Ô%7ðsð sð sñô ð ð õ  8¸
ÑCÔCÐØ×%Ò%Ñ'Ô'ð  Ø�ð #ð 
Ð&Bð 
Ø 4ÐØ%/×%LÒ%LÐMbÑ%cÔ%cÐfgÑ%gÐÝ!ØÔØ'Ø(Ø'<Ø-Bð	
ñ 	
ô 	
ð 	
ð ˆð .ÐØ!×>Ò>Ð?RÑSÔSÐVWÑWÐØÔ Ô&Ô+ð nð nˆØŒ<˜:Ò%Ð%¨d¬iÐ%Ø2ÐHÐ4DÐHÐHˆMØ Ñ!ÐØ%ˆDŒIØˆHÝŒOÐl¨D¬LÐlÐlÐ\iÐlÐlÐlÑmÔmÐmøàð 

Ø×#Ò#Ñ%Ô%Ð%ÝŒØØØ"7Ø$;Ø+Ø7Ø=ð	
ñ 	
ô 	
ð 	
ð €Or.   rF   úonnx.ModelProtor'   c                ó¬  — t          j        d¬¦  «        5 }t          |¦  «                             d¦  «        }t	          j        | |d¬¦  «         |r^t          |¦  «                             d¦  «        }t          j                             t          |¦  «        t          |¦  «        ¦  «         |}t          |¦  «                             d¦  «        }t          ||¦  «         t	          j
        |¦  «        }dd	i}|j        r|                     |j        ¦  «         t          j                             ||¦  «         |cd d d ¦  «         S # 1 swxY w Y   d S )
Nzort.qnn_preproc.)Úprefixzqnn_proc_input.onnxT)r   zqnn_proc_infer.onnxzqnn_proc_output.onnxz
onnx.inferz onnxruntime.tools.qnn.preprocess)ÚtempfileÚTemporaryDirectoryr   Újoinpathr@   rS   Úshape_inferenceÚinfer_shapes_pathÚstrr   rB   Úmetadata_propsÚupdateÚhelperÚset_model_props)rF   r'   Úqnn_preproc_tmp_dirÚmodel_in_pathÚmodel_infer_pathÚmodel_out_pathÚ	ret_modelÚret_metapropss           r,   rC   rC   µ   s†  € Ý	Ô	$Ð,>Ð	?Ñ	?Ô	?ð ÐCVÝÐ0Ñ1Ô1×:Ò:Ð;PÑQÔQˆÝŒ˜˜}ÀDÐIÑIÔIÐIØð 	-Ý#Ð$7Ñ8Ô8×AÒAÐBWÑXÔXÐÝÔ ×2Ò2µ3°}Ñ3EÔ3EÅsÐK[ÑG\ÔG\Ñ]Ô]Ð]Ø,ˆMÝÐ1Ñ2Ô2×;Ò;Ð<RÑSÔSˆÝ�} nÑ5Ô5Ð5Ý”O NÑ3Ô3ˆ	Ø%Ð'IÐJˆØÔ#ð 	;Ø× Ò  Ô!9Ñ:Ô:Ð:ÝŒ×#Ò# I¨}Ñ=Ô=Ð=Øðð ð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ð s   –D&E	Å	EÅEc                  ó   — e Zd Zdd„Zdd	„Zd
S )ÚInputOutputNameMapÚorig_tensor_namesúset[str]Úorig_graph_inputsúdict[str, onnx.ValueInfoProto]Úorig_graph_outputsc                óL   — || _         || _        || _        i | _        g | _        d S ©N)ry   r{   r}   Úupdated_io_namesÚnew_value_infos)Úselfry   r{   r}   s       r,   Ú__init__zInputOutputNameMap.__init__È   s2   € ð "3ˆÔØ!2ˆÔØ"4ˆÔØ "ˆÔØ!ˆÔÐÐr.   Ú	orig_namerl   c                óX  — || j         v r| j         |         S |› d�}d}| j        D ]t}|                     |¦  «        r]|t          |¦  «        d …                              ¦   «         r4t          |t          |¦  «        d …         ¦  «        }t          ||¦  «        }Œu|dz  }|› |›�}| j                             |¦  «        p| j	        |         }t          j        ¦   «         }|                     |¦  «         ||_        | j                             |¦  «         || j         |<   | j         |         S )NÚ_channel_first_éÿÿÿÿr   )r€   ry   Ú
startswithÚlenÚisdigitr   Úmaxr{   Úgetr}   r@   ÚValueInfoProtoÚCopyFromrQ   r�   Úappend)	r‚   r„   rf   ÚsuffixÚtensor_nameÚindexÚnew_nameÚorig_value_infoÚvalue_info_protos	            r,   Úget_new_namezInputOutputNameMap.get_new_nameÔ   sG  € Ø˜Ô-Ð-Ð-ØÔ(¨Ô3Ð3ð #Ð3Ð3Ð3ˆØˆØÔ1ð 	,ð 	,ˆKØ×%Ò% fÑ-Ô-ð ,°+½cÀ&¹k¼k¸m¸mÔ2L×2TÒ2TÑ2VÔ2Vð ,Ý˜K­¨F©¬¨¨Ô6Ñ7Ô7�Ý˜V UÑ+Ô+�øà�!‰ˆØÐ(˜fÐ(Ð(ˆð Ô0×4Ò4°YÑ?Ô?ÐeÀ4ÔCZÐ[dÔCeˆÝÔ.Ñ0Ô0ÐØ×!Ò! /Ñ2Ô2Ð2Ø (ÐÔØÔ×#Ò#Ð$4Ñ5Ô5Ð5à+3ˆÔ˜iÑ(ØÔ$ YÔ/Ð/r.   N)ry   rz   r{   r|   r}   r|   )r„   rl   )Ú__name__Ú
__module__Ú__qualname__rƒ   r–   r)   r.   r,   rx   rx   Ç   s<   € € € € € ð
"ð 
"ð 
"ð 
"ð0ð 0ð 0ð 0ð 0ð 0r.   rx   r6   Úinputs_to_updateÚoutputs_to_updater7   rl   r8   c           	     ó\  — t          |pg ¦  «        }t          |pg ¦  «        }|s|sd S | j        }d„ |j        D ¦   «         }d„ |j        D ¦   «         }|D ]}||vrt	          |› d�¦  «        ‚Œ|D ]}	|	|vrt	          |	› d�¦  «        ‚Œt          ¦   «         }
|
                     t          |¦  «        ¦  «         |
                     t          |¦  «        ¦  «         |
                     d„ |j        D ¦   «         ¦  «         t          |
||¦  «        }|j        D �]}t          t          |j        ¦  «        ¦  «        D ]‹}|j        |         r8|j        |         |v r)| 
                    |j        |         ¦  «        |j        |<   ŒG|j        |         r7|j        |         |v r(| 
                    |j        |         ¦  «        |j        |<   ŒŒt          t          |j        ¦  «        ¦  «        D ]9}|j        |         |v r(| 
                    |j        |         ¦  «        |j        |<   Œ:�Œ|D �]ñ}||         }|j                             d¦  «        r|j        j                             d¦  «        st	          d|j        › d	�¦  «        ‚|j        j        j        }t          |j        ¦  «        }|d
k     rt	          d|j        › d�¦  «        ‚t"          j                             ¦   «         }|                     |j        d         ¦  «         t          d|dz
  ¦  «        D ]0}|j        |                              |j        |dz            ¦  «         Œ1|j        |dz
                                |¦  «         t+          t          |¦  «        ¦  «        }t          |¦  «        D ]}|dk     r|n|dz
  ||<   Œ|dz
  |d<   t"          j                             d|› |›�|j        g| 
                    |j        ¦  «        g|¬¦  «        }|dz  }|j                             |g¦  «         �Œó|D �]ñ}||         }|j                             d¦  «        r|j        j                             d¦  «        st	          d|j        › d	�¦  «        ‚|j        j        j        }t          |j        ¦  «        }|d
k     rt	          d|j        › d�¦  «        ‚t"          j                             ¦   «         }|                     |j        d         ¦  «         t          d|dz
  ¦  «        D ]0}|j        |                              |j        |dz            ¦  «         Œ1|j        |dz
                                |¦  «         t+          t          |¦  «        ¦  «        }t          |¦  «        D ]}|dk    r|n|dz   ||<   Œd||dz
  <   t"          j                             d|› |›�| 
                    |j        ¦  «        g|j        g|¬¦  «        }|dz  }|j                             |g¦  «         �Œó|j                             |j        ¦  «         d S )Nc                ó   — i | ]
}|j         |“ŒS r)   ©rQ   )r*   Úginputs     r,   ú
<dictcomp>z-update_io_to_channel_last.<locals>.<dictcomp>ü   s   € ÐGÐGÐG°˜œ fÐGÐGÐGr.   c                ó   — i | ]
}|j         |“ŒS r)   rž   )r*   Úgoutputs     r,   r    z-update_io_to_channel_last.<locals>.<dictcomp>ý   s   € ÐLÐLÐL°G˜'œ,¨ÐLÐLÐLr.   z is not a graph inputz is not a graph outputc              3  ó2   K  — | ]}|j         D ]}|¯|V — Œ	Œd S r   )Úinput)r*   rO   rV   s      r,   r4   z,update_io_to_channel_last.<locals>.<genexpr>  s9   è è € ÐjÐj¨DÐQUÔQ[ÐjÐjÀ:Ð_iÐj˜ZÐjÐjÐjÐjÐjÐjÐjr.   Útensor_typeÚshapezExpected input z# to have a tensor_type with a shaper
   z to be of rank >= 3r   Ú	Transpose)rQ   ÚinputsÚoutputsÚpermzExpected output r   )ÚsetrE   r¤   ÚoutputÚ
ValueErrorrn   rO   rx   Úranger‰   r–   ÚtypeÚHasFieldr¥   rQ   r¦   Údimr@   ÚTensorShapeProtoÚ	DimensionrŽ   Úlistro   Ú	make_nodeÚextendÚ
value_infor�   )rF   rš   r›   r7   r8   rE   r{   r}   rV   Úoutput_namery   Úio_maprO   r+   Úg_input_nameÚg_inputrX   Ú
input_rankÚchannel_dimÚtranspose_permÚtranspose_nodeÚg_output_nameÚg_outputÚoutput_shapeÚoutput_ranks                            r,   rN   rN   î   sÄ  € õ Ð+Ð1¨rÑ2Ô2ÐÝÐ-Ð3°Ñ4Ô4Ðàð Ð$5ð ØˆàŒK€EØGÐG¸5¼;ÐGÑGÔGÐØLÐL¸u¼|ÐLÑLÔLÐð 'ð Cð Cˆ
ØÐ.Ð.Ð.Ý 
ÐAÐAÐAÑBÔBÐBð /ð )ð Eð EˆØÐ0Ð0Ð0Ý ÐCÐCÐCÑDÔDÐDð 1õ ™œÐØ×Ò�SÐ!2Ñ3Ô3Ñ4Ô4Ð4Ø×Ò�SÐ!3Ñ4Ô4Ñ5Ô5Ð5Ø×ÒÐjÐj°E´JÐjÑjÔjÑjÔjÐjõ  Ð 1Ð3DÐFXÑYÔY€Fð ”
ð 	Eñ 	EˆÝ•s˜4œ:‘”Ñ'Ô'ð 	Cð 	CˆAØŒz˜!Œ}ð C ¤¨A¤Ð2BÐ!BÐ!BØ &× 3Ò 3°D´J¸q´MÑ BÔ B�”
˜1‘�Ø”˜A”ð C 4¤:¨a¤=Ð4EÐ#EÐ#EØ &× 3Ò 3°D´J¸q´MÑ BÔ B�”
˜1‘øå•s˜4œ;Ñ'Ô'Ñ(Ô(ð 	Eð 	EˆAØŒ{˜1Œ~Ð!2Ð2Ð2Ø!'×!4Ò!4°T´[À´^Ñ!DÔ!D�”˜A‘øñ	Eð
 )ð  ,ñ  ,ˆØ# LÔ1ˆàŒ|×$Ò$ ]Ñ3Ô3ð 	b¸7¼<Ô;S×;\Ò;\Ð]dÑ;eÔ;eð 	bÝÐ`¨w¬|Ð`Ð`Ð`ÑaÔaÐaà”lÔ.Ô4ˆÝ˜œÑ)Ô)ˆ
à˜Š>ˆ>ÝÐP¨w¬|ÐPÐPÐPÑQÔQÐQåÔ+×5Ò5Ñ7Ô7ˆØ×Ò˜[œ_¨QÔ/Ñ0Ô0Ð0Ý�q˜* q™.Ñ)Ô)ð 	@ð 	@ˆAØŒO˜AÔ×'Ò'¨¬¸¸A¹Ô(>Ñ?Ô?Ð?Ð?ØŒ˜
 Q™Ô'×0Ò0°Ñ=Ô=Ð=å�e JÑ/Ô/Ñ0Ô0ˆÝ�zÑ"Ô"ð 	6ð 	6ˆAØ%&¨¢U U  °°A±ˆN˜1ÑÐØ&¨™Nˆ�qÑåœ×.Ò.ØØ.ÐTÐ0PÐTÐTØ”L�>Ø×(Ò(¨¬Ñ6Ô6Ð7Øð /ñ 
ô 
ˆð 	)¨AÑ-Ð(àŒ
×Ò˜>Ð*Ñ+Ô+Ð+Ñ+ð +ð ,ñ ,ˆØ% mÔ4ˆØŒ}×%Ò% mÑ4Ô4ð 	d¸H¼MÔ<U×<^Ò<^Ð_fÑ<gÔ<gð 	dÝÐb°´ÐbÐbÐbÑcÔcÐcà”}Ô0Ô6ˆÝ˜,Ô*Ñ+Ô+ˆà˜Š?ˆ?ÝÐR°´ÐRÐRÐRÑSÔSÐSåÔ+×5Ò5Ñ7Ô7ˆØ×Ò˜\Ô-¨aÔ0Ñ1Ô1Ð1Ý�q˜+¨™/Ñ*Ô*ð 	Bð 	BˆAØÔ˜QÔ×(Ò(¨Ô)9¸!¸a¹%Ô)@ÑAÔAÐAÐAØÔ˜ q™Ô)×2Ò2°;Ñ?Ô?Ð?å�e KÑ0Ô0Ñ1Ô1ˆÝ�{Ñ#Ô#ð 	7ð 	7ˆAØ%&¨!¢V V  °°Q±ˆN˜1ÑÐØ*+ˆ�{ Q‘Ñ'åœ×.Ò.ØØ.ÐTÐ0PÐTÐTØ×'Ò'¨¬Ñ6Ô6Ð7Ø”]�OØð /ñ 
ô 
ˆð 	)¨AÑ-Ð(àŒ
×Ò˜>Ð*Ñ+Ô+Ð+Ñ+à	Ô×Ò˜FÔ2Ñ3Ô3Ð3Ð3Ð3r.   )
FFFFNr   FNNN)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   )rF   rd   r'   r   r%   rd   )r6   r   )
rF   rd   rš   r!   r›   r!   r7   rl   r8   r   )Ú
__future__r   rK   rg   Úpathlibr   r@   Útools.onnx_model_utilsr   r   r   Ú#tools.remove_initializer_from_inputr	   Úfusionsr   r   rU   r   rZ   r   Úfusion_spacetodepthr   rc   rC   rx   rN   r)   r.   r,   ú<module>rÊ      sr  ðð #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø Ð Ð Ð Ð Ð à €€€à `Ð `Ð `Ð `Ð `Ð `Ð `Ð `Ð `Ð `Ø QÐ QÐ QÐ QÐ QÐ QØ ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø #Ð #Ð #Ð #Ð #Ð #Ø 0Ð 0Ð 0Ð 0Ð 0Ð 0Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3ð ,1Ø Ø"'Ø$)Ø)-Ø(,Ø,1Ø48Ø59Ø9=ð\ð \ð \ð \ð \ð~ð ð ð ð$$0ð $0ð $0ð $0ð $0ñ $0ô $0ð $0ðV ';Ø,-ðs4ð s4ð s4ð s4ð s4ð s4ð s4r.   