
    i3                     *   S r SSKrSSKJrJrJrJrJr  SSKJ	r	  SSK
JrJr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S
KJr  \\/\\SS4   4   rS\S\\SS4   4S jr\\\SS4   \\\\   S4   \\\\   \\   4   4   r " S S\5      r g)z(Utility functions for scheduling passes.    N)Callable	GeneratorOptionalTupleUnion)	lru_cache)ControlFlowOpMeasureReset	Parameter)
DAGCircuit	DAGOpNode)InstructionDurationsInstructionDurationsType)Target)TranspilerError)Backenddagreturnc           	   #     ^ ^	^
^^^#    S[         S[        4S jmS[         S[        4S jm
[        SS9S[         S[        [            S[        [            S[        4U
UU 4S	 jj5       m	T R	                  5       nU(       Gag  Un[        5       n/ n/ n/ m/ mS
nU H  nXc;   a  UR                  U5        M  T" U5      (       a4  SnT R                  U5      nU[        U5      -  nTR                  U5        M\  T
" U5      (       a4  SnT R                  U5      nU[        U5      -  nTR                  U5        M  UR                  U5        M     / nU HG  nT R                  U5      n[        U	UU4S jU 5       5      (       a  Uv   M6  UR                  U5        MI     UnT H  nUv   M	     T H  nUv   M	     U(       d  U H  nUv   M	     OUR                  U5        UnU(       a  GMg  T	R                  5         g7f)z{Yield nodes such that they are sorted into groups of blocks that minimize synchronization.

Measurements are also grouped.
noder   c                 B    [        U R                  [        [        45      $ )z"Does this node need to be grouped?)
isinstanceopr   r
   r   s    o/home/james-whalen/.local/lib/python3.13/site-packages/qiskit_ibm_runtime/transpiler/passes/scheduling/utils.py_is_grouped_measure1block_order_op_nodes.<locals>._is_grouped_measure'   s    $''E7#344    c                 6    [        U R                  [        5      $ )z*Does this node trigger the end of a block?)r   r   r	   r   s    r   _is_block_trigger/block_order_op_nodes.<locals>._is_block_trigger+   s    $''=11r   i    )maxsizegrouped_measureblock_triggersc                    > U H  nTR                  X5      (       d  M    g   U H  nTR                  X5      (       d  M    g   T" U 5      =(       d    T" U 5      $ )zShould we emit this node?T)is_predecessor)r   r$   r%   measureblock_triggerr!   r   r   s        r   _emit#block_order_op_nodes.<locals>._emit/   s[     'G!!$00 ' ,M!!$66 , #4(C,=d,CCr   FTc              3      >#    U  H8  n[        U[        5      (       d  M  T" U[        T5      [        T5      5      v   M:     g 7fN)r   r   tuple).0
descendantr*   yield_block_triggersyield_measuress     r   	<genexpr>'block_order_op_nodes.<locals>.<genexpr>f   s<      "2Jj)4 Vj%"7?S9TUU"2s
   A#AN)r   boolr   r   topological_op_nodessetappenddescendantsanyextendcache_clear)r   
next_nodes
curr_nodesnext_nodes_setto_pushblock_breakr   node_descendantsnew_to_pushr*   r!   r   r1   r2   s   `        @@@@@r   block_order_op_nodesrD   !   s     5) 5 52	 2d 2 tDDy)D i(D 
	D D D  ))+J


!D %!!$' #4(("#&??4#8 #&6"77%%d+ #4(("#&??4#8 #&6"77$++D1 t$1 4 D"t4 "2  
 
""4(   #DJ # )DJ ) 
   	z"
 *B 
s   GG7&G7c                   @  ^  \ rS rSrSrSrSr   SS\\   S\	S\
4U 4S	 jjjr\S
\SS 4S j5       r\S\SS 4S j5       r SS\\   S\	SS 4U 4S jj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S4S jrS\S\\\4   4S jrS\S\S\SS4S jrS\4S jrSrU =r$ )"DynamicCircuitInstructionDurations   a;  For dynamic circuits the IBM Qiskit backend currently
reports instruction durations that differ compared with those
required for the legacy Qobj-based path. For now we use this
class to report updated InstructionDurations.
TODO: This would be mitigated by a specialized Backend/Target for
dynamic circuit backends.
   @   Ninstruction_durationsdtenable_patchingc                 `   > [         R                  " S[        SS9  X0l        [        TU ]  XS9  g)z&Dynamic circuit instruction durations.a  The DynamicCircuitInstructionDurations class is deprecated as of qiskit_ibm_runtime v0.43.0 and will be removed in a future release. If you are using one of the scheduling passes defined in qiskit_ibm_runtime, provide a `target` instance instead. ex: PadDelay(target=backend.target).   )
stacklevel)rJ   rK   N)warningswarnDeprecationWarning_enable_patchingsuper__init__)selfrJ   rK   rL   	__class__s       r   rU   +DynamicCircuitInstructionDurations.__init__   s7     	3 		
 !0/DLr   backendr   c                 8    U R                  UR                  5      $ )zConstruct a :class:`DynamicInstructionDurations` object from the backend.
Args:
    backend: backend from which durations (gate lengths) and dt are extracted.
Returns:
    DynamicInstructionDurations: The InstructionDurations constructed from backend.
)from_targettarget)clsrY   s     r   from_backend/DynamicCircuitInstructionDurations.from_backend   s     w~~..r   r\   c                     UR                  5       R                  n/ nUR                  5        H  u  pEU/ UQUQ7/-  nM      UR                  nU " X6S9$ ! [         a    Sn Nf = f)zConstruct a :class:`DynamicInstructionDurations` object from the target.
Args:
    target: target from which durations (gate lengths) and dt are extracted.
Returns:
    DynamicInstructionDurations: The InstructionDurations constructed from backend.
NrK   )	durationsduration_by_name_qubitsitemsrK   AttributeError)r]   r\   instruction_durations_dictrJ   	instr_keyinstr_valuerK   s          r   r[   .DynamicCircuitInstructionDurations.from_target   s     &,%5%5%7%O%O" "&@&F&F&H"I!&@	&@K&@%AA! 'I	B (00  	B	s   A A#"A#inst_durationsc                   > [         TU ]  XS9  U R                  (       a  Uc  U $ [        U[        5      (       a*  UR                  5        H  nU R                  U5        M     U $ U H  u  pEpgn[        U[        5      (       a  U/n[        U[        [        45      (       a  U/nUc  USS4nO)Uc  U[        U5      S4nOU[        U5      [        U5      4nU R                  U5        M     U $ )a  Update self with inst_durations (inst_durations overwrite self). Overrides the default
durations for certain hardcoded instructions.

Args:
    inst_durations: Instruction durations to be merged into self (overwriting self).
    dt: Sampling duration in seconds of the target backend.

Returns:
    InstructionDurations: The updated InstructionDurations.

Raises:
    TranspilerError: If the format of instruction_durations is invalid.
ra   N)
rT   updaterS   r   r   keys_patch_instructionintfloatr.   )	rV   rj   rK   keynamequbits_
parametersrW   s	           r   rl   )DynamicCircuitInstructionDurations.update   s    $ 	~-$$(>K
 n&:;;%**,'', -& ! 3A.aQfc**$XFj3,77",J>t,C'v5Cvj0ABC'', 3A  r   rq   c                 n    US   nUS:X  a  U R                  U5        gUS:X  a  U R                  U5        gg)z(Dispatcher logic for instruction patchesr   r(   resetN)_patch_measurement_patch_reset)rV   rq   rr   s      r   rn   5DynamicCircuitInstructionDurations._patch_instruction   s;    1v9##C(W_c" r   c                     U R                  U5      u  p#US:w  a  U R                  X#S5      nU R                  5       nX R                  -   U-   nUS:w  a  U R                  USU5      nU R	                  XU5        g)z$Convert duration to dt and patch keyrK   N)_get_duration_convert_unit_get_odd_cycle_correctionMEASURE_PATCH_CYCLES
_patch_key)rV   rq   prev_durationunitodd_cycle_correctionnew_durations         r   _convert_and_patch_key9DynamicCircuitInstructionDurations._convert_and_patch_key  sz    "0054< ..}DIM#==?$'@'@@CWW4<--lD$GL40r   c                 Z    U R                  U5        U R                  SUS   US   45        g)zrPatch measurement duration by extending duration by 160dt as temporarily
required by the dynamic circuit backend.
rx      rN   N)r   rz   )rV   rq   s     r   ry   5DynamicCircuitInstructionDurations._patch_measurement  s/     	##C(7CFCF34r   c                     SUS   US   4n U R                  U5      u  p4U R                  XU5        g! [         a    U R                  U5         gf = f)zxPatch reset duration by extending duration by measurement patch as temporarily
required by the dynamic circuit backend.
r(   r   rN   N)r}   r   KeyErrorr   )rV   rq   measure_keymeasure_durationr   s        r   rz   /DynamicCircuitInstructionDurations._patch_reset  s\     !#a&#a&1	-%)%7%7%D"OOC48 	-'',	-s   %3 AAc                     US   c  US   c  U R                   US      nU$ US   c  U R                  US   US   4   nU$ U R                  U   nU$ )Handling for the complicated structure of this class.

