def test_insert_dd_bad_sequence(self): """Test DD raises when non-identity sequence is inserted.""" dd_sequence = [XGate(), YGate()] pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence), ]) with self.assertRaises(TranspilerError): pm.run(self.ghz4)
def test_dd_with_calibrations_with_parameters(self, param_value): """Check that calibrations in a circuit with parameters work fine.""" circ = QuantumCircuit(2) circ.x(0) circ.cx(0, 1) circ.rx(param_value, 1) rx_duration = int(param_value * 1000) with pulse.build() as rx: pulse.play(pulse.Gaussian(rx_duration, 0.1, rx_duration // 4), pulse.DriveChannel(1)) circ.add_calibration("rx", (1, ), rx, params=[param_value]) durations = InstructionDurations([("x", None, 100), ("cx", None, 300)]) dd_sequence = [XGate(), XGate()] pm = PassManager([ ALAPScheduleAnalysis(durations), PadDynamicalDecoupling(durations, dd_sequence) ]) self.assertEqual(pm.run(circ).duration, rx_duration + 100 + 300)
def test_insert_dd_ghz_everywhere(self): """Test DD gates even on initial idle spots. ┌───┐ ┌────────────────┐┌───┐┌────────────────┐┌───┐» q_0: ──────┤ H ├─────────■──┤ Delay(100[dt]) ├┤ Y ├┤ Delay(200[dt]) ├┤ Y ├» ┌─────┴───┴─────┐ ┌─┴─┐└────────────────┘└───┘└────────────────┘└───┘» q_1: ┤ Delay(50[dt]) ├─┤ X ├───────────────────────────────────────────■──» ├───────────────┴┐├───┤┌────────────────┐┌───┐┌────────────────┐┌─┴─┐» q_2: ┤ Delay(162[dt]) ├┤ Y ├┤ Delay(326[dt]) ├┤ Y ├┤ Delay(162[dt]) ├┤ X ├» ├────────────────┤├───┤├────────────────┤├───┤├────────────────┤└───┘» q_3: ┤ Delay(212[dt]) ├┤ Y ├┤ Delay(426[dt]) ├┤ Y ├┤ Delay(212[dt]) ├─────» └────────────────┘└───┘└────────────────┘└───┘└────────────────┘ » « ┌────────────────┐ «q_0: ┤ Delay(100[dt]) ├───────────────────────────────────────────── « ├───────────────┬┘┌───┐┌────────────────┐┌───┐┌───────────────┐ «q_1: ┤ Delay(50[dt]) ├─┤ Y ├┤ Delay(100[dt]) ├┤ Y ├┤ Delay(50[dt]) ├ « └───────────────┘ └───┘└────────────────┘└───┘└───────────────┘ «q_2: ────────■────────────────────────────────────────────────────── « ┌─┴─┐ «q_3: ──────┤ X ├──────────────────────────────────────────────────── « └───┘ """ dd_sequence = [YGate(), YGate()] pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence, skip_reset_qubits=False), ]) ghz4_dd = pm.run(self.ghz4) expected = self.ghz4.copy() expected = expected.compose(Delay(50), [1], front=True) expected = expected.compose(Delay(162), [2], front=True) expected = expected.compose(YGate(), [2], front=True) expected = expected.compose(Delay(326), [2], front=True) expected = expected.compose(YGate(), [2], front=True) expected = expected.compose(Delay(162), [2], front=True) expected = expected.compose(Delay(212), [3], front=True) expected = expected.compose(YGate(), [3], front=True) expected = expected.compose(Delay(426), [3], front=True) expected = expected.compose(YGate(), [3], front=True) expected = expected.compose(Delay(212), [3], front=True) expected = expected.compose(Delay(100), [0]) expected = expected.compose(YGate(), [0]) expected = expected.compose(Delay(200), [0]) expected = expected.compose(YGate(), [0]) expected = expected.compose(Delay(100), [0]) expected = expected.compose(Delay(50), [1]) expected = expected.compose(YGate(), [1]) expected = expected.compose(Delay(100), [1]) expected = expected.compose(YGate(), [1]) expected = expected.compose(Delay(50), [1]) self.assertEqual(ghz4_dd, expected)
def test_scheduling_with_calibration(self): """Test if calibrated instruction can update node duration.""" qc = QuantumCircuit(2) qc.x(0) qc.cx(0, 1) qc.x(1) qc.cx(0, 1) xsched = Schedule(Play(Constant(300, 0.1), DriveChannel(0))) qc.add_calibration("x", (0, ), xsched) durations = InstructionDurations([("x", None, 160), ("cx", None, 600)]) pm = PassManager([ASAPScheduleAnalysis(durations), PadDelay()]) scheduled = pm.run(qc) expected = QuantumCircuit(2) expected.x(0) expected.delay(300, 1) expected.cx(0, 1) expected.x(1) expected.delay(160, 0) expected.cx(0, 1) expected.add_calibration("x", (0, ), xsched) self.assertEqual(expected, scheduled)
def swap_direction(circuit: DAGCircuit, coupling: CouplingMap): if not coupling.is_symmetric: cxDirection = [CXDirection(coupling)] pass_manager = PassManager(cxDirection) transpiled_circuit = pass_manager.run(circuit) return transpiled_circuit else: return circuit
def test_alap_agree_with_reverse_asap_reverse(self): """Test if ALAP schedule agrees with doubly-reversed ASAP schedule.""" qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) qc.measure_all() durations = InstructionDurations([("h", 0, 200), ("cx", [0, 1], 700), ("measure", None, 1000)]) pm = PassManager(ALAPSchedule(durations)) alap_qc = pm.run(qc) pm = PassManager(ASAPSchedule(durations)) new_qc = pm.run(qc.reverse_ops()) new_qc = new_qc.reverse_ops() # pylint: disable=no-member new_qc.name = new_qc.name self.assertEqual(alap_qc, new_qc)
def swap(circuit: DAGCircuit, coupling: CouplingMap): # embedding is needed for the swap algorithm passes = [ DenseLayout(coupling_map=coupling), FullAncillaAllocation(coupling), EnlargeWithAncilla(), ApplyLayout(), LookaheadSwap(coupling_map=coupling) ] pass_manager = PassManager(passes) transpiled_circuit = pass_manager.run(circuit) return transpiled_circuit
def test_insert_midmeas_hahn_asap(self): """Test a single X gate as Hahn echo can absorb in the upstream circuit. ┌──────────────────┐ ┌────────────────┐┌─────────┐» q_0: ────────■─────────┤ U(3π/4,-π/2,π/2) ├─┤ Delay(600[dt]) ├┤ Rx(π/4) ├» ┌─┴─┐ └──────────────────┘┌┴────────────────┤└─────────┘» q_1: ──────┤ X ├────────────────■──────────┤ Delay(1000[dt]) ├─────■─────» ┌─────┴───┴──────┐ ┌─┴─┐ └───────┬─┬───────┘ ┌─┴─┐ » q_2: ┤ Delay(700[dt]) ├───────┤ X ├────────────────┤M├───────────┤ X ├───» └────────────────┘ └───┘ └╥┘ └───┘ » c: 1/═══════════════════════════════════════════════╩════════════════════» 0 » « ┌────────────────┐ «q_0: ┤ Delay(600[dt]) ├──■── « └────────────────┘┌─┴─┐ «q_1: ──────────────────┤ X ├ « ┌────────────────┐└───┘ «q_2: ┤ Delay(700[dt]) ├───── « └────────────────┘ «c: 1/═══════════════════════ « """ dd_sequence = [RXGate(pi / 4)] pm = PassManager([ ASAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence), ]) midmeas_dd = pm.run(self.midmeas) combined_u = UGate(3 * pi / 4, -pi / 2, pi / 2) expected = QuantumCircuit(3, 1) expected.cx(0, 1) expected.compose(combined_u, [0], inplace=True) expected.delay(600, 0) expected.rx(pi / 4, 0) expected.delay(600, 0) expected.delay(700, 2) expected.cx(1, 2) expected.delay(1000, 1) expected.measure(2, 0) expected.cx(1, 2) expected.cx(0, 1) expected.delay(700, 2) self.assertEqual(midmeas_dd, expected) # check the absorption into U was done correctly self.assertTrue( Operator(XGate()).equiv( Operator(UGate(3 * pi / 4, -pi / 2, pi / 2)) & Operator(RXGate(pi / 4))))
def test_insert_dd_ghz_one_qubit(self): """Test DD gates are inserted on only one qubit. ┌───┐ ┌────────────────┐ ┌───┐ » q_0: ──────┤ H ├─────────■──┤ Delay(100[dt]) ├──────┤ X ├───────» ┌─────┴───┴─────┐ ┌─┴─┐└────────────────┘┌─────┴───┴──────┐» q_1: ┤ Delay(50[dt]) ├─┤ X ├────────■─────────┤ Delay(300[dt]) ├» ├───────────────┴┐└───┘ ┌─┴─┐ └────────────────┘» q_2: ┤ Delay(750[dt]) ├───────────┤ X ├───────────────■─────────» ├────────────────┤ └───┘ ┌─┴─┐ » q_3: ┤ Delay(950[dt]) ├─────────────────────────────┤ X ├───────» └────────────────┘ └───┘ » meas: 4/═══════════════════════════════════════════════════════════» » « ┌────────────────┐┌───┐┌────────────────┐ ░ ┌─┐ « q_0: ┤ Delay(200[dt]) ├┤ X ├┤ Delay(100[dt]) ├─░─┤M├───────── « └────────────────┘└───┘└────────────────┘ ░ └╥┘┌─┐ « q_1: ──────────────────────────────────────────░──╫─┤M├────── « ░ ║ └╥┘┌─┐ « q_2: ──────────────────────────────────────────░──╫──╫─┤M├─── « ░ ║ ║ └╥┘┌─┐ « q_3: ──────────────────────────────────────────░──╫──╫──╫─┤M├ « ░ ║ ║ ║ └╥┘ «meas: 4/═════════════════════════════════════════════╩══╩══╩══╩═ « 0 1 2 3 """ dd_sequence = [XGate(), XGate()] pm = PassManager( [ ALAPSchedule(self.durations), DynamicalDecoupling(self.durations, dd_sequence, qubits=[0]), ] ) ghz4_dd = pm.run(self.ghz4.measure_all(inplace=False)) expected = self.ghz4.copy() expected = expected.compose(Delay(50), [1], front=True) expected = expected.compose(Delay(750), [2], front=True) expected = expected.compose(Delay(950), [3], front=True) expected = expected.compose(Delay(100), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(200), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(100), [0]) expected = expected.compose(Delay(300), [1]) expected.measure_all() self.assertEqual(ghz4_dd, expected)
def test_insert_midmeas_hahn_alap(self): """Test a single X gate as Hahn echo can absorb in the downstream circuit. global phase: 3π/2 ┌────────────────┐ ┌───┐ ┌────────────────┐» q_0: ────────■─────────┤ Delay(625[dt]) ├───────┤ X ├───────┤ Delay(625[dt]) ├» ┌─┴─┐ └────────────────┘┌──────┴───┴──────┐└────────────────┘» q_1: ──────┤ X ├───────────────■─────────┤ Delay(1000[dt]) ├────────■─────────» ┌─────┴───┴──────┐ ┌─┴─┐ └───────┬─┬───────┘ ┌─┴─┐ » q_2: ┤ Delay(700[dt]) ├──────┤ X ├───────────────┤M├──────────────┤ X ├───────» └────────────────┘ └───┘ └╥┘ └───┘ » c: 1/═════════════════════════════════════════════╩═══════════════════════════» 0 » « ┌───────────────┐ «q_0: ┤ U(0,π/2,-π/2) ├───■── « └───────────────┘ ┌─┴─┐ «q_1: ──────────────────┤ X ├ « ┌────────────────┐└───┘ «q_2: ┤ Delay(700[dt]) ├───── « └────────────────┘ «c: 1/═══════════════════════ """ dd_sequence = [XGate()] pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence), ]) midmeas_dd = pm.run(self.midmeas) combined_u = UGate(0, pi / 2, -pi / 2) expected = QuantumCircuit(3, 1) expected.cx(0, 1) expected.delay(625, 0) expected.x(0) expected.delay(625, 0) expected.compose(combined_u, [0], inplace=True) expected.delay(700, 2) expected.cx(1, 2) expected.delay(1000, 1) expected.measure(2, 0) expected.cx(1, 2) expected.cx(0, 1) expected.delay(700, 2) expected.global_phase = 4.71238898038469 self.assertEqual(midmeas_dd, expected) # check the absorption into U was done correctly self.assertEqual(Operator(combined_u), Operator(XGate()) & Operator(XGate()))
def test_dd_can_sequentially_called(self): """Test if sequentially called DD pass can output the same circuit. This test verifies: - if global phase is properly propagated from the previous padding node. - if node_start_time property is properly updated for new dag circuit. """ dd_sequence = [XGate(), YGate(), XGate(), YGate()] pm1 = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence, qubits=[0]), PadDynamicalDecoupling(self.durations, dd_sequence, qubits=[1]), ]) circ1 = pm1.run(self.ghz4) pm2 = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence, qubits=[0, 1]), ]) circ2 = pm2.run(self.ghz4) self.assertEqual(circ1, circ2)
def unroll_and_map_circuit(self, circuit: QuantumCircuit, mapping, backend) -> QuantumCircuit: layout = Layout({q: i for q, i in zip(circuit.qubits, mapping)}) pm = PassManager([ SetLayout(layout), ApplyLayout(), Unroller(self._backend.configuration().basis_gates), ]) # pm = level_0_pass_manager(PassManagerConfig( # initial_layout = layout, # basis_gates=backend.configuration().basis_gates, # coupling_map=CouplingMap(backend.configuration().coupling_map), # backend_properties=backend.properties() # )) return pm.run(circuit)
def test_insert_dd_ghz(self): """Test DD gates are inserted in correct spots. ┌───┐ ┌────────────────┐ ┌───┐ » q_0: ──────┤ H ├─────────■──┤ Delay(100[dt]) ├──────┤ X ├──────» ┌─────┴───┴─────┐ ┌─┴─┐└────────────────┘┌─────┴───┴─────┐» q_1: ┤ Delay(50[dt]) ├─┤ X ├────────■─────────┤ Delay(50[dt]) ├» ├───────────────┴┐└───┘ ┌─┴─┐ └───────────────┘» q_2: ┤ Delay(750[dt]) ├───────────┤ X ├───────────────■────────» ├────────────────┤ └───┘ ┌─┴─┐ » q_3: ┤ Delay(950[dt]) ├─────────────────────────────┤ X ├──────» └────────────────┘ └───┘ » « ┌────────────────┐ ┌───┐ ┌────────────────┐ «q_0: ┤ Delay(200[dt]) ├──────┤ X ├───────┤ Delay(100[dt]) ├───────────────── « └─────┬───┬──────┘┌─────┴───┴──────┐└─────┬───┬──────┘┌───────────────┐ «q_1: ──────┤ X ├───────┤ Delay(100[dt]) ├──────┤ X ├───────┤ Delay(50[dt]) ├ « └───┘ └────────────────┘ └───┘ └───────────────┘ «q_2: ─────────────────────────────────────────────────────────────────────── « «q_3: ─────────────────────────────────────────────────────────────────────── « """ dd_sequence = [XGate(), XGate()] pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence), ]) ghz4_dd = pm.run(self.ghz4) expected = self.ghz4.copy() expected = expected.compose(Delay(50), [1], front=True) expected = expected.compose(Delay(750), [2], front=True) expected = expected.compose(Delay(950), [3], front=True) expected = expected.compose(Delay(100), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(200), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(100), [0]) expected = expected.compose(Delay(50), [1]) expected = expected.compose(XGate(), [1]) expected = expected.compose(Delay(100), [1]) expected = expected.compose(XGate(), [1]) expected = expected.compose(Delay(50), [1]) self.assertEqual(ghz4_dd, expected)
def test_c_if_on_different_qubits(self, schedule_pass): """Test if ALAP/ASAP schedules circuits with `c_if`s on different qubits. (input) ┌─┐ q_0: ┤M├────────────────────── └╥┘ ┌───┐ q_1: ─╫────┤ X ├────────────── ║ └─╥─┘ ┌───┐ q_2: ─╫──────╫────────┤ X ├─── ║ ║ └─╥─┘ ║ ┌────╨────┐┌────╨────┐ c: 1/═╩═╡ c_0 = T ╞╡ c_0 = T ╞ 0 └─────────┘└─────────┘ (scheduled) ┌─┐┌────────────────┐ q_0: ───────────────────┤M├┤ Delay(200[dt]) ├─────────── ┌─────────────────┐└╥┘└─────┬───┬──────┘ q_1: ┤ Delay(1000[dt]) ├─╫───────┤ X ├────────────────── ├─────────────────┤ ║ └─╥─┘ ┌───┐ q_2: ┤ Delay(1000[dt]) ├─╫─────────╫────────────┤ X ├─── └─────────────────┘ ║ ║ └─╥─┘ ║ ┌────╨────┐ ┌────╨────┐ c: 1/════════════════════╩════╡ c_0=0x1 ╞════╡ c_0=0x1 ╞ 0 └─────────┘ └─────────┘ """ qc = QuantumCircuit(3, 1) qc.measure(0, 0) qc.x(1).c_if(0, True) qc.x(2).c_if(0, True) durations = InstructionDurations([("x", None, 200), ("measure", None, 1000)]) pm = PassManager([schedule_pass(durations), PadDelay()]) scheduled = pm.run(qc) expected = QuantumCircuit(3, 1) expected.measure(0, 0) expected.delay(1000, 1) expected.delay(1000, 2) expected.x(1).c_if(0, True) expected.x(2).c_if(0, True) expected.delay(200, 0) self.assertEqual(expected, scheduled)
def test_measure_after_c_if(self, schedule_pass): """Test if ALAP/ASAP schedules circuits with c_if after measure with a common clbit. (input) ┌─┐ q_0: ┤M├────────────── └╥┘ ┌───┐ q_1: ─╫────┤ X ├────── ║ └─╥─┘ ┌─┐ q_2: ─╫──────╫─────┤M├ ║ ┌────╨────┐└╥┘ c: 1/═╩═╡ c_0 = T ╞═╩═ 0 └─────────┘ 0 (scheduled) ┌─┐┌─────────────────┐ q_0: ───────────────────┤M├┤ Delay(1000[dt]) ├────────────────── ┌─────────────────┐└╥┘└──────┬───┬──────┘┌────────────────┐ q_1: ┤ Delay(1000[dt]) ├─╫────────┤ X ├───────┤ Delay(800[dt]) ├ ├─────────────────┤ ║ └─╥─┘ └──────┬─┬───────┘ q_2: ┤ Delay(1000[dt]) ├─╫──────────╫────────────────┤M├──────── └─────────────────┘ ║ ┌────╨────┐ └╥┘ c: 1/════════════════════╩═════╡ c_0=0x1 ╞════════════╩═════════ 0 └─────────┘ 0 """ qc = QuantumCircuit(3, 1) qc.measure(0, 0) qc.x(1).c_if(0, 1) qc.measure(2, 0) durations = InstructionDurations([("x", None, 200), ("measure", None, 1000)]) pm = PassManager([schedule_pass(durations), PadDelay()]) scheduled = pm.run(qc) expected = QuantumCircuit(3, 1) expected.delay(1000, 1) expected.delay(1000, 2) expected.measure(0, 0) expected.x(1).c_if(0, 1) expected.measure(2, 0) expected.delay(1000, 0) expected.delay(800, 1) self.assertEqual(expected, scheduled)
def test_dag_introduces_extra_dependency_between_conditionals(self): """Test dependency between conditional operations in the scheduling. In the below example circuit, the conditional x on q1 could start at time 0, however it must be scheduled after the conditional x on q0 in ASAP scheduling. That is because circuit model used in the transpiler passes (DAGCircuit) interprets instructions acting on common clbits must be run in the order given by the original circuit (QuantumCircuit). (input) ┌────────────────┐ ┌───┐ q_0: ┤ Delay(100[dt]) ├───┤ X ├─── └─────┬───┬──────┘ └─╥─┘ q_1: ──────┤ X ├────────────╫───── └─╥─┘ ║ ┌────╨────┐ ┌────╨────┐ c: 1/═══╡ c_0=0x1 ╞════╡ c_0=0x1 ╞ └─────────┘ └─────────┘ (ASAP scheduled) ┌────────────────┐ ┌───┐ q_0: ┤ Delay(100[dt]) ├───┤ X ├────────────── ├────────────────┤ └─╥─┘ ┌───┐ q_1: ┤ Delay(100[dt]) ├─────╫────────┤ X ├─── └────────────────┘ ║ └─╥─┘ ┌────╨────┐┌────╨────┐ c: 1/══════════════════╡ c_0=0x1 ╞╡ c_0=0x1 ╞ └─────────┘└─────────┘ """ qc = QuantumCircuit(2, 1) qc.delay(100, 0) qc.x(0).c_if(0, True) qc.x(1).c_if(0, True) durations = InstructionDurations([("x", None, 160)]) pm = PassManager([ASAPScheduleAnalysis(durations), PadDelay()]) scheduled = pm.run(qc) expected = QuantumCircuit(2, 1) expected.delay(100, 0) expected.delay(100, 1) # due to extra dependency on clbits expected.x(0).c_if(0, True) expected.x(1).c_if(0, True) self.assertEqual(expected, scheduled)
def test_asymmetric_xy4_in_t2(self): """Test insertion of XY4 sequence with unbalanced spacing. global phase: π ┌───┐┌───┐┌────────────────┐┌───┐┌────────────────┐┌───┐┌────────────────┐» q_0: ┤ H ├┤ X ├┤ Delay(450[dt]) ├┤ Y ├┤ Delay(450[dt]) ├┤ X ├┤ Delay(450[dt]) ├» └───┘└───┘└────────────────┘└───┘└────────────────┘└───┘└────────────────┘» « ┌───┐┌────────────────┐┌───┐ «q_0: ┤ Y ├┤ Delay(450[dt]) ├┤ H ├ « └───┘└────────────────┘└───┘ """ dd_sequence = [XGate(), YGate()] * 2 spacing = [0] + [1 / 4] * 4 pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence, spacing=spacing), ]) t2 = QuantumCircuit(1) t2.h(0) t2.delay(2000, 0) t2.h(0) expected = QuantumCircuit(1) expected.h(0) expected.x(0) expected.delay(450, 0) expected.y(0) expected.delay(450, 0) expected.x(0) expected.delay(450, 0) expected.y(0) expected.delay(450, 0) expected.h(0) expected.global_phase = pi t2_dd = pm.run(t2) self.assertEqual(t2_dd, expected) # check global phase is correct self.assertEqual(Operator(t2), Operator(expected))
def test_dd_after_reset(self): """Test skip_reset_qubits option works. ┌─────────────────┐┌───┐┌────────────────┐┌───┐┌─────────────────┐» q_0: ─|0>─┤ Delay(1000[dt]) ├┤ H ├┤ Delay(190[dt]) ├┤ X ├┤ Delay(1710[dt]) ├» └─────────────────┘└───┘└────────────────┘└───┘└─────────────────┘» « ┌───┐┌───┐ «q_0: ┤ X ├┤ H ├ « └───┘└───┘ """ dd_sequence = [XGate(), XGate()] spacing = [0.1, 0.9] pm = PassManager( [ ALAPSchedule(self.durations), DynamicalDecoupling( self.durations, dd_sequence, spacing=spacing, skip_reset_qubits=True ), ] ) t2 = QuantumCircuit(1) t2.reset(0) t2.delay(1000) t2.h(0) t2.delay(2000, 0) t2.h(0) expected = QuantumCircuit(1) expected.reset(0) expected.delay(1000) expected.h(0) expected.delay(190, 0) expected.x(0) expected.delay(1710, 0) expected.x(0) expected.h(0) t2_dd = pm.run(t2) self.assertEqual(t2_dd, expected)
def test_measure_after_measure(self, schedule_pass): """Test if ALAP/ASAP schedules circuits with measure after measure with a common clbit. See: https://github.com/Qiskit/qiskit-terra/issues/7006 (input) ┌───┐┌─┐ q_0: ┤ X ├┤M├─── └───┘└╥┘┌─┐ q_1: ──────╫─┤M├ ║ └╥┘ c: 1/══════╩══╩═ 0 0 (scheduled) ┌───┐ ┌─┐ q_0: ──────┤ X ├───────┤M├─── ┌─────┴───┴──────┐└╥┘┌─┐ q_1: ┤ Delay(200[dt]) ├─╫─┤M├ └────────────────┘ ║ └╥┘ c: 1/═══════════════════╩══╩═ 0 0 """ qc = QuantumCircuit(2, 1) qc.x(0) qc.measure(0, 0) qc.measure(1, 0) durations = InstructionDurations([("x", None, 200), ("measure", None, 1000)]) pm = PassManager(schedule_pass(durations)) scheduled = pm.run(qc) expected = QuantumCircuit(2, 1) expected.x(0) expected.measure(0, 0) expected.delay( 200, 1) # 2nd measure starts at the same time as 1st measure starts expected.measure(1, 0) self.assertEqual(expected, scheduled)
def test_classically_controlled_gate_after_measure(self, schedule_pass): """Test if ALAP/ASAP schedules circuits with c_if after measure with a common clbit. See: https://github.com/Qiskit/qiskit-terra/issues/7006 (input) ┌─┐ q_0: ┤M├─────────── └╥┘ ┌───┐ q_1: ─╫────┤ X ├─── ║ └─╥─┘ ║ ┌────╨────┐ c: 1/═╩═╡ c_0 = T ╞ 0 └─────────┘ (scheduled) ┌─┐┌────────────────┐ q_0: ───────────────────┤M├┤ Delay(200[dt]) ├ ┌─────────────────┐└╥┘└─────┬───┬──────┘ q_1: ┤ Delay(1000[dt]) ├─╫───────┤ X ├─────── └─────────────────┘ ║ └─╥─┘ ║ ┌────╨────┐ c: 1/════════════════════╩════╡ c_0 = T ╞════ 0 └─────────┘ """ qc = QuantumCircuit(2, 1) qc.measure(0, 0) qc.x(1).c_if(0, True) durations = InstructionDurations([("x", None, 200), ("measure", None, 1000)]) pm = PassManager(schedule_pass(durations)) scheduled = pm.run(qc) expected = QuantumCircuit(2, 1) expected.measure(0, 0) expected.delay(200, 0) expected.delay(1000, 1) # x.c_if starts after measure expected.x(1).c_if(0, True) self.assertEqual(expected, scheduled)
def test_shorter_measure_after_measure(self, schedule_pass): """Test if ALAP/ASAP schedules circuits with shorter measure after measure with a common clbit. (input) ┌─┐ q_0: ┤M├─── └╥┘┌─┐ q_1: ─╫─┤M├ ║ └╥┘ c: 1/═╩══╩═ 0 0 (scheduled) ┌─┐┌────────────────┐ q_0: ───────────────────┤M├┤ Delay(700[dt]) ├ ┌─────────────────┐└╥┘└──────┬─┬───────┘ q_1: ┤ Delay(1000[dt]) ├─╫────────┤M├──────── └─────────────────┘ ║ └╥┘ c: 1/════════════════════╩═════════╩═════════ 0 0 """ qc = QuantumCircuit(2, 1) qc.measure(0, 0) qc.measure(1, 0) durations = InstructionDurations([("measure", [0], 1000), ("measure", [1], 700)]) pm = PassManager([schedule_pass(durations), PadDelay()]) scheduled = pm.run(qc) expected = QuantumCircuit(2, 1) expected.measure(0, 0) expected.delay(1000, 1) expected.measure(1, 0) expected.delay(700, 0) self.assertEqual(expected, scheduled)
def test_insert_dd_ghz_xy4(self): """Test XY4 sequence of DD gates. ┌───┐ ┌───────────────┐ ┌───┐ ┌───────────────┐» q_0: ──────┤ H ├─────────■──┤ Delay(37[dt]) ├──────┤ X ├──────┤ Delay(75[dt]) ├» ┌─────┴───┴─────┐ ┌─┴─┐└───────────────┘┌─────┴───┴─────┐└─────┬───┬─────┘» q_1: ┤ Delay(50[dt]) ├─┤ X ├────────■────────┤ Delay(12[dt]) ├──────┤ X ├──────» ├───────────────┴┐└───┘ ┌─┴─┐ └───────────────┘ └───┘ » q_2: ┤ Delay(750[dt]) ├───────────┤ X ├──────────────■─────────────────────────» ├────────────────┤ └───┘ ┌─┴─┐ » q_3: ┤ Delay(950[dt]) ├────────────────────────────┤ X ├───────────────────────» └────────────────┘ └───┘ » « ┌───┐ ┌───────────────┐ ┌───┐ ┌───────────────┐» «q_0: ──────┤ Y ├──────┤ Delay(76[dt]) ├──────┤ X ├──────┤ Delay(75[dt]) ├» « ┌─────┴───┴─────┐└─────┬───┬─────┘┌─────┴───┴─────┐└─────┬───┬─────┘» «q_1: ┤ Delay(25[dt]) ├──────┤ Y ├──────┤ Delay(26[dt]) ├──────┤ X ├──────» « └───────────────┘ └───┘ └───────────────┘ └───┘ » «q_2: ────────────────────────────────────────────────────────────────────» « » «q_3: ────────────────────────────────────────────────────────────────────» « » « ┌───┐ ┌───────────────┐ «q_0: ──────┤ Y ├──────┤ Delay(37[dt]) ├───────────────── « ┌─────┴───┴─────┐└─────┬───┬─────┘┌───────────────┐ «q_1: ┤ Delay(25[dt]) ├──────┤ Y ├──────┤ Delay(12[dt]) ├ « └───────────────┘ └───┘ └───────────────┘ «q_2: ─────────────────────────────────────────────────── « «q_3: ─────────────────────────────────────────────────── """ dd_sequence = [XGate(), YGate(), XGate(), YGate()] pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence), ]) ghz4_dd = pm.run(self.ghz4) expected = self.ghz4.copy() expected = expected.compose(Delay(50), [1], front=True) expected = expected.compose(Delay(750), [2], front=True) expected = expected.compose(Delay(950), [3], front=True) expected = expected.compose(Delay(37), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(75), [0]) expected = expected.compose(YGate(), [0]) expected = expected.compose(Delay(76), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(75), [0]) expected = expected.compose(YGate(), [0]) expected = expected.compose(Delay(37), [0]) expected = expected.compose(Delay(12), [1]) expected = expected.compose(XGate(), [1]) expected = expected.compose(Delay(25), [1]) expected = expected.compose(YGate(), [1]) expected = expected.compose(Delay(26), [1]) expected = expected.compose(XGate(), [1]) expected = expected.compose(Delay(25), [1]) expected = expected.compose(YGate(), [1]) expected = expected.compose(Delay(12), [1]) self.assertEqual(ghz4_dd, expected)
def test_parallel_gate_different_length(self): """Test circuit having two parallel instruction with different length. (input) ┌───┐┌─┐ q_0: ┤ X ├┤M├─── ├───┤└╥┘┌─┐ q_1: ┤ X ├─╫─┤M├ └───┘ ║ └╥┘ c: 2/══════╩══╩═ 0 1 (expected, ALAP) ┌────────────────┐┌───┐┌─┐ q_0: ┤ Delay(200[dt]) ├┤ X ├┤M├ └─────┬───┬──────┘└┬─┬┘└╥┘ q_1: ──────┤ X ├────────┤M├──╫─ └───┘ └╥┘ ║ c: 2/════════════════════╩═══╩═ 1 0 (expected, ASAP) ┌───┐┌─┐┌────────────────┐ q_0: ┤ X ├┤M├┤ Delay(200[dt]) ├ ├───┤└╥┘└──────┬─┬───────┘ q_1: ┤ X ├─╫────────┤M├──────── └───┘ ║ └╥┘ c: 2/══════╩═════════╩═════════ 0 1 """ qc = QuantumCircuit(2, 2) qc.x(0) qc.x(1) qc.measure(0, 0) qc.measure(1, 1) durations = InstructionDurations([("x", [0], 200), ("x", [1], 400), ("measure", None, 1000)]) pm = PassManager(ALAPSchedule(durations)) qc_alap = pm.run(qc) alap_expected = QuantumCircuit(2, 2) alap_expected.delay(200, 0) alap_expected.x(0) alap_expected.x(1) alap_expected.measure(0, 0) alap_expected.measure(1, 1) self.assertEqual(qc_alap, alap_expected) pm = PassManager(ASAPSchedule(durations)) qc_asap = pm.run(qc) asap_expected = QuantumCircuit(2, 2) asap_expected.x(0) asap_expected.x(1) asap_expected.measure(0, 0) # immediately start after X gate asap_expected.measure(1, 1) asap_expected.delay(200, 0) self.assertEqual(qc_asap, asap_expected)
def test_parallel_gate_different_length_with_barrier(self): """Test circuit having two parallel instruction with different length with barrier. (input) ┌───┐┌─┐ q_0: ┤ X ├┤M├─── ├───┤└╥┘┌─┐ q_1: ┤ X ├─╫─┤M├ └───┘ ║ └╥┘ c: 2/══════╩══╩═ 0 1 (expected, ALAP) ┌────────────────┐┌───┐ ░ ┌─┐ q_0: ┤ Delay(200[dt]) ├┤ X ├─░─┤M├─── └─────┬───┬──────┘└───┘ ░ └╥┘┌─┐ q_1: ──────┤ X ├─────────────░──╫─┤M├ └───┘ ░ ║ └╥┘ c: 2/═══════════════════════════╩══╩═ 0 1 (expected, ASAP) ┌───┐┌────────────────┐ ░ ┌─┐ q_0: ┤ X ├┤ Delay(200[dt]) ├─░─┤M├─── ├───┤└────────────────┘ ░ └╥┘┌─┐ q_1: ┤ X ├───────────────────░──╫─┤M├ └───┘ ░ ║ └╥┘ c: 2/═══════════════════════════╩══╩═ 0 1 """ qc = QuantumCircuit(2, 2) qc.x(0) qc.x(1) qc.barrier() qc.measure(0, 0) qc.measure(1, 1) durations = InstructionDurations([("x", [0], 200), ("x", [1], 400), ("measure", None, 1000)]) pm = PassManager([ALAPScheduleAnalysis(durations), PadDelay()]) qc_alap = pm.run(qc) alap_expected = QuantumCircuit(2, 2) alap_expected.delay(200, 0) alap_expected.x(0) alap_expected.x(1) alap_expected.barrier() alap_expected.measure(0, 0) alap_expected.measure(1, 1) self.assertEqual(qc_alap, alap_expected) pm = PassManager([ASAPScheduleAnalysis(durations), PadDelay()]) qc_asap = pm.run(qc) asap_expected = QuantumCircuit(2, 2) asap_expected.x(0) asap_expected.delay(200, 0) asap_expected.x(1) asap_expected.barrier() asap_expected.measure(0, 0) asap_expected.measure(1, 1) self.assertEqual(qc_asap, asap_expected)
def test_insert_dd_ghz_xy4_with_alignment(self): """Test DD with pulse alignment constraints. ┌───┐ ┌───────────────┐ ┌───┐ ┌───────────────┐» q_0: ──────┤ H ├─────────■──┤ Delay(40[dt]) ├──────┤ X ├──────┤ Delay(70[dt]) ├» ┌─────┴───┴─────┐ ┌─┴─┐└───────────────┘┌─────┴───┴─────┐└─────┬───┬─────┘» q_1: ┤ Delay(50[dt]) ├─┤ X ├────────■────────┤ Delay(20[dt]) ├──────┤ X ├──────» ├───────────────┴┐└───┘ ┌─┴─┐ └───────────────┘ └───┘ » q_2: ┤ Delay(750[dt]) ├───────────┤ X ├──────────────■─────────────────────────» ├────────────────┤ └───┘ ┌─┴─┐ » q_3: ┤ Delay(950[dt]) ├────────────────────────────┤ X ├───────────────────────» └────────────────┘ └───┘ » « ┌───┐ ┌───────────────┐ ┌───┐ ┌───────────────┐» «q_0: ──────┤ Y ├──────┤ Delay(70[dt]) ├──────┤ X ├──────┤ Delay(70[dt]) ├» « ┌─────┴───┴─────┐└─────┬───┬─────┘┌─────┴───┴─────┐└─────┬───┬─────┘» «q_1: ┤ Delay(20[dt]) ├──────┤ Y ├──────┤ Delay(20[dt]) ├──────┤ X ├──────» « └───────────────┘ └───┘ └───────────────┘ └───┘ » «q_2: ────────────────────────────────────────────────────────────────────» « » «q_3: ────────────────────────────────────────────────────────────────────» « » « ┌───┐ ┌───────────────┐ «q_0: ──────┤ Y ├──────┤ Delay(50[dt]) ├───────────────── « ┌─────┴───┴─────┐└─────┬───┬─────┘┌───────────────┐ «q_1: ┤ Delay(20[dt]) ├──────┤ Y ├──────┤ Delay(20[dt]) ├ « └───────────────┘ └───┘ └───────────────┘ «q_2: ─────────────────────────────────────────────────── « «q_3: ─────────────────────────────────────────────────── « """ dd_sequence = [XGate(), YGate(), XGate(), YGate()] pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling( self.durations, dd_sequence, pulse_alignment=10, extra_slack_distribution="edges", ), ]) ghz4_dd = pm.run(self.ghz4) expected = self.ghz4.copy() expected = expected.compose(Delay(50), [1], front=True) expected = expected.compose(Delay(750), [2], front=True) expected = expected.compose(Delay(950), [3], front=True) expected = expected.compose(Delay(40), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(70), [0]) expected = expected.compose(YGate(), [0]) expected = expected.compose(Delay(70), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(70), [0]) expected = expected.compose(YGate(), [0]) expected = expected.compose(Delay(50), [0]) expected = expected.compose(Delay(20), [1]) expected = expected.compose(XGate(), [1]) expected = expected.compose(Delay(20), [1]) expected = expected.compose(YGate(), [1]) expected = expected.compose(Delay(20), [1]) expected = expected.compose(XGate(), [1]) expected = expected.compose(Delay(20), [1]) expected = expected.compose(YGate(), [1]) expected = expected.compose(Delay(20), [1]) self.assertEqual(ghz4_dd, expected)
def test_insert_ghz_uhrig(self): """Test custom spacing (following Uhrig DD [1]). [1] Uhrig, G. "Keeping a quantum bit alive by optimized π-pulse sequences." Physical Review Letters 98.10 (2007): 100504. ┌───┐ ┌──────────────┐ ┌───┐ ┌──────────────┐┌───┐» q_0: ──────┤ H ├─────────■──┤ Delay(3[dt]) ├──────┤ X ├───────┤ Delay(8[dt]) ├┤ X ├» ┌─────┴───┴─────┐ ┌─┴─┐└──────────────┘┌─────┴───┴──────┐└──────────────┘└───┘» q_1: ┤ Delay(50[dt]) ├─┤ X ├───────■────────┤ Delay(300[dt]) ├─────────────────────» ├───────────────┴┐└───┘ ┌─┴─┐ └────────────────┘ » q_2: ┤ Delay(750[dt]) ├──────────┤ X ├──────────────■──────────────────────────────» ├────────────────┤ └───┘ ┌─┴─┐ » q_3: ┤ Delay(950[dt]) ├───────────────────────────┤ X ├────────────────────────────» └────────────────┘ └───┘ » « ┌───────────────┐┌───┐┌───────────────┐┌───┐┌───────────────┐┌───┐┌───────────────┐» «q_0: ┤ Delay(13[dt]) ├┤ X ├┤ Delay(16[dt]) ├┤ X ├┤ Delay(20[dt]) ├┤ X ├┤ Delay(16[dt]) ├» « └───────────────┘└───┘└───────────────┘└───┘└───────────────┘└───┘└───────────────┘» «q_1: ───────────────────────────────────────────────────────────────────────────────────» « » «q_2: ───────────────────────────────────────────────────────────────────────────────────» « » «q_3: ───────────────────────────────────────────────────────────────────────────────────» « » « ┌───┐┌───────────────┐┌───┐┌──────────────┐┌───┐┌──────────────┐ «q_0: ┤ X ├┤ Delay(13[dt]) ├┤ X ├┤ Delay(8[dt]) ├┤ X ├┤ Delay(3[dt]) ├ « └───┘└───────────────┘└───┘└──────────────┘└───┘└──────────────┘ «q_1: ──────────────────────────────────────────────────────────────── « «q_2: ──────────────────────────────────────────────────────────────── « «q_3: ──────────────────────────────────────────────────────────────── « """ n = 8 dd_sequence = [XGate()] * n # uhrig specifies the location of the k'th pulse def uhrig(k): return np.sin(np.pi * (k + 1) / (2 * n + 2))**2 # convert that to spacing between pulses (whatever finite duration pulses have) spacing = [] for k in range(n): spacing.append(uhrig(k) - sum(spacing)) spacing.append(1 - sum(spacing)) pm = PassManager([ ALAPScheduleAnalysis(self.durations), PadDynamicalDecoupling(self.durations, dd_sequence, qubits=[0], spacing=spacing), ]) ghz4_dd = pm.run(self.ghz4) expected = self.ghz4.copy() expected = expected.compose(Delay(50), [1], front=True) expected = expected.compose(Delay(750), [2], front=True) expected = expected.compose(Delay(950), [3], front=True) expected = expected.compose(Delay(3), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(8), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(13), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(16), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(20), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(16), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(13), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(8), [0]) expected = expected.compose(XGate(), [0]) expected = expected.compose(Delay(3), [0]) expected = expected.compose(Delay(300), [1]) self.assertEqual(ghz4_dd, expected)