
    x-jc                       d dl mZ d dlZd dlZd dlmZ d dlmZmZ d dl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 d	d
lmZ d	dlmZmZmZ d	dlmZmZ d	dlmZmZmZm Z m!Z! er%d dl"m#Z# d dlm$Z$ d dlm%Z%  ede$e#e$                   Z&	 d-d.dZ'd/dZ( G d d          Z) G d  d!          Z*d" Z+d# d$d$fd0d'Z,e
j-        d-d1d)            Z.e
j-        	 d2d3d,            Z/dS )4    )annotationsN)OrderedDict)TYPE_CHECKINGTypeVar)	framework)ops_contain_noneprim_config)Operatordefault_main_program)
as_tensors   )
_composite)lookup_compositelookup_orig2primlookup_prim2orig)
_orig2prim
_prim2orig)flatten_and_remove_noneget_input_var_listget_output_var_listmap_output_for_compositeprepare_python_api_arguments)Sequence)Tensor)Block_TensorOrTensorsTxsSequence[Tensor]ysblockBlock | Nonereturn/tuple[list[Tensor], list[Tensor], list[Tensor]]c                &   | t                                                      n|}g }g }t                      t                      | D ]+}||j        |k    s
J d            |t	          |          <   ,fd}|j        D ]S} ||          rF|                    |           t          t          |                    D ]}|t	          |          <   Tt          fd|D                       fd}	t          |          D ]S} |	|          rF|                    |           t          t          |                    D ]}|t	          |          <   Tfd| D             }
fd|D             }t          t          |                    |
|fS )a  Returns the list of ops on the path from `xs` to `ys` in topological
    order.

    TODO(Tongxin): supporting control flow and nested blocks.
    Args:
        xs: a list|tuple of vars as source
        ys: a list|tuple of vars as sink
        block: the program block containing the path, optional
    Returns:
        (path, unused_xs, unreached_ys): a tuple comprised of the resulting op
        path, the unused variables in `xs`, and the unreached variables in `ys`
    Nz"x is not None and x.block != blockc                n    t          fdt          t          |                     D                       S )Nc              3  :   K   | ]}t          |          v V  d S Nid).0vreached_varss     ^/var/www/html/banglarbhumi/venv/lib/python3.11/site-packages/paddle/incubate/autograd/primx.py	<genexpr>z.topo_path.<locals>.<lambda>.<locals>.<genexpr>S   sB         	1         )anyr   r   )opr,   s    r-   <lambda>ztopo_path.<locals>.<lambda>S   sH    #    ();B)?)?@@     r/   c              3  \   K   | ]&}t          |          v t          |          |fV  'd S r'   r(   r*   yr,   s     r-   r.   ztopo_path.<locals>.<genexpr>a   s=      LL1bee|6K6KRUUAJ6K6K6K6KLLr/   c                n    t          fdt          t          |                     D                       S )Nc              3  :   K   | ]}t          |          v V  d S r'   r(   )r*   out	used_varss     r-   r.   z.topo_path.<locals>.<lambda>.<locals>.<genexpr>b   sB       # # 	39# # # # # #r/   )r0   r   r   )r1   r9   s    r-   r2   ztopo_path.<locals>.<lambda>b   sH    s # # # #*+>r+B+BCC# # #     r/   c                6    g | ]}t          |          v|S  r(   )r*   xr9   s     r-   
<listcomp>ztopo_path.<locals>.<listcomp>n   s)    999q"Q%%y"8"8"8"8"8r/   c                6    g | ]}t          |          v|S r;   r(   r4   s     r-   r=   ztopo_path.<locals>.<listcomp>o   s)    ???!RUU,%>%>A%>%>%>r/   )r   current_blockr   r    r)   opsappendr   r   reversedr   list)r   r   r    pathbackpathr<   reachingr1   varback_reaching	unused_xsunreached_ysr,   r9   s               @@r-   	topo_pathrK   4   s     7<m ""00222EDH==LI     yAGu,,,0 -,,  RUU   H i , ,8B<< 	,KKOOO./B2/F/FGG , ,(+RWW%%LLLLLLLLLI   M tnn ) )= 	)OOB./A"/E/EFF ) )%(	"S''""9999B999I????r???L""##Y<<r/   rD   Sequence[Operator]OrderedDict[int, list[Tensor]]c                    t                      }| D ]3}t          t          |                    D ]}||t          |          <   4|S )zReturns the output variables of all the ops on the path from `xs`
    to `ys`.

    Args:
        path: a list of ops on which to find the output variables

    Returns:
        vars: the output vars
    )r   r   r   r)   )rD   varsr1   r8   s       r-   output_vars_on_pathrP   t   sY     ==D    *+>r+B+BCC 	  	 CDCMM	  Kr/   c                      e Zd ZU dZg dZded<   ded<   ded<   ddZddZddZd dZ	d!dZ
