§
    º³ÙgaI  ã                   óÆ   — d Z ddlmZmZmZm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mZmZmZmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ  G d„ de¦  «        ZdS )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                   óh  ‡ — e Zd ZdZ	 	 	 	 	 ddee         dee         deee                  de	de	f
ˆ fd	„Z
d
efd„Zdeee	f         fd„Zdeee	f         fd„Zd
edeeeeef         df         fd„Zdedeeeef         defd„Zdeee	f         fd„Zdede	fd„Zdede	fd„Zdeee	f         fd„Zˆ xZS )ÚOptimizeAnnotateda@  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.

    NTÚtargetÚequivalence_libraryÚbasis_gatesÚrecurseÚdo_conjugate_reductionc                 ó  •— t          ¦   «                              ¦   «          || _        || _        || _        || _        | p| j        du o| j        du | _        | j        s)| j        €$h d£}|t          | j        ¦  «        z  | _        dS dS dS )aÙ  
        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          €ún/granary/edev/quantum/lib/python3.11/site-packages/qiskit/transpiler/passes/optimization/optimize_annotated.pyr&   zOptimizeAnnotated.__init__<   s«   ø€ õ2 	‰Œ×ÒÑÔÐàˆŒØ-ˆŒØ'ˆÔØ'=ˆÔ$à#*˜{Ðb¨tÔ/@ÀDÐ/HÐ/aÈTÌ\Ð]aÐMaˆÔàÔ#ð 	F¨¬Ð(<ØWÐWÐWˆKØ!,­s°4Ô3DÑ/EÔ/EÑ!EˆDÔÐÐð	Fð 	FÐ(<Ð(<ó    Údagc                 ó6   — |                       |¦  «        \  }}|S )z÷Run 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.   r3   Ú_s      r1   ÚrunzOptimizeAnnotated.runb   s   € ð —’ Ñ%Ô%‰ˆˆQØˆ
r2   Úreturnc                 ó  — | j         r2|                     d¬¦  «        }d|vrt          j        |¦  «        s|dfS |                     ¦   «         D ]Q}t          |j        t          ¦  «        r5|                     |t          j
        | j        |j        ¦  «        d¬¦  «         ŒR|                      |¦  «        \  }}d}| j         s|                      |¦  «        \  }}d}| j         s| j        r|                      |¦  «        \  }}||p|p|fS )zX
        Optimizes annotated operations.
        Returns True if did something.
        F)r   Ú	annotated©Úpropagate_condition)r+   Ú	count_opsr   ÚintersectionÚop_nodesÚ
isinstanceÚopr   Úsubstitute_noder   Ú
map_blocksr7   Ú_canonicalizeÚ_recurser*   Ú_conjugate_reduction)r.   r3   Úop_namesÚnodeÚopt1Úopt2Úopt3s          r1   r5   zOptimizeAnnotated._run_innerr   s3  € ð Ôð 	"Ø—}’}¨U�}Ñ3Ô3ˆHØ (Ð*Ð*Õ3HÔ3UÐV^Ñ3_Ô3_Ð*Ø˜E�zÐ!ð —L’L‘N”Nð 	ð 	ˆDÝ˜$œ'¥=Ñ1Ô1ð Ø×#Ò#Ø�,Ô1°$´(¸D¼GÑDÔDÐZ_ð $ñ ô ð øð
 ×&Ò& sÑ+Ô+‰	ˆˆTàˆØÔ#ð 	+ð Ÿš cÑ*Ô*‰IˆC�àˆØÔ#ð 	7¨Ô(Dð 	7Ø×1Ò1°#Ñ6Ô6‰IˆC�à�DÐ(˜DÐ( DÐ(Ð(r2   c                 óœ  — d}|                      t          ¬¦  «        D ]«}g }|j        }t          |t          ¦  «        r6|                     |j        ¦  «         |j        }t          |t          ¦  «        °6t          |¦  «        }t          |¦  «        dk    r||j        _        ||j        _        n| 	                    ||d¬¦  «         d}Œ¬||fS )z}
        Combines recursive annotated operations and canonicalizes modifiers.
        Returns True if did something.
        F©rA   r   r;   T)
