
    in                        S r SSKJr  SSKJrJrJrJrJrJ	r	  SSK
r
SSKrSSKrSSKJrJrJrJr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  SS
KJr  SSK J!r!  SSK"J#r#  SSK$J%r%J&r&   " S S\!5      r' " S S\'5      r( " S S\'5      r)g)z'Scheduler for dynamic circuit backends.    )abstractmethod)DictListOptionalUnionSetTupleN)BitBarrierClbitControlFlowOpMeasureQubitReset)ParameterExpression)circuit_to_dag)
DAGCircuitDAGNode)Target)TranspilerError)TransformationPass)TimeUnitConversion   )BlockOrderingCallableTypeblock_order_op_nodesc                     ^  \ rS rSrSr   S!S\\R                  R                  R                     S\\
   S\\   SS4U 4S jjjr\S\\\\4   \4   4S	 j5       rS
\S\\\4   SS4S jrS\SS4S jrS\SS4S jr\S\SS4S j5       r\S\SS4S j5       r\S\SS4S j5       rS\SS4S jrS\S\4S jr S"S\S\S\S\SS4
S jjr S#S jr!S#S jr"S\#\   4S jr$S\SS4S jr%S\S\&\   4S jr'S\S\&\   4S jr(S r)U =r*$ )$BaseDynamicCircuitAnalysis!   aG  Base class for scheduling analysis

This is a scheduler designed to work for the unique scheduling constraints of the dynamic circuits
backends due to the limitations imposed by hardware. This is expected to evolve over time as the
dynamic circuit backends also change.

The primary differences are that:

* Resets and control-flow currently trigger the end of a "quantum block". The period between the end
    of the block and the next is *nondeterministic*
    ie., we do not know when the next block will begin (as we could be evaluating a classical
    function of nondeterministic length) and therefore the
    next block starts at a *relative* t=0.
* During a measurement it is possible to apply gates in parallel on disjoint qubits.
* Measurements and resets on disjoint qubits happen simultaneously and are part of the same block.
N	durationsblock_ordering_callabletargetreturnc                   > U(       a  [         R                  " S[        SS9  Xl        X0l        Uc  [
        OUU l        SU l        SU l        SU l	        SU l
        0 U l        0 U l        SU l        SU l        SU l        SU l        SU l        SU l        ['        5       U l        SU l        SU l        SU l        [1        U5      U l        [4        TU ]m  5         g)a9  Scheduler for dynamic circuit backends.

Args:
    durations: Durations of instructions to be used in scheduling.
    block_ordering_callable: A callable used to produce an ordering of the nodes to minimize
        the number of blocks needed. If not provided, :func:`~block_order_op_nodes` will be
        used.
zThe `durations` input argument of `BaseDynamicCircuitAnalysis` is deprecated as of qiskit_ibm_runtime v0.43.0 and will be removed in a future release. Provide a `target` instance instead ex: BaseDynamicCircuitAnalysis(target=backend.target).   )
stacklevelNr   F)warningswarnDeprecationWarning
_durations_targetr   _block_ordering_callable_dag
_block_dag	_wire_map_node_mapped_wires_node_block_dags_block_idx_dag_map_current_block_idx_max_block_t1_control_flow_block_node_start_time_node_stop_time_bit_stop_timesset_current_block_measures!_current_block_measures_has_reset_node_tied_to_bit_indicesr   _time_unit_convertersuper__init__)selfr   r    r!   	__class__s       s/home/james-whalen/.local/lib/python3.13/site-packages/qiskit_ibm_runtime/transpiler/passes/scheduling/scheduler.pyr?   #BaseDynamicCircuitAnalysis.__init__3   s     MME # $$;$C I` 	% +/	0437FJ;=9; #$7;#( JNIMTX 69U$7<.DH8<$6y$A!    c                 4    U R                   U R                     $ N)r7   r2   r@   s    rB   _current_block_bit_times3BaseDynamicCircuitAnalysis._current_block_bit_timesn   s    ##D$;$;<<rD   blockwire_mapc                 .   U R                   nXl         U R                  Uso@l        U R                  R                  U5        U R	                  5         U R                  U5       H  nU R                  U5        M     U R                  5         X0l         X@l        g rF   )r-   r.   r=   run_begin_new_circuit_blockr+   _visit_node_flush_measures)r@   rJ   rK   prev_block_dagprev_wire_mapnodes         rB   _visit_block'BaseDynamicCircuitAnalysis._visit_blockr   s    (,%~
 	!!%%e,%%'11%8DT" 9 	 )&rD   rS   c                 L   [        UR                  [        5      (       a  U R                  U5        g [        UR                  [        5      (       a  U R                  U5        g [        UR                  [        5      (       a  U R                  U5        g U R                  U5        g rF   )	