d"dZd#dZd$dZd%dZdS )&VarMapz~A general map data structure for linking variables to variables.

    An example is linking variables to their gradients.
    )namevarsettabstrrS   OrderedDict[int, Tensor]rT   zOrderedDict[int, int]rU   r"   Nonec                H    || _         || _        t                      | _        d S r'   )rS   rT   r   rU   )selfrS   rT   s      r-   __init__zVarMap.__init__   s    	==r/   key_varr   	value_varc                N    t          |          | j        t          |          <   d S r'   r)   rU   )rZ   r\   r]   s      r-   addz
VarMap.add   s      "9Gr/   key_vars
value_varsTensor | Nonec                Z   |d S t          |t          j        j        j        t          j        j        f          rzt          |t          j        j        j        t          j        j        f          st          dt          |                     t          |          | j
        t          |          <   d S t          |          t          |          k    s+J dt          |           dt          |           d            t          ||          D ]\  }}|                     ||           d S )Nz%value_vars must be Variable, but got zDlen(key_vars) should be equal to len(value_vars), but len(key_vars)=z and len(value_vars)=.)
isinstancepaddlebaser   VariablepirValue	TypeErrortyper)   rU   lenzipadd_rec)rZ   ra   rb   r\   r]   s        r-   rp   zVarMap.add_rec   sD   Fv{,5vz7GH
 
 	1 V[2;VZ=MN    ND<L<LNN   &(
^^DHR\\"""x==C
OO333\%(]]\ \ILZ\ \ \ 433 '*(J&?&? 1 1"Wi00001 1r/   c                    | j                             t          |                    }|| j                            |          S d S r'   )rU   getr)   rT   )rZ   r\   value_ids      r-   lookupzVarMap.lookup   s:    8<<7,,;??8,,,4r/   c                d    t          |          }|| j        v r| j        t          |          = d S d S r'   r_   )rZ   r\   varids      r-   deletezVarMap.delete   s8    7DHG%%% r/   r   c                P    |D ]"}t          |          }|| j        v r| j        |= #d S r'   r_   )rZ   ra   rG   rv   s       r-   delete_keyvarszVarMap.delete_keyvars   s=     	$ 	$CsGGE  HUO	$ 	$r/   c                    d |D             fd| j                                         D             }|D ]
}| j         |= d S )Nc                ,    g | ]}t          |          S r;   r(   r*   r+   s     r-   r=   z+VarMap.delete_valuevars.<locals>.<listcomp>   s    )))r!uu)))r/   c                "    g | ]\  }}|v 	|S r;   r;   )r*   kr+   idss      r-   r=   z+VarMap.delete_valuevars.<locals>.<listcomp>   s"    ;;;da!s(((((r/   )rU   items)rZ   rb   keysr~   r   s       @r-   delete_valuevarszVarMap.delete_valuevars   s_    ))j)));;;;dhnn..;;; 	 	A	 	r/   boolc                P    | j                             t          |                    S r'   )rU   __contains__r)   )rZ   r\   s     r-   contain_varzVarMap.contain_var   s    x$$R[[111r/   c                R    t          |          | j                                        v S r'   )r)   rU   values)rZ   r]   s     r-   contain_valuezVarMap.contain_value   s    )}} 1 111r/   N)rS   rV   rT   rW   r"   rX   )r\   r   r]   r   r"   rX   )ra   r   rb   rc   r"   rX   )r\   r   r"   rc   )r\   r   r"   rX   )ra   r   r"   rX   )rb   r   r"   rX   )r\   r   r"   r   )r]   r   r"   r   )__name__
__module____qualname____doc__	__slots____annotations__r[   r`   rp   rt   rw   ry   r   r   r   r;   r/   r-   rR   rR      s         
 *))IIII$$$$! ! ! !
. . . .1 1 1 1*   & & & &
$ $ $ $   2 2 2 22 2 2 2 2 2r/   rR   c                  |    e Zd ZU dZded<   ded<   ded<   ded<   ddZddZddZd dZd!dZ	d"dZ
d#dZd$dZdS )%	TransformzYAn object that maintains the state of transformations applied to a
    primitive program.r   r    rW   rO   rR   var2dotdot2barr"   rX   c                   |t                                                      k    s
J d            || _        |                     |          | _        t          d| j                  | _        t          d| j                  | _        d S )Nz8only support transform on current block of main program.r   dot2var)r   r?   r    	init_varsrO   rR   r   r   )rZ   r    s     r-   r[   zTransform.__init__   sw    ,..<<>>>>>F ?>> 
NN5))	i33i33r/   c                    t                      }|j                                        D ]\  }}||t          |          <   |S r'   )r   rO   r   r)   )rZ   r    rO   _rG   s        r-   r   zTransform.init_vars   sB    }}j&&(( 	  	 FAsDCMMr/   new_varsSequence[Tensor | None]c                N    | j                             d |D                        d S )Nc                2    i | ]}|t          |          |S r'   r(   r|   s     r-   
<dictcomp>z&Transform.add_vars.<locals>.<dictcomp>   s!    FFFq"Q%%r/   )rO   update)rZ   r   s     r-   add_varszTransform.add_vars   s-    	FFHFFFGGGGGr/   Tensor | list[Tensor] | Nonec                j   |d S t          |t          j        j        j        t          j        j        f          r+| j                            t          |          |i           d S t          |t                    st          dt          |                     |D ]}|                     |           d S )Nznew_vars must be list, but got )rf   rg   rh   r   ri   rj   rk   rO   r   r)   rC   rl   rm   add_vars_rec)rZ   r   rG   s      r-   r   zTransform.add_vars_rec   s    Fv{,5vz7GH
 
 	 IbllH5666F(D)) 	PNd8nnNNOOO 	# 	#Cc""""	# 	#r/   ordered_indexesSequence[int]c                    | j         }t          |          D ] }|j                            ||dz              !t          |          D ]
}|j        |= |                                 d S )Nr   )r    rB   desc
_remove_opr@   _sync_with_cpp)rZ   r   r    op_indexs       r-   	erase_opszTransform.erase_ops   s}    
 11 	: 	:HJ!!(HqL9999 !11 	$ 	$H	(##r/   vars_to_eraser   c                   |D ]-}t          |          | j        v r| j        t          |          = .| j                            |           | j                            |           | j        }|D ]=}|j        }|j        	                    |
                                           |j        |= >|                                 d S r'   )r)   rO   r   ry   r   r   r    rS   r   _remove_varencoder   )rZ   r   rG   r    rS   s        r-   
erase_dotszTransform.erase_dots  s      	' 	'C#ww$)##Ibgg&##M222%%m444
  	! 	!C8DJ""4;;==111
4  r/   r   c                     t          |t          j        j        j        t          j        j        f          r j                            |          }|S  fd|D             }|S )zLookup var2dot recursively.c                :    g | ]}                     |          S r;   )var2dot_rec)r*   rG   rZ   s     r-   r=   z)Transform.var2dot_rec.<locals>.<listcomp>  '    666#  %%666r/   )	rf   rg   rh   r   ri   rj   rk   r   rt   )rZ   rO   dotdotss   `   r-   r   zTransform.var2dot_rec  s_    dV[2;VZ=MNOO 	,%%d++CJ6666666r/   r   c                     t          |t          j        j        j        t          j        j        f          r( j                            |          }|
J d            |S  fd|D             }|S )Nzbar must be not Nonec                :    g | ]}                     |          S r;   )dot2bar_rec)r*   r   rZ   s     r-   r=   z)Transform.dot2bar_rec.<locals>.<listcomp>   r   r/   )	rf   rg   rh   r   ri   rj   rk   r   rt   )rZ   r   barbarss   `   r-   r   zTransform.dot2bar_rec  so    dV[2;VZ=MNOO 	,%%d++C??$:???J6666666r/   N)r    r   r"   rX   )r    r   r"   rW   )r   r   r"   rX   )r   r   r"   rX   )r   r   r"   rX   )r   r   r"   rX   )rO   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      s           LLL""""OOOOOO4 4 4 4   H H H H# # # #	 	 	 	           r/   r   c                	   fdfdfd|rt           nt          }|rt          nt          }i }i }i }| j                                        D ]>}|                     |                                          ||                                <   ?g }	t                      }
t          t          | j                            D ]u}| j        |         }|	                    |            ||j                  |j        |vrt          |          } |||           t           t!          |                     t#           ||g|R                                D ]Z\  }}|d u |d u z  r
J d            |
                    |j                   |||j        <   |j        ||j        <   |j        ||j        <   [i }t          t          |j                            D ]:} |                    |j        |                   |          ||j        |         <   ;i }t          t          |j                            D ]0}|                    |j        |                   ||j        |         <   1i }t/          |j                  D ]}|                    |          ||<   ddlm} | j                                        } ||          5   ||          5  t;          | ||j        |||          }d d d            n# 1 swxY w Y   d d d            n# 1 swxY w Y   | j                            |           wt=          |	          D ](}| j                            ||dz              | j        |= )|                                   t          t          | j                            D ]c}| j        |         }|j!        D ]"}||v r|"                    |||                    #|j#        D ]"}||v r|$                    |||                    #dt/          |
          D ]T}||v sJ d	| d
            |||         k    r4| j        %                    |&                                           | j'        |= U|                                   d S )Nc                
   t          t          |                     D ]d}t          | |         t                    r | |         ||           1| |         +| |         j        |v r||| |         j                          | |<   ed S r'   )rangern   rf   rC   rS   argsto_bindvalue_tableibinds       r-   r   z_lower.<locals>.bind'  s    s4yy!! 	= 	=A$q'4(( =T!Wg{3333a$a)@)@%gd1gl&;<Q		= 	=r/   c                    g }| D ]X}t          |t                    r |                     ||                     7|                    ||v r||         n|           Y|S r'   rf   rC   rA   namesr   return_listrS   	bind_names       r-   r   z_lower.<locals>.bind_name.  |     	O 	OD$%% O""99T7#;#;<<<<""DGOO74==NNNNr/   c                    g }| D ];}t          |t                    r| |          z   }&|                    |           <|S r'   r   r   r   r<   expand_nested_lists      r-   r   z"_lower.<locals>.expand_nested_list7  ^     	& 	&A!T"" &),>,>q,A,AA""1%%%%r/   "orig_out and new_out should match.r   )param_guard)r    r   rm   inputsoutputsattrsr   
var_name "" is not in to_bind_rev.)(r   r   r   r   r   all_varsrG   rS   setr   rn   r@   rA   rm   r   ro   r   r   r`   input_namesinputoutput_namesoutputsorted
attr_namesattrpaddle.base.dygraph.baser   	append_opr
   rB   r   r   input_arg_names_rename_inputoutput_arg_names_rename_outputr   r   rO   )r    reverse	blacklistlower_fn	lookup_fnr   r   to_bind_revrG   ops_to_removevars_to_removeop_idxr1   
