
    z	i@I                         S r SSKJrJrJr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JrJr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   " S S\5      rg)z+Optimize annotated operations on a circuit.    )OptionalListTupleUnion)CONTROL_FLOW_OP_NAMES)circuit_to_dagdag_to_circuit)AnnotatedOperation_canonicalize_modifiers)QuantumCircuitInstructionEquivalenceLibraryControlledGate	OperationControlFlowOp)TransformationPass)control_flow)Target)
DAGCircuit)TranspilerErrorc                   F  ^  \ rS rSrSr     SS\\   S\\   S\\\	      S\
S\
4
U 4S	 jjjrS
\4S jrS\\\
4   4S jrS\\\
4   4S jrS
\S\\\\\4   S4   4S jrS\S\\\\4   S\4S jrS\\\
4   4S jrS\S\
4S jrS\S\
4S jrS\\\
4   4S jrSrU =r$ )OptimizeAnnotated#   a   Optimization pass on circuits with annotated operations.

Implemented optimizations:

* For each annotated operation, converting the list of its modifiers to a canonical form.
  For example, consecutively applying ``inverse()``, ``control(2)`` and ``inverse()``
  is equivalent to applying ``control(2)``.

* Removing annotations when possible.
  For example, ``AnnotatedOperation(SwapGate(), [InverseModifier(), InverseModifier()])``
  is equivalent to ``SwapGate()``.

* Recursively combining annotations.
  For example, if ``g1 = AnnotatedOperation(SwapGate(), InverseModifier())`` and
  ``g2 = AnnotatedOperation(g1, ControlModifier(2))``, then ``g2`` can be replaced with
  ``AnnotatedOperation(SwapGate(), [InverseModifier(), ControlModifier(2)])``.

* Applies conjugate reduction to annotated operations. As an example,
  ``control - [P -- Q -- P^{-1}]`` can be rewritten as ``P -- control - [Q] -- P^{-1}``,
  that is, only the middle part needs to be controlled. This also works for inverse
  and power modifiers.

Ntargetequivalence_librarybasis_gatesrecursedo_conjugate_reductionc                 @  > [         TU ]  5         Xl        X l        X0l        XPl        U(       + =(       d#    U R                  SL =(       a    U R                  SL U l        U R                  (       d0  U R                  c"  1 SknU[        U R                  5      -  U l        ggg)aa  
OptimizeAnnotated initializer.

Args:
    target: Optional, the backend target to use for this pass.
    equivalence_library: The equivalence library used
        (instructions in this library will not be optimized by this pass).
    basis_gates: Optional, target basis names to unroll to, e.g. `['u3', 'cx']`
        (instructions in this list will not be optimized by this pass).
        Ignored if ``target`` is also specified.
    recurse: By default, when either ``target`` or ``basis_gates`` is specified,
        the pass recursively descends into gate definitions (and the recursion is
        not applied when neither is specified since such objects do not need to
        be synthesized). Setting this value to ``False`` precludes the recursion in
        every case.
    do_conjugate_reduction: controls whether conjugate reduction should be performed.
N>   delayresetstorebarriermeasuresnapshot)	super__init___target
_equiv_lib_basis_gates_do_conjugate_reduction_top_level_onlyset_device_insts)selfr   r   r   r   r   basic_insts	__class__s          r/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/transpiler/passes/optimization/optimize_annotated.pyr'   OptimizeAnnotated.__init__<   s    2 	-''=$#*{bt/@/@D/H/aT\\]aMa##(<WK!,s43D3D/E!ED )=#    dagc                 ,    U R                  U5      u  pU$ )zRun the OptimizeAnnotated pass on `dag`.

Args:
    dag: input dag.

Returns:
    Output dag with higher-level operations optimized.