r?   r
   rA   r@   ÚextendÚ	modifiersÚbase_opr   ÚlenrB   )r.   r3   Údid_somethingrH   rO   ÚcurÚcanonical_modifierss          r1   rD   zOptimizeAnnotated._canonicalize”   sá   € ð ˆØ—L’LÕ$6�LÑ7Ô7ð 	!ð 	!ˆDØˆIØ”'ˆCÝ˜SÕ"4Ñ5Ô5ð "Ø× Ò  ¤Ñ/Ô/Ð/Ø”k�õ ˜SÕ"4Ñ5Ô5ð "õ #:¸)Ñ"DÔ"DÐÝÐ&Ñ'Ô'¨!Ò+Ð+à"%�””Ø$7�”Ô!Ð!ð ×#Ò# D¨#À5Ð#ÑIÔIÐIØ ˆMˆMØ�MÐ!Ð!r2   c                 óŒ  — g }g }i }i }i }i }t          ¦   «         }t          ¦   «         }	t          ¦   «         }
|                     ¦   «         D ]Ø}t          |                     |¦  «        ¦  «        }t	          |¦  «        ||<   t	          |¦  «        dk    r$|j        D ]}|||<   |	                     |¦  «         Œt          |                     |¦  «        ¦  «        }t	          |¦  «        ||<   t	          |¦  «        dk    r$|j        D ]}|||<   |	                     |¦  «         ŒŒÙt	          |	¦  «        dk    �r|	                     ¦   «         }|	 	                    ¦   «          |D �]Ó}| 
                    |d¦  «        x}€Œ| 
                    |d¦  «        x}€Œ5||v s||v rŒ>||k    rŒE||f|
v rŒL|j        |j        k    s|j        |j        k    rŒm|j        |j                             ¦   «         k    �r,|j        D ]}d||<   Œ|j        D ]}d||<   Œ|                     |¦  «        D ]F}||vr@||xx         dz  cc<   ||         dk    r$|j        D ]}|||<   |	                     |¦  «         ŒŒG|                     |¦  «        D ]F}||vr@||xx         dz  cc<   ||         dk    r$|j        D ]}|||<   |	                     |¦  «         ŒŒG|                     |¦  «         |                     |¦  «         |                     |¦  «         |                     |¦  «         �Œ¼|
                     ||f¦  «         �ŒÕt	          |	¦  «        dk    �°t	          |¦  «        dk    rdS |                     ¦   «         }|                     ¦   «         }|                     ¦   «         }d|_        d|_        |D ](}|                     |j        |j        |j        ¦  «         Œ)|D ](}|                     |j        |j        |j        ¦  «         Œ)|                     ¦   «         D ],}||vr&|                     |j        |j        |j        ¦  «         Œ-|||fS )a  
        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_predecessorsrQ   ÚqargsÚaddÚop_successorsÚcopyÚclearÚgetÚcargsrA   ÚinverseÚappendÚcopy_empty_likeÚglobal_phaseÚapply_operation_backÚapply_operation_front)r.   r3   Úfront_blockÚ
