§
    º³Ùg1  ã                   óî   — d Z ddlmZ ddlmZ ddlZddlmZ ddl	m
Z
 ddlmZ ddl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ededededededefd„¦   «         ZdS )zOAdd single-pulse RX calibrations that are bootstrapped from the SX calibration.é    )ÚUnion)Ú	lru_cacheN)ÚInstruction)ÚRXGate)ÚQiskitError)ÚScheduleÚScheduleBlockÚbuilderÚScalableSymbolicPulse)ÚChannel)ÚDrag)ÚCalibrationBuilder)ÚTarget)Údeprecate_pulse_dependencyc                   ót   ‡ — e Zd ZdZe	 d
defˆ fd„¦   «         Zdedede	fd„Z
dededeeef         fd	„Zˆ xZS )ÚRXCalibrationBuilderaŽ  Add single-pulse RX calibrations that are bootstrapped from the SX calibration.

    .. note::

        Requirement: NormalizeRXAngles pass (one of the optimization passes).

    It is recommended to place this pass in the post-optimization stage of a passmanager.
    A simple demo:

    .. code-block:: python

       from qiskit.providers.fake_provider import GenericBackendV2
       from qiskit.transpiler import PassManager, PassManagerConfig
       from qiskit.transpiler.preset_passmanagers import level_1_pass_manager
       from qiskit.circuit import Parameter
       from qiskit.circuit.library import QuantumVolume
       from qiskit.circuit.library.standard_gates import RXGate

       from qiskit.transpiler.passes import RXCalibrationBuilder

       qv = QuantumVolume(4, 4, seed=1004)

       # Transpiling with single pulse RX gates enabled
       backend_with_single_pulse_rx = GenericBackendV2(5)
       rx_inst_props = {}
       for i in range(backend_with_single_pulse_rx.num_qubits):
         rx_inst_props[(i,)] = None
       backend_with_single_pulse_rx.target.add_instruction(RXGate(Parameter("theta")), rx_inst_props)
       config_with_rx = PassManagerConfig.from_backend(backend=backend_with_single_pulse_rx)
       pm_with_rx = level_1_pass_manager(pass_manager_config=config_with_rx)
       rx_builder = RXCalibrationBuilder(target=backend_with_single_pulse_rx.target)
       pm_with_rx.post_optimization = PassManager([rx_builder])
       transpiled_circ_with_single_pulse_rx = pm_with_rx.run(qv)
       transpiled_circ_with_single_pulse_rx.count_ops()

       # Conventional transpilation: each RX gate is decomposed into a sequence with two SX gates
       original_backend = GenericBackendV2(5)
       original_config = PassManagerConfig.from_backend(backend=original_backend)
       original_pm = level_1_pass_manager(pass_manager_config=original_config)
       original_transpiled_circ = original_pm.run(qv)
       original_transpiled_circ.count_ops()

    References
        * [1]: Gokhale et al. (2020), Optimized Quantum Compilation for
          Near-Term Algorithms with OpenPulse.
          `arXiv:2004.11205 <https://arxiv.org/abs/2004.11205>`
    NÚtargetc                 óœ   •— ddl m} t          ¦   «                              ¦   «          || _        i | _         || j        ¦  «        g| _        dS )zýBootstrap single-pulse RX gate calibrations from the
        (hardware-calibrated) SX gate calibration.

        Args:
            target (Target): Should contain a SX calibration that will be
            used for bootstrapping RX calibrations.
        r   )ÚNormalizeRXAngleN)Ú%qiskit.transpiler.passes.optimizationr   ÚsuperÚ__init__r   Úalready_generatedÚrequires)Úselfr   r   Ú	__class__s      €úe/granary/edev/quantum/lib/python3.11/site-packages/qiskit/transpiler/passes/calibration/rx_builder.pyr   zRXCalibrationBuilder.__init__O   sX   ø€ ð 	KÐJÐJÐJÐJÐJå‰Œ×ÒÑÔÐØˆŒØ!#ˆÔØ)Ð)¨$¬+Ñ6Ô6Ð7ˆŒˆˆó    Únode_opÚqubitsÚreturnc                 ó(  — t          |t          ¦  «        oý| j                             dt	          |¦  «        ¦  «        oÕt          | j                             dt	          |¦  «        ¦  «        j        ¦  «        dk    o—t          | j                             dt	          |¦  «        ¦  «        j        d         d         j        t          ¦  «        oF| j                             dt	          |¦  «        ¦  «        j        d         d         j        j
        dk    S )z[
        Check if the calibration for SX gate exists and it's a single DRAG pulse.
        Úsxé   r   r   )Ú
isinstancer   r   Ú_has_calibrationÚtupleÚlenÚ_get_calibrationÚinstructionsÚpulser   Ú
pulse_type)r   r   r    s      r   Ú	supportedzRXCalibrationBuilder.supportedb   së   € õ
 �w¥Ñ'Ô'ð 
