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_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_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_active_reset_circuit(self, write_lat, cond_lat): """Test practical example of reset circuit. Because of the stimulus pulse overlap with the previous XGate on the q register, measure instruction is always triggered after XGate regardless of write latency. Thus only conditional latency matters in the scheduling. (input) ┌─┐ ┌───┐ ┌─┐ ┌───┐ ┌─┐ ┌───┐ q: ┤M├───┤ X ├───┤M├───┤ X ├───┤M├───┤ X ├─── └╥┘ └─╥─┘ └╥┘ └─╥─┘ └╥┘ └─╥─┘ ║ ┌────╨────┐ ║ ┌────╨────┐ ║ ┌────╨────┐ c: 1/═╩═╡ c_0=0x1 ╞═╩═╡ c_0=0x1 ╞═╩═╡ c_0=0x1 ╞ 0 └─────────┘ 0 └─────────┘ 0 └─────────┘ """ qc = QuantumCircuit(1, 1) qc.measure(0, 0) qc.x(0).c_if(0, 1) qc.measure(0, 0) qc.x(0).c_if(0, 1) qc.measure(0, 0) qc.x(0).c_if(0, 1) durations = InstructionDurations([("x", None, 100), ("measure", None, 1000)]) actual_asap = PassManager([ SetIOLatency(clbit_write_latency=write_lat, conditional_latency=cond_lat), ASAPScheduleAnalysis(durations), PadDelay(), ]).run(qc) actual_alap = PassManager([ SetIOLatency(clbit_write_latency=write_lat, conditional_latency=cond_lat), ALAPScheduleAnalysis(durations), PadDelay(), ]).run(qc) expected = QuantumCircuit(1, 1) expected.measure(0, 0) if cond_lat > 0: expected.delay(cond_lat, 0) expected.x(0).c_if(0, 1) expected.measure(0, 0) if cond_lat > 0: expected.delay(cond_lat, 0) expected.x(0).c_if(0, 1) expected.measure(0, 0) if cond_lat > 0: expected.delay(cond_lat, 0) expected.x(0).c_if(0, 1) self.assertEqual(expected, actual_asap) self.assertEqual(expected, actual_alap)
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 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_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_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_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 default_pass_manager_simulator(basis_gates): """ The default pass manager without a coupling map. Args: basis_gates (list[str]): list of basis gate names to unroll to. Returns: PassManager: A passmanager that just unrolls, without any optimization. """ pass_manager = PassManager() pass_manager.append(Unroller(basis_gates)) return pass_manager
def generate_pre_op_passmanager(target=None, coupling_map=None, remove_reset_in_zero=False): """Generate a pre-optimization loop :class:`~qiskit.transpiler.PassManager` This pass manager will check to ensure that directionality from the coupling map is respected Args: target (Target): the :class:`~.Target` object representing the backend coupling_map (CouplingMap): The coupling map to use remove_reset_in_zero (bool): If ``True`` include the remove reset in zero pass in the generated PassManager Returns: PassManager: The pass manager """ pre_opt = PassManager() if coupling_map: pre_opt.append(CheckGateDirection(coupling_map, target=target)) def _direction_condition(property_set): return not property_set["is_direction_mapped"] pre_opt.append([GateDirection(coupling_map, target=target)], condition=_direction_condition) if remove_reset_in_zero: pre_opt.append(RemoveResetInZeroState()) return pre_opt
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_no_pad_very_end_of_circuit(self): """Test padding option that inserts no delay at the very end of circuit. This circuit will be unchanged after ASAP-schedule/padding. ┌────────────────┐┌─┐ q_0: ┤ Delay(100[dt]) ├┤M├ └─────┬───┬──────┘└╥┘ q_1: ──────┤ X ├────────╫─ └───┘ ║ c: 1/═══════════════════╩═ 0 """ qc = QuantumCircuit(2, 1) qc.delay(100, 0) qc.x(1) qc.measure(0, 0) durations = InstructionDurations([("x", None, 160), ("measure", None, 1000)]) scheduled = PassManager([ ASAPScheduleAnalysis(durations), PadDelay(fill_very_end=False), ]).run(qc) self.assertEqual(scheduled, qc)
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_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_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_padding_not_working_without_scheduling(self): """Test padding fails when un-scheduled DAG is input.""" qc = QuantumCircuit(1, 1) qc.delay(100, 0) qc.x(0) qc.measure(0, 0) with self.assertRaises(TranspilerError): PassManager(PadDelay()).run(qc)
def setUp(self): coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]] coupling_map = CouplingMap(couplinglist=coupling) basis_gates = ['u1', 'u3', 'u2', 'cx'] qr = QuantumRegister(7, 'q') layout = Layout({qr[i]: i for i in range(coupling_map.size())}) # Create a pass manager with a variety of passes and flow control structures self.pass_manager = PassManager() self.pass_manager.append(SetLayout(layout)) self.pass_manager.append(TrivialLayout(coupling_map), condition=lambda x: True) self.pass_manager.append(FullAncillaAllocation(coupling_map)) self.pass_manager.append(EnlargeWithAncilla()) self.pass_manager.append(Unroller(basis_gates)) self.pass_manager.append(CheckMap(coupling_map)) self.pass_manager.append(BarrierBeforeFinalMeasurements(), do_while=lambda x: False) self.pass_manager.append(CXDirection(coupling_map)) self.pass_manager.append(RemoveResetInZeroState())
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 _layout_and_route_passmanager(self, initial_layout): """Return a passmanager for a full layout and routing. We use a factory to remove potential statefulness of passes. """ layout_and_route = [SetLayout(initial_layout), FullAncillaAllocation(self.coupling_map), EnlargeWithAncilla(), ApplyLayout(), self.routing_pass] pm = PassManager(layout_and_route) return pm
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 generate_embed_passmanager(coupling_map): """Generate a layout embedding :class:`~qiskit.transpiler.PassManager` This is used to generate a :class:`~qiskit.transpiler.PassManager` object that can be used to expand and apply an initial layout to a circuit Args: coupling_map (CouplingMap): The coupling map for the backend to embed the circuit to. Returns: PassManager: The embedding passmanager that assumes the layout property set has been set in earlier stages """ return PassManager([ FullAncillaAllocation(coupling_map), EnlargeWithAncilla(), ApplyLayout() ])
def generate_unroll_3q( target, basis_gates=None, approximation_degree=None, unitary_synthesis_method="default", unitary_synthesis_plugin_config=None, ): """Generate an unroll >3q :class:`~qiskit.transpiler.PassManager` Args: target (Target): the :class:`~.Target` object representing the backend basis_gates (list): A list of str gate names that represent the basis gates on the backend target approximation_degree (float): The heuristic approximation degree to use. Can be between 0 and 1. unitary_synthesis_method (str): The unitary synthesis method to use unitary_synthesis_plugin_config (dict): The optional dictionary plugin configuration, this is plugin specific refer to the specified plugin's documenation for how to use. Returns: PassManager: The unroll 3q or more pass manager """ unroll_3q = PassManager() unroll_3q.append( UnitarySynthesis( basis_gates, approximation_degree=approximation_degree, method=unitary_synthesis_method, min_qubits=3, plugin_config=unitary_synthesis_plugin_config, target=target, )) unroll_3q.append(HighLevelSynthesis()) unroll_3q.append(Unroll3qOrMore(target=target, basis_gates=basis_gates)) return unroll_3q
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 default_pass_manager_simulator(basis_gates): """ The default pass manager without a coupling map. Args: basis_gates (list[str]): list of basis gate names to unroll to. Returns: PassManager: A passmanager that just unrolls, without any optimization. """ pass_manager = PassManager() pass_manager.append(Unroller(basis_gates)) pass_manager.append( [RemoveResetInZeroState(), Depth(), FixedPoint('depth')], do_while=lambda property_set: not property_set['depth_fixed_point']) return pass_manager