§
    º³Ùgþ5  ã                   óÊ   — d Z ddlZddlZddlZddlmZmZmZ ddl	m
Z
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 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$Dynamical Decoupling insertion pass.é    N)ÚGateÚDelayÚReset)ÚIGateÚUGateÚU3Gate)Ú	DAGOpNodeÚ	DAGInNode)Úmatrix_equal)ÚOneQubitEulerDecomposer)ÚTransformationPass)ÚTranspilerError)ÚInstructionDurations)ÚOptimize1qGates)Údeprecate_funcc                   ól   ‡ — e Zd ZdZ edd¬¦  «        	 dˆ fd„	¦   «         Zd„ Zd	„ Zd
ede	de
fd„Zˆ xZS )ÚDynamicalDecouplingaÜ  Dynamical decoupling insertion pass.

    This pass works on a scheduled, physical circuit. It scans the circuit for
    idle periods of time (i.e. those containing delay instructions) and inserts
    a DD sequence of gates in those spots. These gates amount to the identity,
    so do not alter the logical action of the circuit, but have the effect of
    mitigating decoherence in those idle periods.

    As a special case, the pass allows a length-1 sequence (e.g. [XGate()]).
    In this case the DD insertion happens only when the gate inverse can be
    absorbed into a neighboring gate in the circuit (so we would still be
    replacing Delay with something that is equivalent to the identity).
    This can be used, for instance, as a Hahn echo.

    This pass ensures that the inserted sequence preserves the circuit exactly
    (including global phase).

    .. plot::
       :alt: Output from the previous code.
       :include-source:

        import numpy as np
        from qiskit.circuit import QuantumCircuit
        from qiskit.circuit.library import XGate
        from qiskit.transpiler import PassManager, InstructionDurations
        from qiskit.transpiler.passes import ALAPSchedule, DynamicalDecoupling
        from qiskit.visualization import timeline_drawer

        # Because the legacy passes do not propagate the scheduling information correctly, it is
        # necessary to run a no-op "re-schedule" before the output circuits can be drawn.
        def draw(circuit):
            from qiskit import transpile

            scheduled = transpile(
                circuit,
                optimization_level=0,
                instruction_durations=InstructionDurations(),
                scheduling_method="alap",
            )
            return timeline_drawer(scheduled)

        circ = QuantumCircuit(4)
        circ.h(0)
        circ.cx(0, 1)
        circ.cx(1, 2)
        circ.cx(2, 3)
        circ.measure_all()
        durations = InstructionDurations(
            [("h", 0, 50), ("cx", [0, 1], 700), ("reset", None, 10),
             ("cx", [1, 2], 200), ("cx", [2, 3], 300),
             ("x", None, 50), ("measure", None, 1000)]
        )
        # balanced X-X sequence on all qubits
        dd_sequence = [XGate(), XGate()]
        pm = PassManager([ALAPSchedule(durations),
                          DynamicalDecoupling(durations, dd_sequence)])
        circ_dd = pm.run(circ)
        draw(circ_dd)

        # Uhrig sequence on qubit 0
        n = 8
        dd_sequence = [XGate()] * n
        def uhrig_pulse_location(k):
            return np.sin(np.pi * (k + 1) / (2 * n + 2)) ** 2
        spacing = []
        for k in range(n):
            spacing.append(uhrig_pulse_location(k) - sum(spacing))
        spacing.append(1 - sum(spacing))
        pm = PassManager(
            [
                ALAPSchedule(durations),
                DynamicalDecoupling(durations, dd_sequence, qubits=[0], spacing=spacing),
            ]
        )
        circ_dd = pm.run(circ)
        draw(circ_dd)
    zšInstead, use :class:`~.PadDynamicalDecoupling`, which performs the same function but requires scheduling and alignment analysis passes to run prior to it.z1.1.0)Úadditional_msgÚsinceNTc                 ó*  •— t          ¦   «                              ¦   «          || _        || _        || _        || _        || _        || _        |�C|                     ¦   «         | _        |D ])}|j	        |j
        vrt          |j	        › d�¦  «        ‚Œ(dS dS )aÈ  Dynamical decoupling initializer.

        Args:
            durations (InstructionDurations): Durations of instructions to be
                used in scheduling.
            dd_sequence (list[Gate]): sequence of gates to apply in idle spots.
            qubits (list[int]): physical qubits on which to apply DD.
                If None, all qubits will undergo DD (when possible).
            spacing (list[float]): a list of spacings between the DD gates.
                The available slack will be divided according to this.
                The list length must be one more than the length of dd_sequence,
                and the elements must sum to 1. If None, a balanced spacing
                will be used [d/2, d, d, ..., d, d, d/2].
            skip_reset_qubits (bool): if True, does not insert DD on idle
                periods that immediately follow initialized/reset qubits (as
                qubits in the ground state are less susceptible to decoherence).
            target (Target): The :class:`~.Target` representing the target backend, if both
                  ``durations`` and this are specified then this argument will take
                  precedence and ``durations`` will be ignored.
        Nz. in dd_sequence is not supported in the target)ÚsuperÚ__init__Ú