back_blockÚ	in_degreeÚ
out_degreeÚfront_node_for_qubitÚback_node_for_qubitÚprocessed_nodesÚactive_qubitsÚchecked_node_pairsrH   ÚpredsÚqÚsuccsÚto_checkÚ
front_nodeÚ	back_nodeÚfront_circuitÚmiddle_circuitÚback_circuits                        r1   Ú_conjugate_decompositionz*OptimizeAnnotated._conjugate_decomposition¬   s.  € ð ˆØˆ
ð ˆ	Øˆ
ð  "ÐØ Ðõ ™%œ%ˆõ ™œˆõ !™UœUÐð —L’L‘N”Nð 	)ð 	)ˆDÝ˜×,Ò,¨TÑ2Ô2Ñ3Ô3ˆEÝ! %™jœjˆI�d‰OÝ�5‰zŒz˜QŠˆØœð )ð )�AØ.2Ð(¨Ñ+Ø!×%Ò% aÑ(Ô(Ð(Ð(Ý˜×*Ò*¨4Ñ0Ô0Ñ1Ô1ˆEÝ" 5™zœzˆJ�tÑÝ�5‰zŒz˜QŠˆØœð )ð )�AØ-1Ð'¨Ñ*Ø!×%Ò% aÑ(Ô(Ð(Ð(øõ �-Ñ Ô  1Ò$Ñ$Ø$×)Ò)Ñ+Ô+ˆHØ×ÒÑ!Ô!Ð!ð ð :Dñ :D�à"6×":Ò":¸1¸dÑ"CÔ"CÐC�JÐLØØ!4×!8Ò!8¸¸DÑ!AÔ!AÐA�IÐJØð  Ð0Ð0°IÀÐ4PÐ4PØð  Ò*Ð*Øð  	Ð*Ð.@Ð@Ð@Øð Ô# y¤Ò6Ð6¸*Ô:JÈiÌoÒ:]Ð:]Øð ”= I¤L×$8Ò$8Ñ$:Ô$:Ò:Ñ:à'Ô-ð 7ð 7˜Ø26Ð,¨QÑ/Ð/Ø&œ_ð 6ð 6˜Ø15Ð+¨AÑ.Ð.ð !$× 1Ò 1°*Ñ =Ô =ð 9ð 9˜Ø Ð6Ð6Ø% d˜O˜OœO¨qÑ0˜O˜O™OØ(¨œ°!Ò3Ð3Ø)-¬ð !9ð !9 AØ>BÐ$8¸Ñ$;Ø$1×$5Ò$5°aÑ$8Ô$8Ð$8Ð$8øð !$× 3Ò 3°IÑ >Ô >ð 9ð 9˜Ø Ð6Ð6Ø& tÐ,Ð,Ô,°Ñ1Ð,Ð,Ñ,Ø)¨$Ô/°1Ò4Ð4Ø)-¬ð !9ð !9 AØ=AÐ$7¸Ñ$:Ø$1×$5Ò$5°aÑ$8Ô$8Ð$8Ð$8øð  ×&Ò& zÑ2Ô2Ð2Ø×%Ò% iÑ0Ô0Ð0Ø#×'Ò'¨
Ñ3Ô3Ð3Ø#×'Ò'¨	Ñ2Ô2Ð2Ñ2ð '×*Ò*¨J¸	Ð+BÑCÔCÐCÑCõA �-Ñ Ô  1Ò$Ñ$õF ˆ{ÑÔ˜qÒ Ð Ø�4ð ×+Ò+Ñ-Ô-ˆØ×,Ò,Ñ.Ô.ˆØ×*Ò*Ñ,Ô,ˆØ%&ˆÔ"Ø$%ˆÔ!àð 	Pð 	PˆDØ×.Ò.¨t¬w¸¼
ÀDÄJÑOÔOÐOÐOàð 	Pð 	PˆDØ×.Ò.¨t¬w¸¼
ÀDÄJÑOÔOÐOÐOà—L’L‘N”Nð 	Uð 	UˆDØ˜?Ð*Ð*Ø×3Ò3°D´G¸T¼ZÈÌÑTÔTÐTøà˜n¨lÐ:Ð:r2   rA   Úbase_decompositionc                 óz  — |\  }}}t          d|j        j        |j        j        g ¬¦  «        }t	          |¦  «        |_        t          d|j        |j        g ¬¦  «        }|j        |j        j        z
  }t          |j        |j        ¦  «        }	|	j        }
