§
    º³Ùg‰;  ã                   ó¢   — d Z ddlZddlmZmZmZmZ ddlmZ ddl	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Base circuit scheduling pass.é    N)ÚDelayÚGateÚMeasureÚReset)ÚParameterExpression)Ú	DAGOpNodeÚ
DAGCircuitÚ
DAGOutNode)ÚTransformationPass)ÚTranspilerError)ÚInstructionDurations)ÚTimeUnitConversion)ÚTargetc            	       ó†   ‡ — e Zd ZdZeefZ	 	 	 	 ddededede	fˆ fd„Z
ed	ed
edefd„¦   «         Zdedefd„Zd
efd„Zˆ xZS )ÚBaseSchedulerTransformu1'  Base scheduler pass.

    .. warning::

        This base class is not part of the public interface for this module
        it should not be used to develop new scheduling passes as the passes
        which are using this are pending a future deprecation and subsequent
        removal. If you are developing new scheduling passes look at the
        ``BaseScheduler`` class instead which is used in the new scheduling
        pass workflow.

    Policy of topological node ordering in scheduling

        The DAG representation of ``QuantumCircuit`` respects the node ordering also in the
        classical register wires, though theoretically two conditional instructions
        conditioned on the same register are commute, i.e. read-access to the
        classical register doesn't change its state.

        .. code-block:: text

            qc = QuantumCircuit(2, 1)
            qc.delay(100, 0)
            qc.x(0).c_if(0, True)
            qc.x(1).c_if(0, True)

        The scheduler SHOULD comply with above topological ordering policy of the DAG circuit.
        Accordingly, the `asap`-scheduled circuit will become

        .. code-block:: text

                 â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”�   â”Œâ”€â”€â”€â”�
            q_0: â”¤ Delay(100[dt]) â”œâ”€â”€â”€â”¤ X â”œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
                 â”œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”¤   â””â”€â•¥â”€â”˜      â”Œâ”€â”€â”€â”�
            q_1: â”¤ Delay(100[dt]) â”œâ”€â”€â”€â”€â”€â•«â”€â”€â”€â”€â”€â”€â”€â”€â”¤ X â”œâ”€â”€â”€
                 â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜     â•‘        â””â”€â•¥â”€â”˜
                                   â”Œâ”€â”€â”€â”€â•¨â”€â”€â”€â”€â”�â”Œâ”€â”€â”€â”€â•¨â”€â”€â”€â”€â”�
            c: 1/â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¡ c_0=0x1 â•žâ•¡ c_0=0x1 â•ž
                                   â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜

        Note that this scheduling might be inefficient in some cases,
        because the second conditional operation can start without waiting the delay of 100 dt.
        However, such optimization should be done by another pass,
        otherwise scheduling may break topological ordering of the original circuit.

    Realistic control flow scheduling respecting for microarchitecture

        In the dispersive QND readout scheme, qubit is measured with microwave stimulus to qubit (Q)
        followed by resonator ring-down (depopulation). This microwave signal is recorded
        in the buffer memory (B) with hardware kernel, then a discriminated (D) binary value
        is moved to the classical register (C).
        The sequence from t0 to t1 of the measure instruction interval might be modeled as follows:

        .. code-block:: text

            Q â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘
            B â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
            D â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–’â–’â–’â–’â–‘â–‘â–‘
            C â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–‘

        However, ``QuantumCircuit`` representation is not enough accurate to represent
        this model. In the circuit representation, thus ``Qubit`` is occupied by the
        stimulus microwave signal during the first half of the interval,
        and ``Clbit`` is only occupied at the very end of the interval.

        This precise model may induce weird edge case.

        .. code-block:: text

                    â”Œâ”€â”€â”€â”�
            q_0: â”€â”€â”€â”¤ X â”œâ”€â”€â”€â”€â”€â”€
                    â””â”€â•¥â”€â”˜   â”Œâ”€â”�
            q_1: â”€â”€â”€â”€â”€â•«â”€â”€â”€â”€â”€â”¤Mâ”œ
                 â”Œâ”€â”€â”€â”€â•¨â”€â”€â”€â”€â”�â””â•¥â”˜
            c: 1/â•¡ c_0=0x1 â•žâ•�â•©â•�
                 â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜ 0

        In this example, user may intend to measure the state of ``q_1``, after ``XGate`` is
        applied to the ``q_0``. This is correct interpretation from viewpoint of
        the topological node ordering, i.e. x gate node come in front of the measure node.
        However, according to the measurement model above, the data in the register
        is unchanged during the stimulus, thus two nodes are simultaneously operated.
        If one `alap`-schedule this circuit, it may return following circuit.

        .. code-block:: text

                 â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”�   â”Œâ”€â”€â”€â”�
            q_0: â”¤ Delay(500[dt]) â”œâ”€â”€â”€â”¤ X â”œâ”€â”€â”€â”€â”€â”€
                 â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜   â””â”€â•¥â”€â”˜   â”Œâ”€â”�
            q_1: â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â•«â”€â”€â”€â”€â”€â”¤Mâ”œ
                                   â”Œâ”€â”€â”€â”€â•¨â”€â”€â”€â”€â”�â””â•¥â”˜
            c: 1/â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¡ c_0=0x1 â•žâ•�â•©â•�
                                   â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜ 0

        Note that there is no delay on ``q_1`` wire, and the measure instruction immediately
        start after t=0, while the conditional gate starts after the delay.
        It looks like the topological ordering between the nodes are flipped in the scheduled view.
        This behavior can be understood by considering the control flow model described above,

        .. code-block:: text

            : Quantum Circuit, first-measure
            0 â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–’â–’â–’â–’â–‘
            1 â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘

            : In wire q0
            Q â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–’â–‘
            C â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–‘â–‘â–‘â–‘â–‘

            : In wire q1
            Q â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘
            B â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
            D â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–’â–’â–’â–’â–‘â–‘â–‘
            C â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–‘

        Since there is no qubit register (Q0, Q1) overlap, the node ordering is determined by the
        shared classical register C. As you can see, the execution order is still
        preserved on C, i.e. read C then apply ``XGate``, finally store the measured outcome in C.
        Because ``DAGOpNode`` cannot define different durations for associated registers,
        the time ordering of two nodes is inverted anyways.

        This behavior can be controlled by ``clbit_write_latency`` and ``conditional_latency``.
        The former parameter determines the delay of the register write-access from
        the beginning of the measure instruction t0, and another parameter determines
        the delay of conditional gate operation from t0 which comes from the register read-access.

        Since we usually expect topological ordering and time ordering are identical
        without the context of microarchitecture, both latencies are set to zero by default.
        In this case, ``Measure`` instruction immediately locks the register C.
        Under this configuration, the `alap`-scheduled circuit of above example may become

        .. code-block:: text

                    â”Œâ”€â”€â”€â”�
            q_0: â”€â”€â”€â”¤ X â”œâ”€â”€â”€â”€â”€â”€
                    â””â”€â•¥â”€â”˜   â”Œâ”€â”�
            q_1: â”€â”€â”€â”€â”€â•«â”€â”€â”€â”€â”€â”¤Mâ”œ
                 â”Œâ”€â”€â”€â”€â•¨â”€â”€â”€â”€â”�â””â•¥â”˜
            c: 1/â•¡ c_0=0x1 â•žâ•�â•©â•�
                 â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜ 0

        If the backend microarchitecture supports smart scheduling of the control flow, i.e.
        it may separately schedule qubit and classical register,
        insertion of the delay yields unnecessary longer total execution time.

        .. code-block:: text

            : Quantum Circuit, first-xgate
            0 â–‘â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
            1 â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘

            : In wire q0
            Q â–‘â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
            C â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘ (zero latency)

            : In wire q1
            Q â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘
            C â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘ (zero latency, scheduled after C0 read-access)

        However this result is much more intuitive in the topological ordering view.
        If finite conditional latency is provided, for example, 30 dt, the circuit
        is scheduled as follows.

        .. code-block:: text

                 â”Œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”�   â”Œâ”€â”€â”€â”�
            q_0: â”¤ Delay(30[dt]) â”œâ”€â”€â”€â”¤ X â”œâ”€â”€â”€â”€â”€â”€
                 â”œâ”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”¤   â””â”€â•¥â”€â”˜   â”Œâ”€â”�
            q_1: â”¤ Delay(30[dt]) â”œâ”€â”€â”€â”€â”€â•«â”€â”€â”€â”€â”€â”¤Mâ”œ
                 â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜â”Œâ”€â”€â”€â”€â•¨â”€â”€â”€â”€â”�â””â•¥â”˜
            c: 1/â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¡ c_0=0x1 â•žâ•�â•©â•�
                                  â””â”€â”€â”€â”€â”€â”€â”€â”€â”€â”˜ 0

        with the timing model:

        .. code-block:: text

            : Quantum Circuit, first-xgate
            0 â–‘â–‘â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
            1 â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘

            : In wire q0
            Q â–‘â–‘â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘
            C â–‘â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘ (30dt latency)

            : In wire q1
            Q â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘
            C â–‘â–‘â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–‘

        See https://arxiv.org/abs/2102.01682 for more details.

    Nr   Ú	durationsÚclbit_write_latencyÚconditional_latencyÚtargetc                 ó  •— t          ¦   «                              ¦   «          || _        |�|                     ¦   «         | _        | j                             t          | j        ¦  «        ¦  «         || _        || _        || _        dS )aó  Scheduler initializer.

        Args:
            durations: Durations of instructions to be used in scheduling
            clbit_write_latency: A control flow constraints. Because standard superconducting
                quantum processor implement dispersive QND readout, the actual data transfer
                to the clbit happens after the round-trip stimulus signal is buffered
                and discriminated into quantum state.
                The interval ``[t0, t0 + clbit_write_latency]`` is regarded as idle time
                for clbits associated with the measure instruction.
                This defaults to 0 dt which is identical to Qiskit Pulse scheduler.
            conditional_latency: A control flow constraints. This value represents
                a latency of reading a classical register for the conditional operation.
                The gate operation occurs after this latency. This appears as a delay
                in front of the DAGOpNode of the gate.
                This defaults to 0 dt.
            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.
        N)	ÚsuperÚ__init__r   ÚrequiresÚappendr   r   r   r   )Úselfr   r   r   r   Ú	__class__s        €úh/granary/edev/quantum/lib/python3.11/site-packages/qiskit/transpiler/passes/scheduling/base_scheduler.pyr   zBaseSchedulerTransform.__init__Ý   sy   ø€ õ6 	‰Œ×ÒÑÔÐØ"ˆŒàÐØ#×-Ò-Ñ/Ô/ˆDŒNØŒ×ÒÕ/°´Ñ?Ô?Ñ@Ô@Ð@ð $7ˆÔ Ø#6ˆÔ àˆŒˆˆó    ÚnodeÚdagÚreturnc           	      óæ  ‡— ˆfd„| j         D ¦   «         }‰                     | ¦  «        rUt          |¦  «        t          d„ | j        j        D ¦   «         ¦  «        f}‰j        | j        j                 |         j        }n| j        j        }t          | j        t          ¦  «        rt          j        d¦  «         n]t          | j        t          ¦  «        rCt          d„ ‰                     | ¦  «        D ¦   «         ¦  «         }|rt          j        d¦  «         t          |t          ¦  «        r#t!          d|› d| j        j        › d|› d	�¦  «        ‚|€ t!          d| j        j        › d|› d�¦  «        ‚|S )z9A helper method to get duration from node or calibration.c                 óD   •— g | ]}‰                      |¦  «        j        ‘ŒS © )Úfind_bitÚindex)Ú.0Úqargr    s     €r   ú