Raises:
    TranspilerError: when something goes wrong.

)
_run_inner)r/   r5   _s      r2   runOptimizeAnnotated.runb   s     %
r4   returnc                 |   U R                   (       a4  UR                  SS9nSU;  a  [        R                  " U5      (       d  US4$ UR	                  5        H_  n[        UR                  [        5      (       d  M$  UR                  U[        R                  " U R                  UR                  5      5        Ma     U R                  U5      u  pSnU R                   (       d  U R                  U5      u  pSnU R                   (       d$  U R                  (       a  U R                  U5      u  pX=(       d    U=(       d    U4$ )z@
Optimizes annotated operations.
Returns True if did something.
F)r   	annotated)r,   	count_opsr   intersectionop_nodes
isinstanceopr   substitute_noder   
map_blocksr9   _canonicalize_recurser+   _conjugate_reduction)r/   r5   op_namesnodeopt1opt2opt3s          r2   r7   OptimizeAnnotated._run_innerr   s     }}U}3H(*3H3U3UV^3_3_Ez! LLND$''=11## ++DHHdgg> # &&s+	## c*IC##(D(D11#6IC(D(D((r4   c                    SnUR                  [        S9 H  n/ nUR                  n[        U[        5      (       a>  UR	                  UR
                  5        UR                  n[        U[        5      (       a  M>  [        U5      n[        U5      S:  a!  XSR                  l        XcR                  l        OUR                  X55        SnM     X4$ )ze
Combines recursive annotated operations and canonicalizes modifiers.
Returns True if did something.
FrB   r   T)
r@   r
   rB   rA   extend	modifiersbase_opr   lenrC   )r/   r5   did_somethingrI   rQ   curcanonical_modifierss          r2   rE   OptimizeAnnotated._canonicalize   s     LL$6L7DI''CS"455  /kk S"455 #:)"D&'!+"%$7! ##D. M 8 !!r4   c                    / n/ n0 n0 n0 n0 n[        5       n[        5       n	[        5       n
UR                  5        H  n[        UR                  U5      5      n[	        U5      XK'   [	        U5      S:X  a(  UR
                   H  nXU'   U	R                  U5        M     [        UR                  U5      5      n[	        U5      X['   [	        U5      S:X  d  M  UR
                   H  nXU'   U	R                  U5        M     M     [	        U	5      S:  Ga,  U	R                  5       nU	R                  5         U GH  nUR                  US5      =nc  M  UR                  US5      =nc  M2  UU;   d  UU;   a  M@  UU:X  a  MH  UU4U
;   a  MR  UR
                  UR
                  :w  d  UR                  UR                  :w  a  M  UR                  UR                  R                  5       :X  Ga/  UR
                   H  nSXm'   M	     UR
                   H  nSX}'   M	     UR                  U5       HH  nX;  d  M
  XK==   S-  ss'   XK   S:X  d  M   UR
                   H  nXU'   U	R                  U5        M     MJ     UR                  U5       HH  nX;  d  M
  X[==   S-  ss'   X[   S:X  d  M   UR
                   H  nXU'   U	R                  U5        M     MJ     UR                  U5        UR                  U5        UR                  U5        UR                  U5        GM  U
R                  UU45        GM     [	        U	5      S:  a  GM,  [	        U5      S:X  a  gUR                  5       nUR                  5       nUR                  5       nSUl        SUl        U H4  nUR#                  UR                  UR
                  UR                  5        M6     U H4  nUR%                  UR                  UR
                  UR                  5        M6     UR                  5        H;  nX;  d  M
  UR#                  UR                  UR
                  UR                  5        M=     UUU4$ )z
Decomposes a circuit ``A`` into 3 sub-circuits ``P``, ``Q``, ``R`` such that
``A = P -- Q -- R`` and ``R = P^{-1}``.

This is accomplished by iteratively finding inverse nodes at the front and at the back of the
circuit.
r   N   )r-   r@   listop_predecessorsrS   qargsaddop_successorscopycleargetcargsrB   inverseappendcopy_empty_likeglobal_phaseapply_operation_backapply_operation_front)r/   r5   front_block
back_block	in_degree
out_degreefront_node_for_qubitback_node_for_qubitprocessed_nodesactive_qubitschecked_node_pairsrI   predsqsuccsto_check
front_node	back_nodefront_circuitmiddle_circuitback_circuits                        r2   _conjugate_decomposition*OptimizeAnnotated._conjugate_decomposition   s    
 	
  "  %  !U LLND,,T23E!%jIO5zQA.2+!%%a( $ **401E"5zJ5zQA-1*!%%a( $ # - 1$$))+H! "6":":1d"CCJL!4!8!8D!AAIJ 0I4P * 	*.@@ ##y6*:J:Jioo:] ==ILL$8$8$::'--26,/ .&__15+. - !$ 1 1* =6%Oq0O(!3)-A>B$;$1$5$5a$8 *4	 !> !$ 3 3I >6&,1,)/14)-A=A$:$1$5$5a$8 *4	 !?  &&z2%%i0#''
3#''	2 '**J	+BCu  - 1$F {q  ++-,,.**,%&"$%!D..tww

DJJO   D..tww

DJJO  LLND*33DGGTZZT # nl::r4   rB   base_decompositionc                    Uu  p4n[        SUR                  R                  UR                  R                  / S9n[	        U5      Ul        [        SUR                  UR                  / S9nUR                  UR                  R                  -
  n[        UR                  UR                  5      n	U	R                  n
U	R                  [	        U5      XUR                   SS9  U	R                  [        XaR                  S9[        UR                  5      5        U	R                  [	        U5      XUR                   SS9  Xl        U$ )a&  
We are given an annotated-operation ``op = M [ B ]`` (where ``B`` is the base operation and
``M`` is the list of modifiers) and the "conjugate decomposition" of the definition of ``B``,
i.e. ``B = P * Q * R``, with ``R = P^{-1}`` (with ``P``, ``Q`` and ``R`` represented as
``DAGCircuit`` objects).

Let ``IQ`` denote a new custom instruction with definitions ``Q``.

We return the operation ``op_new`` which a new custom instruction with definition
``P * A * R``, where ``A`` is a new annotated-operation with modifiers ``M`` and
base gate ``IQ``.
iq)name
num_qubits
num_clbitsparams	optimized)r   r   r   T)inplace)rR   rQ   )r   rR   r   r   r	   
definitionr   qubitscomposerd   r
   rQ   range)r/   rB   r}   p_dagq_dagr_dagq_instrop_newnum_control_qubitscircr   s              r2   _conjugate_reduce_op&OptimizeAnnotated._conjugate_reduce_opA  s    1e"**"7"7BJJDYDYbd
 ,E2BMMbmmTV
  ]]RZZ-B-BBbmmR]];5!6r}}#MW[ 	 	
 	w,,Gr}}I]	
 	5!6r}}#MW[ 	 	
 !r4   c                 N   SnUR                  [        S9 H  nUR                  R                  nU R	                  U5      (       a  M1  [        UR                  SS9nU R                  U5      nUc  M[  U R                  UR                  U5      nUR                  X75        SnM     X4$ )a  
Looks for annotated operations whose base operation has a nontrivial conjugate decomposition.
In such cases, the modifiers of the annotated operation can be moved to the "middle" part of
the decomposition.

Returns the modified DAG and whether it did something.
FrO   copy_operationsT)
r@   r
   rB   rR   _skip_definitionr   r   r{   r   rC   )r/   r5   rT   rI   rR   base_dagr}   new_ops           r2   rG   &OptimizeAnnotated._conjugate_reductionj  s     LL$6L7DggooG((11)'*<*<eT%)%B%B8%L"%1!66tww@RSF''5$(M 8 !!r4   c                 T   [        U[        5      =(       a    UR                  nU(       d~  U R                  b#  U R                  R	                  UR
                  S9OUR
                  U R                  ;   nU(       d-  U R                  b!  U R                  R                  U5      (       a  gg)zA
Returns True if we should not recurse into a gate's definition.
)operation_nameTF)	rA   r   
_open_ctrlr(   instruction_supportedr   r.   r)   	has_entry)r/   rB   controlled_gate_open_ctrlinst_supporteds       r2   r   "OptimizeAnnotated._skip_definition~  s     %/r>$B$Tr}}!( <<+ 22"''2JWW 2 22 
 $//"=$//B[B[\^B_B_r4   c                    [        U[        5      (       a  U R                  UR                  5      $ U R	                  U5      (       a  g UR
                  nUc  [        SU S35      e[        USS9nU R                  U5      u  pEU(       a  [        U5      Ul        U$ ! [         a!  n[        SUR                   SU 35      UeSnAf[         a    Sn Nf = f)z
Recursively applies optimizations to op's definition (or to op.base_op's
definition if op is an annotated operation).
Returns True if did something.
Fz7OptimizeAnnotated was unable to extract definition for z: Nz)OptimizeAnnotated was unable to optimize .r   )rA   r
    _recursively_process_definitionsrR   r   r   	TypeErrorr   r   AttributeErrorr   r7   r	   )r/   rB   r   errdefinition_dagopts         r2   r   2OptimizeAnnotated._recursively_process_definitions  s     b,--88DD  $$		J !$MbTQR"STT'
EJ"oon= +>:BM
'  	!I"''RTUXTYZ  	J	s   	B 
C'CCCc                     SnUR                  5        H)  nU R                  UR                  5      nU=(       d    UnM+     X4$ )zF
Recursively handles gate definitions.
Returns True if did something.
F)r@   r   rB   )r/   r5   rT   rI   r   s        r2   rF   OptimizeAnnotated._recurse  sB    
 LLND77@C)0SM # !!r4   )r*   r.   r+   r)   r(   r,   )NNNTT)__name__
__module____qualname____firstlineno____doc__r   r   r   r   strboolr'   r   r9   r   r7   rE   r   r{   r
   r   r   rG   r   r   rF   __static_attributes____classcell__)r1   s   @r2   r   r   #   sZ   4 $(<@+/'+$F $F &&89$F d3i(	$F
 $F !%$F $FLz  !)z4'7!8 !)F"E*d*:$; "0R;R;	uZZ78$>	?R;h'$':?
JXb@b:c'	'R"5T1A+B "(9  $$9 $ $L"uZ%56 " "r4   r   N) r   typingr   r   r   r   qiskit.circuit.controlflowr   qiskit.convertersr   r	   "qiskit.circuit.annotated_operationr
   r   qiskit.circuitr   r   r   r   r   r   qiskit.transpiler.basepassesr   qiskit.transpiler.passes.utilsr   qiskit.transpiler.targetr   qiskit.dagcircuitr   qiskit.transpiler.exceptionsr   r    r4   r2   <module>r      sC    2 / / < < Z  < 7 + ( 8^"* ^"r4   