From c0c193466411f7794784c015b0d9829d200ef937 Mon Sep 17 00:00:00 2001 From: nick bronn Date: Thu, 8 Aug 2024 20:13:03 -0400 Subject: [PATCH] added instruction pi_phi to target for urdd DD and converted from backend to target --- qiskit_research/utils/convenience.py | 11 ++++---- qiskit_research/utils/dynamical_decoupling.py | 25 +++++++++++-------- test/utils/test_dynamical_decoupling.py | 19 ++++++++------ 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/qiskit_research/utils/convenience.py b/qiskit_research/utils/convenience.py index bd3bac8..b67a38c 100644 --- a/qiskit_research/utils/convenience.py +++ b/qiskit_research/utils/convenience.py @@ -16,7 +16,7 @@ from qiskit.circuit import Gate from qiskit.circuit.library import XGate from qiskit.providers.backend import Backend -from qiskit.transpiler import PassManager +from qiskit.transpiler import PassManager, Target from qiskit.transpiler.passes.scheduling import ALAPScheduleAnalysis from qiskit.transpiler.passes.scheduling.scheduling.base_scheduler import BaseScheduler @@ -37,7 +37,7 @@ def add_dynamical_decoupling( circuits: Union[QuantumCircuit, List[QuantumCircuit], List[List[QuantumCircuit]]], - backend: Backend, + target: Target, dd_str: str, scheduler: BaseScheduler = ALAPScheduleAnalysis, add_pulse_cals: bool = False, @@ -67,23 +67,22 @@ def add_dynamical_decoupling( single or sequence type of QuantumCircuit, shceduled with DD sequences inserted into idle times. """ - pass_manager = PassManager( list( dynamical_decoupling_passes( - backend, dd_str, scheduler, urdd_pulse_num=urdd_pulse_num + target, dd_str, scheduler, urdd_pulse_num=urdd_pulse_num ) ) ) if isinstance(circuits, QuantumCircuit) or isinstance(circuits[0], QuantumCircuit): circuits_dd = pass_manager.run(circuits) if add_pulse_cals: - add_pulse_calibrations(circuits_dd, backend, pulse_method=pulse_method) + add_pulse_calibrations(circuits_dd, target, pulse_method=pulse_method) else: circuits_dd = [pass_manager.run(circs) for circs in circuits] if add_pulse_cals: for circs_dd in circuits_dd: - add_pulse_calibrations(circs_dd, backend, pulse_method=pulse_method) + add_pulse_calibrations(circs_dd, target, pulse_method=pulse_method) return circuits_dd diff --git a/qiskit_research/utils/dynamical_decoupling.py b/qiskit_research/utils/dynamical_decoupling.py index 1684534..41ac2c9 100644 --- a/qiskit_research/utils/dynamical_decoupling.py +++ b/qiskit_research/utils/dynamical_decoupling.py @@ -17,7 +17,7 @@ import numpy as np from qiskit import QuantumCircuit, pulse -from qiskit.circuit import Gate, Qubit +from qiskit.circuit import Gate, Parameter, Qubit from qiskit.circuit.delay import Delay from qiskit.circuit.library import U3Gate, UGate, XGate, YGate from qiskit.circuit.reset import Reset @@ -26,7 +26,7 @@ from qiskit.providers.backend import Backend from qiskit.pulse import Drag, Waveform from qiskit.synthesis import OneQubitEulerDecomposer -from qiskit.transpiler import InstructionDurations +from qiskit.transpiler import InstructionDurations, Target from qiskit.transpiler.basepasses import BasePass from qiskit.transpiler.exceptions import TranspilerError from qiskit.transpiler.instruction_durations import InstructionDurationsType @@ -69,7 +69,7 @@ class PulseMethod(Enum): def dynamical_decoupling_passes( - backend: Backend, + target: Target, dd_str: str, scheduler: BaseScheduler = ALAPScheduleAnalysis, urdd_pulse_num: int = 4, @@ -87,18 +87,21 @@ def dynamical_decoupling_passes( Yields: Iterator[Iterable[BasePass]]: Transpiler passes used for adding DD sequences. """ - target = backend.target for new_gate in [Xp, Xm, Yp, Ym]: - target.add_instruction(new_gate, target["x"]) - durations = target.durations() + if new_gate.name not in target: + target.add_instruction(new_gate, target["x"]) if dd_str in DD_SEQUENCE: sequence = DD_SEQUENCE[dd_str] elif dd_str == "URDD": phis = get_urdd_angles(urdd_pulse_num) sequence = tuple(PiPhiGate(phi) for phi in phis) - yield scheduler(durations) - yield PadDynamicalDecoupling(durations, list(sequence)) + if "pi_phi" not in target: + phi = Parameter("φ") + target.add_instruction(PiPhiGate(phi), target["x"]) + + yield scheduler(target.durations()) + yield PadDynamicalDecoupling(target.durations(), list(sequence)) def periodic_dynamical_decoupling( @@ -173,7 +176,7 @@ def periodic_dynamical_decoupling( # TODO refactor this as a CalibrationBuilder transpilation pass def add_pulse_calibrations( circuits: Union[QuantumCircuit, List[QuantumCircuit]], - backend: Backend, + target: Target, pulse_method: PulseMethod = PulseMethod.PHASESHIFT, ) -> None: """ @@ -190,8 +193,8 @@ def add_pulse_calibrations( Raises: ValueError: Not a defined method for implementing pulse schedules for URDD gates. """ - inst_sched_map = backend.defaults().instruction_schedule_map - num_qubits = backend.configuration().num_qubits + inst_sched_map = target.instruction_schedule_map() + num_qubits = target.num_qubits if isinstance(circuits, QuantumCircuit): circuits = [circuits] diff --git a/test/utils/test_dynamical_decoupling.py b/test/utils/test_dynamical_decoupling.py index 7a41b26..b9bf9a0 100644 --- a/test/utils/test_dynamical_decoupling.py +++ b/test/utils/test_dynamical_decoupling.py @@ -12,8 +12,8 @@ import unittest -from qiskit import transpile from qiskit.circuit import QuantumCircuit +from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager from qiskit_ibm_runtime.fake_provider import FakeSherbrooke from qiskit_research.utils.convenience import ( @@ -38,9 +38,11 @@ def test_add_dynamical_decoupling(self): circuit.rx(1.0, [0, 1, 2]) backend = FakeSherbrooke() - transpiled = transpile(circuit, backend) + target = backend.target + pm = generate_preset_pass_manager(target=target, optimization_level=2) + transpiled = pm.run(circuit) transpiled_dd = add_dynamical_decoupling( - transpiled, backend, "XY4pm", add_pulse_cals=True + transpiled, target, "XY4pm", add_pulse_cals=True ) self.assertIsInstance(transpiled_dd, QuantumCircuit) self.assertIn("xp", transpiled_dd.count_ops()) @@ -60,10 +62,12 @@ def test_add_urdd_dynamical_decoupling(self): circuit.rx(1.0, [0, 1, 2]) backend = FakeSherbrooke() - transpiled = transpile(circuit, backend) + target = backend.target + pm = generate_preset_pass_manager(2, backend) + transpiled = pm.run(circuit) transpiled_urdd4 = add_dynamical_decoupling( transpiled, - backend, + target, "URDD", add_pulse_cals=True, urdd_pulse_num=4, @@ -75,7 +79,7 @@ def test_add_urdd_dynamical_decoupling(self): transpiled_urdd8 = add_dynamical_decoupling( transpiled, - backend, + target, "URDD", add_pulse_cals=True, urdd_pulse_num=8, @@ -89,7 +93,8 @@ def test_add_pulse_calibrations(self): """Test adding dynamical decoupling.""" circuit = QuantumCircuit(2) backend = FakeSherbrooke() - add_pulse_calibrations(circuit, backend) + target = backend.target + add_pulse_calibrations(circuit, target) for key in circuit.calibrations["xp"]: drag_xp = circuit.calibrations["xp"][key].instructions[0][1].operands[0] drag_xm = circuit.calibrations["xm"][key].instructions[0][1].operands[0]