isinstanceopr   _visit_control_flow_opr   _visit_measurer   _visit_reset_visit_genericr@   rS   s     rB   rO   &BaseDynamicCircuitAnalysis._visit_node   sm    dgg}--''-$''7++##D)DGGU++!!$'##D)rD   c                   ^  / =T R                   U'   n[        U 4S jT R                  U5       5       5      nUnT R                  XU5        UR                  R
                   H}  nST l        [        U5      n[        T R                  U5      UR                  UR                  -   5       VVs0 s H  u  pxX_M	     n	nnUR                  U5        T R                  Xi5        M     T R                  5         g s  snnf )Nc              3   B   >#    U  H  nTR                   U   v   M     g 7frF   rH   .0bitr@   s     rB   	<genexpr>DBaseDynamicCircuitAnalysis._visit_control_flow_op.<locals>.<genexpr>          
:O3D))#.:O   T)r0   max
_map_wires_update_bit_timesrX   blocksr4   r   zipqubitsclbitsappendrT   rN   )
r@   rS   node_block_dagst0t1rJ   new_dagouterinnerinner_wire_maps
   `         rB   rY   1BaseDynamicCircuitAnalysis._visit_control_flow_op   s     9;:d#o 
:>//$:O
 

 t,WW^^E'+D$$U+G %((=w~~PWP^P^?^$_$_LE $_   ""7+g6 $ 	%%'s   +C3c                     [         erF   NotImplementedErrorr]   s     rB   rZ   )BaseDynamicCircuitAnalysis._visit_measure       !!rD   c                     [         erF   rz   r]   s     rB   r[   'BaseDynamicCircuitAnalysis._visit_reset   r}   rD   c                     [         erF   rz   r]   s     rB   r\   )BaseDynamicCircuitAnalysis._visit_generic   r}   rD   dagc                 n   Xl         SU l        UR                   Vs0 s H  o"U_M     snU l        0 U l        0 U l        0 U l        SU l        0 U l        SU l	        [        UR                  5      S:w  d  UR                  R                  SS5      c  [        S5      e0 U l        0 U l        SUR                   UR"                  -    Vs0 s H  o3S_M     sn0U l        ['        5       U l        SU l        0 U l        [/        UR                   5       VVs0 s H  u  pCX4_M	     snnU l        gs  snf s  snf s  snnf )zSetup for initial run.Nr   Fr   qz,ASAP schedule runs on physical circuits only)r,   r-   wiresr.   r/   r0   r1   r2   r3   r4   lenqregsgetr   r5   r6   rn   ro   r7   r8   r9   r:   r;   	enumerater<   )r@   r   wirer   indexs        rB   	_init_run$BaseDynamicCircuitAnalysis._init_run   s    	14;*;"$ ""$"##( syy>Q#))--T":"B!"PQQ "! !#**szz2I#J2IQqD2I#JK'*u$16.6?

6KL6K(%QX6KL% < $K Ms   D'D,D1c           	         [        UR                  [        5      (       a  gU R                  U5       Vs/ s H  o R                  U   PM     nnUR
                  S:X  a  UR                  R                  nOUR
                  S:X  a  SnOU R                  (       a  U R                  R                  UR
                  5      nU(       d  S nOUR                  [        U5      5      nU(       d  S nOoU R                  R                  c  UR                  nOKU R                  R                  UR                  5      nO%U R                  R                  UR                  USS9n[        U[        5      (       a)  [        SU SUR                  R
                   SU S	35      eUc&  [        S
UR                  R
                   SU S35      eU$ s  snf )Nr   delaybarrierdt)unitzParameterized duration (z) of z on qubits z is not bounded.zDuration of z is not found.)rW   rX   r   _map_qubitsr<   namedurationr*   r   tupler   seconds_to_dtr)   r   r   )r@   rS   qargindicesr   
props_dictpropss          rB   _get_duration(BaseDynamicCircuitAnalysis._get_duration   sv   dgg}-- 7;7G7G7MN7Mt$$T*7MN99ww''HYY)#H\\))$))4J"uW~6#H||.#(>>#'<<#=#=enn#M**477G$*GHh 344!*8* 5ggll^;wi7GI  !Lk'R`"abb= Os   Grr   rs   update_cargsc                 ~   [        U R                  R                  U R                  S5      U5      U R                  U R                  '   U(       a  U R	                  U5      OU R                  U5      nU H  nX0R                  U'   M     U R                  U4U R                  U'   U R                  U4U R                  U'   g )Nr   )	ri   r3   r   r2   rj   r   rH   r5   r6   )r@   rS   rr   rs   r   update_bitsrd   s          rB   rk   ,BaseDynamicCircuitAnalysis._update_bit_times   s     7:""4#:#:A>7
4223 0<dood+AQAQRVAWC13))#.  (,'>'>&Cd#&*&=&=r%BT"rD   c                 B   U =R                   S-  sl         U R                  U R                  U R                   '   SU l        U R                  R                   Vs0 s H  oR
                  U   S_M     snU R                  U R                   '   U R                  5         gs  snf )z?Create a new timed circuit block completing the previous block.r   Fr   N)r2   r-   r1   r4   r   r.   r7   rP   )r@   r   s     rB   rN   3BaseDynamicCircuitAnalysis._begin_new_circuit_block  s    1$;??? 7 78#( 040E0E9