_durationsÚ_dd_sequenceÚ_qubitsÚ_spacingÚ_skip_reset_qubitsÚ_targetÚ	durationsÚnameÚoperation_namesr   )	Úselfr   Údd_sequenceÚqubitsÚspacingÚskip_reset_qubitsÚtargetÚgateÚ	__class__s	           €ún/granary/edev/quantum/lib/python3.11/site-packages/qiskit/transpiler/passes/scheduling/dynamical_decoupling.pyr   zDynamicalDecoupling.__init__n   s¶   ø€ õ< 	‰Œ×ÒÑÔÐØ#ˆŒØ'ˆÔØˆŒØˆŒØ"3ˆÔØˆŒØÐØ$×.Ò.Ñ0Ô0ˆDŒOØ#ð ð �Ø”9 FÔ$:Ð:Ð:Ý)Øœ9ÐTÐTÐTñô ð ð ;ð Ððð ó    c           	      óh  ‡"— t          |j        ¦  «        dk    s|j                             dd¦  «        €t          d¦  «        ‚|j        €t          d¦  «        ‚|                      |¦  «        }t          | j        ¦  «        }d}|dk    r¼|dz  dk    rt          d¦  «        ‚t          j        d¦  «        }| j        D ])}| 	                    | 
                    ¦   «         ¦  «        }Œ*t          |t          ¦   «          
                    ¦   «         d	¬
¦  «        st          d¦  «        ‚t          j        |d         d         ¦  «        }| j        €4t          t!          |                     ¦   «         ¦  «        ¦  «        | _        nt          | j        ¦  «        | _        | j        rFt'          | j        ¦  «        dk    st)          d„ | j        D ¦   «         ¦  «        rt          d¦  «        ‚n d|z  }|dz  }|g|g|dz
  z  z   |gz   | _        t+          | j        ¦  «        D ]>}	| j        D ]4}|                      ||	¦  «        s| j                             |	¦  «          nŒ5Œ?i }