<listcomp>z=BaseSchedulerTransform._get_node_duration.<locals>.<listcomp>  s(   ø€ ÐCÐCÐC°�3—<’< Ñ%Ô%Ô+ÐCÐCÐCr   c              3   ó4   K  — | ]}t          |¦  «        V — Œd S ©N)Úfloat)r'   Úps     r   ú	<genexpr>z<BaseSchedulerTransform._get_node_duration.<locals>.<genexpr>  s(   è è € Ð+MÐ+M¸­E°!©H¬HÐ+MÐ+MÐ+MÐ+MÐ+MÐ+Mr   z¿Qiskit scheduler assumes Reset works similarly to Measure instruction. Actual behavior depends on the control system of your quantum backend. Your backend may provide a plugin scheduler pass.c              3   ó@   K  — | ]}t          |t          ¦  «        V — Œd S r+   )Ú
isinstancer
   )r'   Úxs     r   r.   z<BaseSchedulerTransform._get_node_duration.<locals>.<genexpr>  s=   è è € ð %ð %Ø./•
˜1�jÑ)Ô)ð%ð %ð %ð %ð %ð %r   z¯Qiskit scheduler assumes mid-circuit measurement works as a standard instruction. Actual backend may apply custom scheduling. Your backend may provide a plugin scheduler pass.zParameterized duration (z) of z on qubits z is not bounded.NzDuration of z is not found.)ÚqargsÚ_has_calibration_forÚtupleÚopÚparamsÚ_calibrations_propÚnameÚdurationr0   r   ÚwarningsÚwarnr   ÚanyÚquantum_successorsr   r   )r   r    ÚindicesÚcal_keyr9   Úis_mid_circuits    `    r   Ú_get_node_durationz)BaseSchedulerTransform._get_node_duration  sÈ  ø€ ð DÐCÐCÐC¸¼
ÐCÑCÔCˆà×#Ò# DÑ)Ô)ð 	(å˜G‘n”n¥eÐ+MÐ+M¸d¼g¼nÐ+MÑ+MÔ+MÑ&MÔ&MÐMˆGØÔ-¨d¬g¬lÔ;¸GÔDÔMˆHˆHà”wÔ'ˆHå�d”g�uÑ%Ô%ð 	ÝŒMðDñô ð ð õ
 ˜œ¥Ñ)Ô)ð 		Ý!$ð %ð %Ø36×3IÒ3IÈ$Ñ3OÔ3Oð%ñ %ô %ñ "ô "ð ˆNð ð Ý”ðHñô ð õ �hÕ 3Ñ4Ô4ð 	Ý!ðI¨8ð Ið IØ”g”lðIð IØ/6ðIð Ið Iñô ð ð ÐÝ!Ð"a°´´Ð"aÐ"aÈ'Ð"aÐ"aÐ"aÑbÔbÐbàˆr   r(   c                 óR   — | j         �| j                              d|f¬¦  «        rdS dS )z8Delay operation is supported on the qubit (qarg) or not.NÚdelay)r2   TF)r   Úinstruction_supported)r   r(   s     r   Ú_delay_supportedz'BaseSchedulerTransform._delay_supported/  s2   € àŒ;Ð $¤+×"CÒ"CÀGÐTXÐSZÐ"CÑ"[Ô"[ÐØ�4Øˆur   c                 ó   — t           ‚r+   )ÚNotImplementedError)r   r    s     r   ÚrunzBaseSchedulerTransform.run5  s   € Ý!Ð!r   )Nr   r   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   ÚCONDITIONAL_SUPPORTEDr   Úintr   r   Ústaticmethodr   r	   rA   ÚboolrE   rH   Ú__classcell__)r   s   @r   r   r      s  ø€ € € € € ð~ð ~ð@ " 5˜MÐð +/Ø#$Ø#$Øð&ð &à'ð&ð !ð&ð !ð	&ð
 ð&ð &ð &ð &ð &ð &ðP ð'Øð'àð'ð 
ð'ð 'ð 'ñ „\ð'ðR Sð ¨Tð ð ð ð ð"�zð "ð "ð "ð "ð "ð "ð "ð "r   r   )rL   r:   Úqiskit.circuitr   r   r   r   Ú"qiskit.circuit.parameterexpressionr   Úqiskit.dagcircuitr   r	   r
   Úqiskit.transpiler.basepassesr   Úqiskit.transpiler.exceptionsr   Ú'qiskit.transpiler.instruction_durationsr   Ú8qiskit.transpiler.passes.scheduling.time_unit_conversionr   Úqiskit.transpiler.targetr   r   r$   r   r   ú<module>rZ      s  ðð $Ð #Ø €€€à 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ð 6Ø BÐ BÐ BÐ BÐ BÐ BØ ?Ð ?Ð ?Ð ?Ð ?Ð ?Ð ?Ð ?Ð ?Ð ?Ø ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø HÐ HÐ HÐ HÐ HÐ HØ WÐ WÐ WÐ WÐ WÐ WØ +Ð +Ð +Ð +Ð +Ð +ð\"ð \"ð \"ð \"ð \"Ð/ñ \"ô \"ð \"ð \"ð \"r   