|	                     t	          |¦  «        |
||j        …         d¬¦  «         |	 	                    t          ||j        ¬¦  «        t          |j        ¦  «        ¦  «         |	                     t	          |¦  «        |
||j        …         d¬¦  «         |	|_        |S )an  
        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)rP   rO   )r   rP   r}   r~   r	   Ú
definitionr   ÚqubitsÚcomposera   r
   rO   Úrange)r.   rA   ry   Úp_dagÚq_dagÚr_dagÚq_instrÚop_newÚnum_control_qubitsÚcircrƒ   s              r1   Ú_conjugate_reduce_opz&OptimizeAnnotated._conjugate_reduce_op@  sQ  € ð 1Ñˆˆu�eåØ "¤*Ô"7ÀBÄJÔDYÐbdð
ñ 
ô 
ˆõ ,¨EÑ2Ô2ˆÔåØ B¤M¸b¼mÐTVð
ñ 
ô 
ˆð  œ]¨R¬ZÔ-BÑBÐå˜bœm¨R¬]Ñ;Ô;ˆØ”ˆØ�ŠÝ˜5Ñ!Ô! 6Ð*<¸r¼}Ð*LÔ#MÐW[ð 	ñ 	
ô 	
ð 	
ð 	�ŠÝ w¸"¼,ÐGÑGÔGÍÈrÌ}ÑI]ÔI]ñ	
ô 	
ð 	
ð 	�ŠÝ˜5Ñ!Ô! 6Ð*<¸r¼}Ð*LÔ#MÐW[ð 	ñ 	
ô 	
ð 	
ð !ˆÔØˆr2   c                 óL  — d}|                      t          ¬¦  «        D ]ƒ}|j        j        }|                      |¦  «        s`t          |j        d¬¦  «        }|                      |¦  «        }|�3|                      |j        |¦  «        }| 	                    ||¦  «         d}Œ„||fS )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.
        FrM   ©Úcopy_operationsNT)
r?   r
   rA   rP   Ú_skip_definitionr   r‚   rx   r�   rB   )r.   r3   rR   rH   rP   Úbase_dagry   Únew_ops           r1   rF   z&OptimizeAnnotated._conjugate_reductioni  s´   € ð ˆØ—L’LÕ$6�LÑ7Ô7ð 	)ð 	)ˆDØ”g”oˆGØ×(Ò(¨Ñ1Ô1ð )Ý)¨'Ô*<ÈeÐTÑTÔT�Ø%)×%BÒ%BÀ8Ñ%LÔ%LÐ"Ø%Ð1Ø!×6Ò6°t´wÐ@RÑSÔS�FØ×'Ò'¨¨fÑ5Ô5Ð5Ø$(�MøØ�MÐ!Ð!r2   c                 óö   — t          |t          ¦  «        o|j        }|sZ| j        � | j                             |j        ¬¦  «        n|j        | j        v }|s!| j        �| j                             |¦  «        rdS dS )zQ
        Returns True if we should not recurse into a gate's definition.
        N)Úoperation_nameTF)	r@   r   Ú
_open_ctrlr'   Úinstruction_supportedr|   r-   r(   Ú	has_entry)r.   rA   Úcontrolled_gate_open_ctrlÚinst_supporteds       r1   r‘   z"OptimizeAnnotated._skip_definition}  s�   € õ %/¨rµ>Ñ$BÔ$BÐ$TÀrÄ}Ð!Ø(ð 	ð ”<Ð+ð ”×2Ò2À"Ä'Ð2ÑJÔJÐJà”W Ô 2Ð2ð ð
 ð  $¤/Ð"=À$Ä/×B[ÒB[Ð\^ÑB_ÔB_Ð"=Ø�tØˆur2   c                 óÀ  — t          |t          ¦  «        r|                      |j        ¦  «        S |                      |¦  «        rdS 	 |j        }n:# t          $ r }t          d|j        › d|› �¦  «        |‚d}~wt          $ r d}Y nw xY w|€t          d|› d�¦  «        ‚t          |d¬¦  «        }|                      |¦  «        \  }}|rt          |¦  «        |_        |S )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�   )r@   r
   Ú _recursively_process_definitionsrP   r‘   r‚   Ú	TypeErrorr   r|   ÚAttributeErrorr   r5   r	   )r.   rA   r‚   ÚerrÚdefinition_dagÚopts         r1   r�   z2OptimizeAnnotated._recursively_process_definitions�  s&  € õ �bÕ,Ñ-Ô-ð 	EØ×8Ò8¸¼ÑDÔDÐDà× Ò  Ñ$Ô$ð 	Ø�5ð		àœˆJˆJøÝð 	ð 	ð 	Ý!ØZÈ"Ì'ÐZÐZÐUXÐZÐZñô àðøøøøõ ð 	ð 	ð 	àˆJˆJˆJð	øøøð ÐÝ!Ð"SÈbÐ"SÐ"SÐ"SÑTÔTÐTå'¨
ÀEÐJÑJÔJˆØ"Ÿošo¨nÑ=Ô=Ñˆ˜àð 	;õ +¨>Ñ:Ô:ˆBŒMàˆ
s   ÁA Á
BÁA5Á5BÂBc                 óx   — d}|                      ¦   «         D ] }|                      |j        ¦  «        }|p|}Œ!||fS )z^
        Recursively handles gate definitions.
        Returns True if did something.
        F)r?   r�   rA   )r.   r3   rR   rH   r¢   s        r1   rE   zOptimizeAnnotated._recurseµ  sL   € ð
 ˆà—L’L‘N”Nð 	1ð 	1ˆDØ×7Ò7¸¼Ñ@Ô@ˆCØ)Ð0¨SˆMˆMà�MÐ!Ð!r2   )NNNTT)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   ÚstrÚboolr&   r   r7   r   r5   rD   r   rx   r
   r   r�   rF   r‘   r�   rE   Ú__classcell__)r0   s   @r1   r   r   #   s  ø€ € € € € ðð ð4 $(Ø<@Ø+/ØØ'+ð$Fð $Fà˜Ô ð$Fð &Ð&8Ô9ð$Fð ˜d 3œiÔ(ð	$Fð
 ð$Fð !%ð$Fð $Fð $Fð $Fð $Fð $FðL�zð ð ð ð ð  )  z°4Ð'7Ô!8ð  )ð  )ð  )ð  )ðD" E¨*°dÐ*:Ô$;ð "ð "ð "ð "ð0R;ØðR;à	ˆu�Z ¨ZÐ7Ô8¸$Ð>Ô	?ðR;ð R;ð R;ð R;ðh'Ø$ð'Ø:?À
ÈJÐXbÐ@bÔ:cð'à	ð'ð 'ð 'ð 'ðR"¨5°¸TÐ1AÔ+Bð "ð "ð "ð "ð( 9ð °ð ð ð ð ð$$°9ð $Àð $ð $ð $ð $ðL"˜u Z°Ð%5Ô6ð "ð "ð "ð "ð "ð "ð "ð "r2   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   © r2   r1   ú<module>r¶      s^  ðð 2Ð 1à /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /Ð /à <Ð <Ð <Ð <Ð <Ð <Ø <Ð <Ð <Ð <Ð <Ð <Ð <Ð <Ø ZÐ ZÐ ZÐ ZÐ ZÐ ZÐ ZÐ Zðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð <Ð ;Ð ;Ð ;Ð ;Ð ;Ø 7Ð 7Ð 7Ð 7Ð 7Ð 7Ø +Ð +Ð +Ð +Ð +Ð +Ø (Ð (Ð (Ð (Ð (Ð (Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8ð]"ð ]"ð ]"ð ]"ð ]"Ð*ñ ]"ô ]"ð ]"ð ]"ð ]"r2   