input_argsorig_outnew_outr   r   r   r   rS   r   new_op_descin_nameout_namevar_namer   r   r   s                             @@@r-   _lowerr   %  s   = = = = =         %4zz*H$+A  1AIKGKz""$$ 8 8"'))CHHJJ"7"7CHHJJMUUN EI'' ,! ,!YvV$$$9RW)bgY.F.F+B//JDWk222%(""#6r#:#:;;"":hhr.GJ.G.G.G#H#HII& & 
: 
:!' %,DA  8 A ""7<000,3GL))0&,4MGL))
: F3r~..//  ,5IHHR^A.//- -r~a()) G3r//00 L L.0ii8J.K.K*++Er}-- , , ggdmmd<<<<<<*..00KV$$  kk'&:&:  $!#                                IR     =))  
ffqj111If	EI'' C CYv) 	@ 	@G+%%  +g*>???+ 	C 	CH;&&!!(K,ABBB	C >** % %;&&&;;;; '&& {8,,,J""8??#4#4555
8$	s6   LK;/L;K??LK?LL	L	c                    dS )NTr;   )r<   s    r-   r2   r2     s    T r/   filter_+typing.Callable[[framework.Operator], bool]c                j   ! fd fd !fd!t          | t          j        j        j                  rBt          j        d           t          }t          }i }i }i }| j	        
                                D ]>}	|                     |	                                          ||	                                <   ?g }