0ENN4 !#0E9
T445 	9
s   Bc                     U R                    H*  nU R                   R                  5       U R                  U'   M,     [        5       U l         SU l        g)zEFlush currently accumulated measurements by resetting block measures.FN)r9   copyr;   r8   r:   r]   s     rB   rP   *BaseDynamicCircuitAnalysis._flush_measures  sE    00D'+'C'C'H'H'JDt$ 1 (+u$16.rD   c                 B   ^  [        U 4S jT R                   5       5      $ )Nc              3   X   >#    U  H  nTR                  U5        H  o"v   M     M!     g 7frF   )r   )rc   measurer   r@   s      rB   re   JBaseDynamicCircuitAnalysis._current_block_measure_qargs.<locals>.<genexpr>   s*      
 <WIYIYZaIbDIbD <s   '*)r8   r9   rG   s   `rB   _current_block_measure_qargs7BaseDynamicCircuitAnalysis._current_block_measure_qargs  s#     
 $ < <
 
 	
rD   c                     U R                  5       [        U R                  U5      5      -  (       a3  U R                  (       a  U R	                  5         g U R                  5         g g rF   )r   r8   r   r:   rN   rP   r]   s     rB   _check_flush_measures0BaseDynamicCircuitAnalysis._check_flush_measures$  sL    ,,.T5E5Ed5K1LL55--/ $$& MrD   c                     XR                   ;  aG  UR                  UR                  -    Vs/ s H  o R                  U   PM     sn=U R                   U'   nU$ U R                   U   $ s  snf )zMap the wires from the current node to the top-level block's wires.

TODO: We should have an easier approach to wire mapping from the transpiler.
)r/   qargscargsr.   )r@   rS   r   rK   s       rB   rj   %BaseDynamicCircuitAnalysis._map_wires-  sm    
 ...+/::

+B8+Baq!+B8 D##D)H O&&t,,8s   A&c                 ~    U R                  U5       Vs/ s H  n[        U[        5      (       d  M  UPM     sn$ s  snf )zMap the qubits from the current node to the top-level block's qubits.

TODO: We should have an easier approach to wire mapping from the transpiler.
)rj   rW   r   )r@   rS   r   s      rB   r   &BaseDynamicCircuitAnalysis._map_qubits:  s0    
 "&!6R!6*T5:Q!6RRRs   ::)r<   r7   r-   r1   r+   r4   r2   r9   r:   r,   r)   r3   r0   r/   r5   r6   r;   r*   r=   r.   )NNN)Tr"   N)+__name__
__module____qualname____firstlineno____doc__r   qiskit
transpilerinstruction_durationsInstructionDurationsr   r   r?   propertyr   r   r   r   intrH   r   rT   r   rO   rY   r   rZ   r[   r\   r   r   boolrk   rN   rP   r   r   r   r   rj   r   __static_attributes____classcell__)rA   s   @rB   r   r   !   s   & ]aGK#'	9F--CCXXY9 "**C!D9  	9
 