| j        D ]f}d}t1          | j        ¦  «        D ]H\  }}|                     ¦   «         }|| j        |<   |                     ||¦  «        |_        ||j        z  }ŒI||
|<   Œg|                     ¦   «         }|                     ¦   «         D �]½}t9          |j        t<          ¦  «        s)|                     |j        |j         |j!        d¬¦  «         ŒF|j         d         }| "                    |¦  «        j#        }|| j        vr)|                     |j        |j         |j!        d¬¦  «         ŒŸtI          | %                    |¦  «        ¦  «        }tI          | &                    |¦  «        ¦  «        }| j'        rYt9          |tP          ¦  «        st9          |j        tR          ¦  «        r*|                     |j        |j         |j!        d¬¦  «         �ŒC|
|         }|j        j        |z
  Š"‰"dk    r*|                     |j        |j         |j!        d¬¦  «         �ŒŠ|dk    �r_| j        d          *                    ¦   «          
                    ¦   «         }tW          ¦   «          ,                    |¦  «        \  }}}}t9          |tZ          ¦  «        rZt9          |j        t\          t^          f¦  «        r9|j        j0        \  }}}tc          j2        ||||||¦  «        |j        _0        ||z  }n™t9          |tZ          ¦  «        rZt9          |j        t\          t^          f¦  «        r9|j        j0        \  }}}tc          j2        ||||||¦  «        |j        _0        ||z  }n*|                     |j        |j         |j!        d¬¦  «         �Œðˆ"fd„| j        D ¦   «         }‰"t'          |¦  «        z
  }tg          t          |¦  «        dz
  dz  ¦  «        } || xx         |z  cc<   ti          j5        || j        ¦  «        D ]L\  }!}|!dk    r&|                     t=          |!¦  «        |gd¬¦  «         |�|                     ||gd¬¦  «         ŒM|j6        |z   |_6        �Œ¿|S )aJ  Run the DynamicalDecoupling pass on dag.

        Args:
            dag (DAGCircuit): a scheduled DAG.

        Returns:
            DAGCircuit: equivalent circuit with delays interrupted by DD,
                where possible.

        Raises:
            TranspilerError: if the circuit is not mapped on physical qubits.
        é   ÚqNz"DD runs on physical circuits only.z#DD runs after circuit is scheduled.r   é   z8DD sequence must contain an even number of gates (or 1).T)Úignore_phasez4The DD sequence does not make an identity operation.c              3   ó"   K  — | ]
}|d k     V — ŒdS )r   N© )Ú.0Úas     r*   ú	<genexpr>z*DynamicalDecoupling.run.<locals>.<genexpr>Â   s&   è è € Ð-KÐ-K¸¨a°!ªeÐ-KÐ-KÐ-KÐ-KÐ-KÐ-Kr+   zRThe spacings must be given in terms of fractions of the slack period and sum to 1.F)Úcheckc                 ó4   •— g | ]}t          ‰|z  ¦  «        ‘ŒS r2   )Úint)r3   r4   Úslacks     €r*   ú
<listcomp>z+DynamicalDecoupling.run.<locals>.<listcomp>  s#   ø€ Ð:Ð:Ð: q•C˜ ™	‘N”NÐ:Ð:Ð:r+   )7ÚlenÚqregsÚgetr   ÚdurationÚ_update_inst_durationsr   ÚnpÚeyeÚdotÚ	to_matrixr   r   Úangler   ÚsetÚrangeÚ
num_qubitsr   ÚsumÚanyÚlistÚ$_DynamicalDecoupling__gate_supportedÚdiscardÚ	enumerateÚ
to_mutableÚcopy_empty_likeÚtopological_op_nodesÚ
isinstanceÚopr   Úapply_operation_backÚqargsÚcargsÚfind_bitÚindexÚnextÚpredecessorsÚ
successorsr   r
   r   Úinverser   Úangles_and_phaser	   r   r   Úparamsr   Ú