t                      }t                      }d}t          | j                  }t!          |          }d|cxk    r|k    sn J d| d|             d|cxk    r|k    sn J d	| d
|             |dk    r|dk    rJ d| d|             |dk    rt!          ||z
            }|dk    rt!          ||          }dx}}t!          |          D ]}| j        |         }|
                    |           |j        } ||          duo ||          o||v }|s|r|                                  |}|rd}t(          d                             |           t-          |          } |||            !t/          |                    } !t1           ||g|R                      }t          |          t          |          k    s-J d| dt          |           dt          |                       t3          ||          D ]2\  }}||!|t4          vrt7          d| d| d|           |.||j        |j        k    s-J d| d|j         d|j         d|j         d|j         
            d|j        vsJ d| d            |j        |j        k    s-J d| d|j         d|j         d|j         d|j         
            |du |du z  r
J d            |                    |j                   |||j        <   |j        ||j        <   |j        ||j        <   |                    |j                   4m| j	                                        }|                    |j	                   |                                  tA          |
          D ](}| j	        !                    ||dz              | j        |= )|                                  t!          t          | j                            D ]c}| j        |         }|j"        D ]"}||v r|#                    |||                    #|j$        D ]"}||v r|%                    |||                    #dtM          |          D ]T}||v sJ d| d            |||         k    r4| j	        '                    |(                                           | j)        |= U|                                  tM          |          D ]6}| j	        '                    |(                                           | j)        |= 7|                                  | j        D ]l}|*                    |j	                                                  r>|j	        +                    | j	                   |j	        ,                    | j	                   m|rt[          | |||            dS t          | t\          j/                  r| D ]}t[          ||||            dS t`          )!z^The operators in block which satisfy the filter condition will be decomposite into primitives.c                   t          t          |                     D ]}t          | |         t                    r | |         ||           t          | |         t          j        j        j        t          j        j	        f          sl| |         +| |         j
        |v r||| |         j
                          | |<   d S r'   )r   rn   rf   rC   rg   rh   r   ri   rj   rk   rS   r   s       r-   r   z_lower_composite.<locals>.bind  s    s4yy!! 	= 	=A$q'4(( 4T!Wg{333Q&+/8&*:JK  = a$a)@)@%gd1gl&;<Q	= 	=r/   c                    g }| D ]X}t          |t                    r |                     ||                     7|                    ||v r||         n|           Y|S r'   r   r   s       r-   r   z#_lower_composite.<locals>.bind_name  r   r/   c                    g }| D ];}t          |t                    r| |          z   }&|                    |           <|S r'   r   r   s      r-   r   z,_lower_composite.<locals>.expand_nested_list  r   r/   z,Atomize composite op to primitive ops begin.Nr   z expect -1 <= backward_length <= z, but got backward_length: zexpect -1 <= start_idx <= z, but got start_idx: zgot start_idx: z and backward_length: FTcomposite_ops_recordzwhen replace origin op z[ with composite rule, num of origin outs should be equal to new outs, but len(orig_outs) = z and len(new_outs) = zop z2 should not contain any None value. original outs=z and its composite rule outs=zW with composite rule, origin out dtype should be equal to new out dtype, but orig_out: z.dtype=z and new_out: z1 with composite rule, composite out shape has -1.zW with composite rule, origin out shape should be equal to new out shape, but orig_out: z.shape=r   r   r   r   )	start_idxbackward_length)1rf   rg   rh   r   r   logginginfor   r   r   r   rG   rS   r   rn   r@   r   rA   rm   r   r	   r`   r   r   r   ro   r   
ValueErrordtypeshaper   	copy_fromrB   r   r   r   r   r   r   r   r   rO   _has_kernelinfer_var_typeinfer_shape_lower_compositetypingr   rl   )"r    r   r   r   r   r   r   r   r   rG   r   r   none_vars_to_removechangelengthidx_listlower	lower_prer   r1   op_namer   	orig_outsnew_outsr   r   op_descr   r   r   itemr   r   r   s"                                  @@@r-   r	  r	    s   	= 	= 	= 	= 	=         %.455 mCDDD $	:&&(( 	< 	<C&+ii

&;&;K

## "ee UY==_.........cvccRacc /.. Y((((&(((((QQQiQQ )(( $b((Y^^^PiPPPP .<^< RVo566Hr>>Y//H!!	Fmm I	+ I	+F6"B  (((gG 7##4/ 'GBKK'h& 
  ' '$$&&&I 3+2377@@@9"==
Z+666../G/K/KLL	--xx8Z88899  9~~X666ag a a,/	NNa aQTU]Q^Q^a a 766
 *-* * !? !?%Hg !(GO'777( P'  P  P]f  P  P  FN  P  P    '  ,'~>>>Fg F F-5]F FCK>F FahamF Fv}  wDF F  ?>>  "666pgppp  766  (~>>>Fg F F-5]F FCK>F FahamF Fv}  wDF F  ?>> %-$4D#I  @ I '**7<8884;GL118.4<MGL11+//>>>>C!?F  *..00!!"'****}-- 	" 	"FJ!!&&1*555	&!!C	NN++ 	G 	GF6"B- D Dk))$$Wk'.BCCC/ G G{**%%hH0EFFFG ~.. 	) 	)H{***?X??? +** ;x000
&&x'8'8999Jx(233 	% 	%HJ""8??#4#4555
8$$) 	0 	0B~~bgllnn-- 0&&uz222##EJ/// 	# /	    		E6?	+	+ 
 	 	D# /	     	r/   rX   c                    |  t                                                      n| } | t                                                      k    s
J d            t          | dg            dS )a-  
    Note:
        **This API is ONLY available in the static graph mode.**
        **Args block must be None or current block of main program.**

    All operators in the target block are processed as follows.
    If it is an original operator, it will be transformed into
    one or a series of automatic differential basic operators with
    equivalent function.

    Args:
        block(paddle.static.Block|None, optional): The
            target block to process on. Default None, and will
            process on the current block of main program.
    N7block is neither None nor current block of main programFr   r   r   r?   r   )r    s    r-   	orig2primr  k  sq    $ 7<m ""00222E(**88:::::A ;:: 5%2......r/   r   list[str] | Nonec                    |  t                                                      n| } | t                                                      k    s
J d            |g n|}t          | d|           dS )a  
    Note:
        **ONLY available in the static graph mode.**
        **Args block must be None or current block of main program.**

    All operators in the target block are processed as follows.
    If it is an automatic differential basic operator, it will be
    transformed into one or a series of original operators with
    equivalent function to support execution.

    Args:
        block(paddle.static.Block|None, optional): The
            target block to process on. Default None, and will
            process on the current block of main program.
        blacklist(list[string]|None, optional): The names of automatic
            differential basic operator that will not be transformed
            into original operators. Default None, and the blacklist
            is treated as empty list.

    Examples:

        .. code-block:: python

            >>> import paddle
            >>> from paddle.incubate.autograd import enable_prim, prim_enabled, prim2orig

            >>> paddle.enable_static()
            >>> enable_prim()

            >>> x = paddle.ones(shape=[2, 2], dtype='float32')
            >>> x.stop_gradient = False
            >>> y = x * x
            >>> dy_dx = paddle.static.gradients(y, x)
            >>> if prim_enabled():
            ...     prim2orig()
    Nr  Tr  r  )r    r   s     r-   	prim2origr    s    R 7<m ""00222E(**88:::::A ;::  'YI
5$)444444r/   r'   )r   r   r   r   r    r!   r"   r#   )rD   rL   r"   rM   )r   r   )r    r!   r"   rX   )NN)r    r!   r   r  r"   rX   )0
__future__r   r   r
  collectionsr   r   r   rg   paddle.baser   paddle.base.corer   r	   paddle.base.frameworkr
   r   paddle.incubate.autograd.utilsr   composite_rulesr   primregr   r   r   	primrulesr   r   utilsr   r   r   r   r   collections.abcr   r   r   r   rK   rP   rR   r   r   r	  static_onlyr  r  r;   r/   r-   <module>r*     s   # " " " " "   # # # # # # ) ) ) ) ) ) ) )  ! ! ! ! ! ! : : : : : : : : @ @ @ @ @ @ @ @ 5 5 5 5 5 5 ' ' ' ' ' '         
 . - - - - - - -               O((((((++++++ 3VXf=MNN GK== == == == ==@   (E2 E2 E2 E2 E2 E2 E2 E2RP P P P P P P Phn n nf <J>	R R R R Rj / / / / /0 >B-5 -5 -5 -5 -5 -5 -5r/   