Ø”×,Ò,¨Tµ5¸±=´=ÑAÔAð
å�T”[×1Ò1°$½¸f¹¼ÑFÔFÔSÑTÔTÐXYÒYð
õ Ø”×,Ò,¨Tµ5¸±=´=ÑAÔAÔNÈqÔQÐRSÔTÔZÝ%ñô ð
ð ”×,Ò,¨Tµ5¸±=´=ÑAÔAÜ˜!ôØô ä”:Øòð	
r   c           	      óì  — |j         d         }	 t          |¦  «        }n"# t          $ r}t          d¦  «        |‚d}~ww xY w| j                             dt          |¦  «        ¦  «        j        d         d         j        j	         
                    ¦   «         }t          || j                             dt          |¦  «        ¦  «        j        d         |d         |d         |d         |d	         ¬
¦  «        }|S )zV
        Generate RX calibration for the rotation angle specified in node_op.
        r   z&Target rotation angle is not assigned.Nr#   r$   ÚdurationÚampÚsigmaÚbeta)Úrx_angleÚchannelr/   r0   r1   r2   )ÚparamsÚfloatÚ	TypeErrorr   r   r)   r'   r*   r+   Ú
parametersÚcopyÚ_create_rx_schedÚchannels)r   r   r    ÚangleÚexr5   Únew_rx_scheds          r   Úget_calibrationz$RXCalibrationBuilder.get_calibrationt   sù   € ð
 ”˜qÔ!ˆð	PÝ˜%‘L”LˆEˆEøÝð 	Pð 	Pð 	PÝÐFÑGÔGÈRÐOøøøøð	Pøøøð ŒK×(Ò(¨­u°V©}¬}Ñ=Ô=Ü˜!ôØô ä”:Ÿdšd™fœfð 	õ
 (ØØ”K×0Ò0°µu¸V±}´}ÑEÔEÔNÈqÔQØ˜JÔ'Ø�u”Ø˜”/Ø˜”ð
ñ 
ô 
ˆð Ðs   � Ÿ
>©9¹>)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   ÚlistÚboolr-   r   r   r	   r?   Ú__classcell__)r   s   @r   r   r      sÄ   ø€ € € € € ð.ð .ð`  ð ð8ð 8àð8ð 8ð 8ð 8ð 8ñ  Ôð8ð$
 ð 
°dð 
¸tð 
ð 
ð 
ð 
ð$ {ð ¸Dð ÀUÈ8ÐUbÐKbÔEcð ð ð ð ð ð ð ð r   r   r3   r/   r0   r1   r2   r4   c           
      óÖ   — | t           j        dz  z  |z  }t          j        ¦   «         5 }t          j        t          ||||d¬¦  «        |¬¦  «         ddd¦  «         n# 1 swxY w Y   |S )zoGenerates (and caches) pulse calibrations for RX gates.
    Assumes that the rotation angle is in [0, pi].
    é   r   )r/   r0   r1   r2   r<   )r4   N)ÚnpÚpir
   ÚbuildÚplayr   )r3   r/   r0   r1   r2   r4   Únew_ampr>   s           r   r:   r:   ‘   s±   € ð �"œ% !™)Ñ$ sÑ*€GÝ	Œ‰Œð 
˜LÝŒÝ˜(¨°uÀ4ÈqÐQÑQÔQØð	
ñ 	
ô 	
ð 	
ð
ð 
ð 
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
øøøð 
ð 
ð 
ð 
ð Ðs   ©)AÁA"Á%A") rC   Útypingr   Ú	functoolsr   ÚnumpyrI   Úqiskit.circuitr   Ú%qiskit.circuit.library.standard_gatesr   Úqiskit.exceptionsr   Úqiskit.pulser   r	   r
   r   Úqiskit.pulse.channelsr   Ú$qiskit.pulse.library.symbolic_pulsesr   Ú1qiskit.transpiler.passes.calibration.base_builderr   Úqiskit.transpiler.targetr   Úqiskit.utils.deprecate_pulser   r   r6   Úintr:   © r   r   ú<module>r\      sˆ  ðð VÐ Uà Ð Ð Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø Ð Ð Ð à &Ð &Ð &Ð &Ð &Ð &Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8Ø )Ð )Ð )Ð )Ð )Ð )Ø PÐ PÐ PÐ PÐ PÐ PÐ PÐ PÐ PÐ PÐ PÐ PØ )Ð )Ð )Ð )Ð )Ð )Ø 5Ð 5Ð 5Ð 5Ð 5Ð 5Ø PÐ PÐ PÐ PÐ PÐ PØ +Ð +Ð +Ð +Ð +Ð +Ø CÐ CÐ CÐ CÐ CÐ Cðpð pð pð pð pÐ-ñ pô pð pðf ðØðàðð 
ðð ð	ð
 ðð ðð ð ñ „ðð ð r   