compose_u3r8   Ú	itertoolsÚzip_longestÚglobal_phase)#r"   Údagr   Ú
num_pulsesÚsequence_gphaseÚnoopr(   ÚmidÚendÚqargÚindex_sequence_duration_mapÚphysical_qubitÚdd_sequence_durationrW   Únew_dagÚndÚ	dag_qubitÚpredÚsuccÚu_invÚthetaÚphiÚlamÚphaseÚtheta_rÚphi_rÚlam_rÚtheta_lÚphi_lÚlam_lÚtausÚunused_slackÚmiddle_indexÚtaur9   s#                                     @r*   ÚrunzDynamicalDecoupling.run›   s¸  ø€ õ ˆsŒy‰>Œ>˜QÒÐ #¤)§-¢-°°TÑ":Ô":Ð"BÝ!Ð"FÑGÔGÐGàŒ<ÐÝ!Ð"GÑHÔHÐHà×/Ò/°Ñ4Ô4ˆ	å˜Ô*Ñ+Ô+ˆ
ØˆØ˜Š?ˆ?Ø˜A‰~ Ò"Ð"Ý%Ð&`ÑaÔaÐaÝ”6˜!‘9”9ˆDØÔ)ð 2ð 2�Ø—x’x §¢Ñ 0Ô 0Ñ1Ô1��Ý ¥e¡g¤g×&7Ò&7Ñ&9Ô&9ÈÐMÑMÔMð ^Ý%Ð&\Ñ]Ô]Ð]Ý œh t¨A¤w¨q¤zÑ2Ô2ˆOàŒ<ÐÝ�u S§^¢^Ñ%5Ô%5Ñ6Ô6Ñ7Ô7ˆDŒLˆLå˜tœ|Ñ,Ô,ˆDŒLàŒ=ð 		EÝ�4”=Ñ!Ô! QÒ&Ð&­#Ð-KÐ-K¸T¼]Ð-KÑ-KÔ-KÑ*KÔ*KÐ&Ý%ð8ñô ð ð 'ð �j‘.ˆCØ˜‘'ˆCØ ˜E S E¨Z¸!©^Ñ$<Ñ<À¸uÑDˆDŒMå˜œÑ&Ô&ð 	ð 	ˆDØÔ)ð ð �Ø×,Ò,¨T°4Ñ8Ô8ð Ø”L×(Ò(¨Ñ.Ô.Ð.Ø�Eðøð ')Ð#Ø"œlð 	Oð 	OˆNØ#$Ð Ý(¨Ô):Ñ;Ô;ð 6ð 6‘��tØ—’Ñ(Ô(�Ø+/�Ô! %Ñ(Ø )§¢¨d°NÑ CÔ C�”à$¨¬Ñ5Ð$Ð$Ø:NÐ'¨Ñ7Ð7à×%Ò%Ñ'Ô'ˆà×*Ò*Ñ,Ô,ð :	Jñ :	JˆBÝ˜bœe¥UÑ+Ô+ð Ø×,Ò,¨R¬U°B´H¸b¼hÈeÐ,ÑTÔTÐTØàœ œˆIØ Ÿ\š\¨)Ñ4Ô4Ô:ˆNØ T¤\Ð1Ð1Ø×,Ò,¨R¬U°B´H¸b¼hÈeÐ,ÑTÔTÐTØå˜×(Ò(¨Ñ,Ô,Ñ-Ô-ˆDÝ˜Ÿš rÑ*Ô*Ñ+Ô+ˆDØÔ&ð Ý˜d¥IÑ.Ô.ð µ*¸T¼WÅeÑ2LÔ2Lð Ø×0Ò0°´¸¼À"Ä(ÐRWÐ0ÑXÔXÐXÙà#>¸~Ô#NÐ Ø”E”NÐ%9Ñ9ˆEØ˜ŠzˆzØ×,Ò,¨R¬U°B´H¸b¼hÈeÐ,ÑTÔTÐTÙà˜QŠ‰ØÔ)¨!Ô,×4Ò4Ñ6Ô6×@Ò@ÑBÔB�Ý)@Ñ)BÔ)B×)SÒ)SÐTYÑ)ZÔ)ZÑ&��s˜C å˜d¥IÑ.Ô.ð µ:¸d¼gÍÍvÀÑ3WÔ3Wð Ø,0¬G¬NÑ)�G˜U EÝ%4Ô%?Ø ¨¨u°c¸3ñ&ô &�D”G”Nð $ uÑ,�O�Oå ¥iÑ0Ô0ð 	µZÀÄÍ%ÕQWÈÑ5YÔ5Yð 	Ø,0¬G¬NÑ)�G˜U EÝ%4Ô%?Ø˜s C¨°%¸ñ&ô &�D”G”Nð $ uÑ,�O�Oð ×0Ò0°´¸¼À"Ä(ÐRWÐ0ÑXÔXÐXÙð ;Ð:Ð:Ð:¨D¬MÐ:Ñ:Ô:ˆDØ ¥3 t¡9¤9Ñ,ˆLÝ¥ D¡	¤	¨A¡°Ñ2Ñ3Ô3ˆLØ�ÐÐÔ ,Ñ.ÐÐÑå&Ô2°4¸Ô9JÑKÔKð Qð Q‘	��TØ˜’7�7Ø×0Ò0µ°s±´¸i¸[ÐPUÐ0ÑVÔVÐVØÐ#Ø×0Ò0°¸	°{È%Ð0ÑPÔPÐPøà#*Ô#7¸/Ñ#IˆGÔ Ñ àˆr+   c           	      ó  — t          ¦   «         }|j        r¾g }t          j        ¦   «         5  t          j        dt
          ¬¦  «         |j                             ¦   «         D ]@\  }}|                     ¦   «         D ]&\  \  }}}|                     ||||j        f¦  «         Œ'ŒA	 ddd¦  «         n# 1 swxY w Y   | 	                    ||j
        ¦  «         | j        �/| 	                    | j        t          | j        dd¦  «        ¦  «         |S )aU  Update instruction durations with circuit information. If the dag contains gate
        calibrations and no instruction durations were provided through the target or as a
        standalone input, the circuit calibration durations will be used.
        The priority order for instruction durations is: target > standalone > circuit.
        Úignore)ÚactionÚcategoryNÚdt)r   Ú_calibrations_propÚwarningsÚcatch_warningsÚsimplefilterÚDeprecationWarningÚitemsÚappendr>   Úupdater…   r   Úgetattr)	r"   rb   Úcirc_durationsÚcal_durationsr(   Ú	gate_calsr$   Ú
parametersÚschedules	            r*   r?   z*DynamicalDecoupling._update_inst_durations  sv  € õ .Ñ/Ô/ˆàÔ!ð 		DØˆMÝÔ(Ñ*Ô*ð \ð \ÝÔ%¨XÕ@RÐSÑSÔSÐSð (+Ô'=×'CÒ'CÑ'EÔ'Eð \ð \‘O�D˜)Ø:C¿/º/Ñ:KÔ:Kð \ð \Ñ6Ñ,˜ ¨hØ%×,Ò,¨d°F¸JÈÔHYÐ-ZÑ[Ô[Ð[Ð[ð\ð\ð	\ð \ð \ñ \ô \ð \ð \ð \ð \ð \ð \øøøð \ð \ð \ð \ð ×!Ò! -°Ô1BÑCÔCÐCàŒ?Ð&Ø×!Ò! $¤/µ7¸4¼?ÈDÐRVÑ3WÔ3WÑXÔXÐXàÐs   «A6B.Â.B2Â5B2r(   rh   Úreturnc                 ó\   — | j         �"| j                              |j        |f¬¦  «        rdS dS )z/A gate is supported on the qubit (qarg) or not.N)rT   TF)r   Úinstruction_supportedr    )r"   r(   rh   s      r*   Ú__gate_supportedz$DynamicalDecoupling.__gate_supported5  s4   € àŒ<Ð 4¤<×#EÒ#EÀdÄiÐX\ÐW^Ð#EÑ#_Ô#_ÐØ�4Øˆur+   )NNTN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r€   r?   r   r8   ÚboolrK   Ú__classcell__)r)   s   @r*   r   r      sÈ   ø€ € € € € ðLð Lð\ €^ðað ðñ ô ð aeð$ð $ð $ð $ð $ñô ð$ðL@ð @ð @ðDð ð ð0 Tð °ð ¸ð ð ð ð ð ð ð ð r+   r   )r›   r_   r‡   Únumpyr@   Úqiskit.circuitr   r   r   Ú%qiskit.circuit.library.standard_gatesr   r   r   Úqiskit.dagcircuitr	   r
   Ú(qiskit.quantum_info.operators.predicatesr   Úqiskit.synthesis.one_qubitr   Úqiskit.transpiler.basepassesr   Úqiskit.transpiler.exceptionsr   Ú'qiskit.transpiler.instruction_durationsr   Ú%qiskit.transpiler.passes.optimizationr   Úqiskit.utils.deprecationr   r   r2   r+   r*   ú<module>r©      s?  ðð +Ð *à Ð Ð Ð Ø €€€à Ð Ð Ð Ø -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ø FÐ FÐ FÐ FÐ FÐ FÐ FÐ FÐ FÐ FØ 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ð 2Ø AÐ AÐ AÐ AÐ AÐ AØ >Ð >Ð >Ð >Ð >Ð >Ø ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø HÐ HÐ HÐ HÐ HÐ HØ AÐ AÐ AÐ AÐ AÐ AØ 3Ð 3Ð 3Ð 3Ð 3Ð 3ðZð Zð Zð Zð ZÐ,ñ Zô Zð Zð Zð Zr+   