9 9v =$uUE\/BC/G*H = ='* 'UE\8J 't ',	* 	*D 	*(7 (t (B "7 "t " " " "T " " "7 "t " "MZ MD M2$' $c $N EICC!$C*-C=AC	C7
c%j 

'' 'd '-w -4; -S SDK S SrD   r   c                   `    \ rS rSrSrS\S\4S jrS\SS4S jrS\SS4S	 jr	S\SS4S
 jr
Srg)ASAPScheduleAnalysisiB  a  Dynamic circuits as-soon-as-possible (ASAP) scheduling analysis pass.

This is a scheduler designed to work for the unique scheduling constraints of the dynamic circuits
backends due to the limitations imposed by hardware. This is expected to evolve over time as the
dynamic circuit backends also change.

In its current form this is similar to Qiskit's ASAP scheduler in which instructions
start as early as possible.

The primary differences are that:

* Resets and control-flow currently trigger the end of a "quantum block". The period between the end
    of the block and the next is *nondeterministic*
    ie., we do not know when the next block will begin (as we could be evaluating a classical
    function of nondeterministic length) and therefore the
    next block starts at a *relative* t=0.
* During a measurement it is possible to apply gates in parallel on disjoint qubits.
* Measurements and resets on disjoint qubits happen simultaneously and are part of the same block.
r   r"   c                     U R                  U5        UR                   Vs0 s H  o"U_M     nnU R                  X5        U R                  U R                  S'   U R
                  U R                  S'   U$ s  snf )a  Run the ALAPSchedule pass on `dag`.

Args:
    dag (DAGCircuit): DAG to schedule.

Raises:
    TranspilerError: if the circuit is not mapped on physical qubits.
    TranspilerError: if conditional bit is added to non-supported instruction.

Returns:
    The scheduled DAGCircuit.
node_start_timerq   )r   r   rT   r5   property_setr0   r@   r   r   rK   s       rB   rM   ASAPScheduleAnalysis.runW  sr     	s ,/99594$J95#(/3/D/D+,/3/D/D+,
 6s   A3rS   Nc                   ^  T R                  5       n[        T R                  U5      5      n[        U 4S jU 5       5      nX#-  (       a5  T R                  (       a  T R                  5         SnOFT R                  5         O5[        [        R                  " U/U 4S jT R                   5       5      5      nT R                  R                  U5        T R                   H,  nUnT R                  U5      nXg-   nT R                  XVU5        M.     g)  Visit a measurement node.

Measurement currently triggers the end of a deterministically scheduled block
of instructions in IBM dynamic circuits hardware.
This means that it is possible to schedule *up to* a measurement (and during its pulses)
but the measurement will be followed by a period of indeterminism.
All measurements on disjoint qubits that topologically follow another
measurement will be collected and performed in parallel. A measurement on a qubit
intersecting with the set of qubits to be measured in parallel will trigger the
end of a scheduling block with said measurement occurring in a following block
which begins another grouping sequence. This behavior will change in future
backend software updates.c              3   B   >#    U  H  nTR                   U   v   M     g 7frF   ra   rc   r   r@   s     rB   re   6ASAPScheduleAnalysis._visit_measure.<locals>.<genexpr>        
6CD))!,mrh   r   c              3   H   >#    U  H  nTR                   U   S    v   M     g7fr   Nr5   rc   r   r@   s     rB   re   r     #     cFb7T**73A6Fb   "Nr   r8   r   ri   r:   rN   rP   	itertoolschainr9   addr   rk   	r@   rS   current_block_measure_qargsmeasure_qargst0qr   rr   measure_durationrs   s	   `        rB   rZ   #ASAPScheduleAnalysis._visit_measureo       '+&G&G&I# D,,T23 
6C
 
 '655--/ $$& EcdFbFbcC 	$$((.33GB#11':&B""73	 4rD   c                 B    SU l         U R                  U5        SU l        ga  Visit a reset node.

Reset currently triggers the end of a pulse block in IBM dynamic circuits hardware
as conditional reset is performed internally using a c_if. This means that it is
possible to schedule *up to* a reset (and during its measurement pulses)
but the reset will be followed by a period of conditional indeterminism.
All resets on disjoint qubits will be collected on the same qubits to be run simultaneously.
TNr:   rZ   r4   r]   s     rB   r[   !ASAPScheduleAnalysis._visit_reset  "     26.D!#' rD   c                    ^  T R                  U5      nT R                  U5        [        U 4S jT R                  U5       5       5      nX2-   nT R	                  XU5        g)/Visit a generic node such as a gate or barrier.c              3   B   >#    U  H  nTR                   U   v   M     g 7frF   ra   rb   s     rB   re   6ASAPScheduleAnalysis._visit_generic.<locals>.<genexpr>  rg   rh   N)r   r   ri   rj   rk   r@   rS   op_durationrr   rs   s   `    rB   r\   #ASAPScheduleAnalysis._visit_generic  s]    ((. 	""4( 
:>//$:O
 
 t,rD   )r4   r:   )r   r   r   r   r   r   rM   r   rZ   r[   r\   r    rD   rB   r   r   B  sT    (z j 0147 14t 14f( (T (-7 -t -rD   r   c                   j    \ rS rSrSrS\SS4S jrS\SS4S jrS\SS4S	 jr	S\SS4S
 jr
SS jrSrg)ALAPScheduleAnalysisi  a  Dynamic circuits as-late-as-possible (ALAP) scheduling analysis pass.

This is a scheduler designed to work for the unique scheduling constraints of the dynamic circuits
backends due to the limitations imposed by hardware. This is expected to evolve over time as the
dynamic circuit backends also change.

In its current form this is similar to Qiskit's ALAP scheduler in which instructions
start as late as possible.

The primary differences are that:

* Resets and control-flow currently trigger the end of a "quantum block". The period between the end
    of the block and the next is *nondeterministic*
    ie., we do not know when the next block will begin (as we could be evaluating a classical
    function of nondeterministic length) and therefore the
    next block starts at a *relative* t=0.
* During a measurement it is possible to apply gates in parallel on disjoint qubits.
* Measurements and resets on disjoint qubits happen simultaneously and are part of the same block.
r   r"   Nc                    U R                  U5        UR                   Vs0 s H  o"U_M     nnU R                  X5        U R                  5         U R                  U R
                  S'   U R                  U R
                  S'   U$ s  snf )a  Run the ASAPSchedule pass on `dag`.

Args:
    dag (DAGCircuit): DAG to schedule.

Raises:
    TranspilerError: if the circuit is not mapped on physical qubits.
    TranspilerError: if conditional bit is added to non-supported instruction.

Returns:
    The scheduled DAGCircuit.
r   rq   )r   r   rT   _push_block_durationsr5   r   r0   r   s       rB   rM   ALAPScheduleAnalysis.run  s~     	s ,/99594$J95#(""$/3/D/D+,/3/D/D+,
 6s   BrS   c                   ^  T R                  5       n[        T R                  U5      5      n[        U 4S jU 5       5      nX#-  (       a5  T R                  (       a  T R                  5         SnOFT R                  5         O5[        [        R                  " U/U 4S jT R                   5       5      5      nT R                  R                  U5        T R                   H,  nUnT R                  U5      nXg-   nT R                  XVU5        M.     g)r   c              3   B   >#    U  H  nTR                   U   v   M     g 7frF   ra   r   s     rB   re   6ALAPScheduleAnalysis._visit_measure.<locals>.<genexpr>   r   rh   r   c              3   H   >#    U  H  nTR                   U   S    v   M     g7fr   r   r   s     rB   re   r     r   r   Nr   r   s	   `        rB   rZ   #ALAPScheduleAnalysis._visit_measure  r   rD   c                 B    SU l         U R                  U5        SU l        gr   r   r]   s     rB   r[   !ALAPScheduleAnalysis._visit_reset   r   rD   c                    ^  T R                   (       a  T R                  5         T R                  U5      nT R                  U5        [	        U 4S jT R                  U5       5       5      nX2-   nT R                  XU5        g)r   c              3   B   >#    U  H  nTR                   U   v   M     g 7frF   ra   rb   s     rB   re   6ALAPScheduleAnalysis._visit_generic.<locals>.<genexpr><  rg   rh   N)r4   rN   r   r   ri   rj   rk   r   s   `    rB   r\   #ALAPScheduleAnalysis._visit_generic/  st    
 ##))+((. 	""4( 
:>//$:O
 
 t,rD   c                   ^ ^^^ 0 nS[         [        [         [        [        4   4   S[         [        [        [        [        4   4U 4S jjn[	        T R
                  R                  5       US9n0 m0 mS[        S[        S[        [        [        [        [        4   4   S[        4U 4S jjn[        5       mS[        S[        S	[        S[        [        [        [        [        4   4   SS
4
UUUU 4S jjnU H  u  nu  nnUT;   a  M  Xq;  a6  T R                  R                   V	s0 s H  oT R                  U   _M     sn	X'   T R                  R                  US
5      n
U
bE  T R                  U    Vs/ s H  nU" X{U5      PM     nn[        U5      nU
 H  nU" X{X5        M     M  U" XvU5      nU" XvX5        M     TT l        TT l        g
s  sn	f s  snf )zJAfter scheduling of each block, pass over and push the times of all nodes.itemr"   c                    > U S   S   U S   S   * [        U S   R                  [        5      (       + TR                  U S   5      4$ )zZIterated nodes ordering by channel, time and preferring that barriers are processed
first.r   r   )rW   rX   r   r   )r  r@   s    rB   	order_ops=ALAPScheduleAnalysis._push_block_durations.<locals>.order_opsK  sN     Q
atAwzz733""47+	 rD   )keyrJ   rS   block_bit_timesc                    >^ ^ [        U U4S jTR                  U5       5       5      nTR                  U   S   nTR                  U   S   nX5-
  nXF-   nU$ )Nc              3   4   >#    U  H  nTT   U   v   M     g 7frF   r   )rc   rd   rJ   r  s     rB   re   [ALAPScheduleAnalysis._push_block_durations.<locals>._calculate_new_times.<locals>.<genexpr>]  s      _H^!7!<H^s   r   )minr   r5   r6   )	rJ   rS   r  max_block_timerr   rs   node_offsetnew_t0r@   s	   ` `     rB   _calculate_new_timesHALAPScheduleAnalysis._push_block_durations.<locals>._calculate_new_timesZ  s`     ! _HXHXY]H^ __N&&t,Q/B%%d+A.B(-K%FMrD   new_timeNc                    > TR                  U5        X4TU'   U UTR                  U5      -   4TU'   TR                  U5       H
  nX#U    U'   M     g rF   )r   r   r   )	rJ   rS   r  r  rd   new_node_start_timenew_node_stop_time	scheduledr@   s	        rB   _update_time@ALAPScheduleAnalysis._push_block_durations.<locals>._update_timeh  sf     MM$).(9%4--d33(t$ ''-.6&s+ .rD   )r	   r   r   r   sortedr6   itemsr   r   r8   r,   r   r3   r;   r   r
  r5   )r@   r  r  iterate_nodesr  r  rS   rJ   _r   
tied_nodes	tied_node	new_timesr  r  r  r  r  s   `              @@@rB   r   *ALAPScheduleAnalysis._push_block_durationsC  s    	E'5c?":; 	c3PTVYFY@Z 	 t3399;K 
	
	%
	8<S$uczBR=R8S
	
	 E		7	7	7 	7 "#tE3J'7"78		7
 	7 	7* 
D 
 y +PTPYPYP_P_)`P_1T-?-?-F*FP_)`& ++//d;J%
 &*%7%7%=%=	 )?K%=   y>!+I 8M ", .e?KU&B/ 2 !41) *as   %G3G)r4   r:   r5   r6   r   )r   r   r   r   r   r   rM   r   rZ   r[   r\   r   r   r   rD   rB   r   r     sZ    (z d 0147 14t 14f( (T (-7 -t -(T2rD   r   )*r   abcr   typingr   r   r   r   r   r	   r   r&   r   qiskit.circuitr
   r   r   r   r   r   r   "qiskit.circuit.parameterexpressionr   qiskit.convertersr   qiskit.dagcircuitr   r   qiskit.transpilerr   qiskit.transpiler.exceptionsr   qiskit.transpiler.basepassesr   8qiskit.transpiler.passes.scheduling.time_unit_conversionr   utilsr   r   r   r   r   r   rD   rB   <module>r*     sn    .  : :    T T T B , 1 $ 8 ; W B^S!3 ^SB	{-5 {-|W25 W2rD   