TODO: This class implementation should be simplified in Qiskit. Too many edge cases.
r   rN   r   duration_by_namerc   duration_by_name_qubits_params)rV   rq   durations      r   r}   0DynamicCircuitInstructionDurations._get_duration'  sv    
 q6>c!fn,,SV4H
 	 V^33SVSV4DEH  ::3?Hr   r   r   c                     US   c  US   c  X#4U R                   US   '   OUS   c  X#4U R                  US   US   4'   X#4U R                  U'   g)r   r   NrN   r   r   )rV   rq   r   r   s       r   r   -DynamicCircuitInstructionDurations._patch_key4  sh    
 q6>c!fn-5,<D!!#a&)V^>F=MD((#a&#a&)9:4<3C++C0r   c                     SnSn U R                  XS5      nUS:  a  US-  (       a  U R                  $ g! [         a"    [        R                  " SU SU S35        Sn NHf = f)	zDetermine the amount of the odd cycle correction to apply
For devices with short gates with odd lenghts we add an extra 16dt to the measurement

TODO: Eliminate the need for this correction
sxr   rK   zNo z gate found for zR for detection of short odd gate lengths, default measurement timing will be used.rH       )getr   rP   rQ   MEASURE_PATCH_ODD_OFFSET)rV   	key_pulse	key_qubitkey_durations       r   r   <DynamicCircuitInstructionDurations._get_odd_cycle_correction@  s     			88I$?L #,"3000  	MMi[ 0 <S S L	s   5 )A! A!)rS   )NNTr-   )__name__
__module____qualname____firstlineno____doc__r   r   r   r   rp   r5   rU   classmethodr   r^   r   r[   rl   InstrKeyrn   r   ry   rz   r   ro   strr}   r   r   __static_attributes____classcell__)rW   s   @r   rF   rF      sh    ! EI $	M'(@AM M 	M M* 	/7 	//S 	/ 	/ 1 1,P 1 1& OS.&'?@.FK.	-. .`#h #4 #
1( 
1t 
15h 54 5- -T - eCHo 
Dh 
D# 
DS 
DT 
D3  r   rF   )!r   rP   typingr   r   r   r   r   	functoolsr   qiskit.circuitr	   r
   r   r   qiskit.dagcircuitr   r   'qiskit.transpiler.instruction_durationsr   r   qiskit.transpiler.targetr   qiskit.transpiler.exceptionsr   qiskit.providersr   BlockOrderingCallableTyperD   r   ro   r   rF    r   r   <module>r      s    /  > >  C C 3 , 8 $ %j\9Yd=R3S%ST aj aYy$7L-M aH 	#tT/	#uSz4
 	#uSz5+
+,.G)= Gr   