class TestScheduledCircuit(QiskitTestCase): """Test scheduled circuit (quantum circuit with duration).""" def setUp(self): super().setUp() self.backend_with_dt = FakeParis() self.backend_without_dt = FakeParis() delattr(self.backend_without_dt.configuration(), 'dt') self.dt = 2.2222222222222221e-10 def test_schedule_circuit_when_backend_tells_dt(self): """dt is known to transpiler by backend""" qc = QuantumCircuit(2) qc.delay(0.1, 0, unit='ms') # 450000[dt] qc.delay(100, 0, unit='ns') # 450[dt] qc.h(0) # 160[dt] qc.h(1) # 160[dt] sc = transpile(qc, self.backend_with_dt, scheduling_method='alap') self.assertEqual(sc.duration, 450610) self.assertEqual(sc.unit, 'dt') self.assertEqual(sc.data[1][0].name, "delay") self.assertEqual(sc.data[1][0].duration, 450) self.assertEqual(sc.data[1][0].unit, 'dt') self.assertEqual(sc.data[2][0].name, "rz") self.assertEqual(sc.data[2][0].duration, 0) self.assertEqual(sc.data[2][0].unit, 'dt') self.assertEqual(sc.data[5][0].name, "delay") self.assertEqual(sc.data[5][0].duration, 450450) self.assertEqual(sc.data[5][0].unit, 'dt') qobj = assemble(sc, self.backend_with_dt) self.assertEqual(qobj.experiments[0].instructions[1].name, "delay") self.assertEqual(qobj.experiments[0].instructions[1].params[0], 450) self.assertEqual(qobj.experiments[0].instructions[5].name, "delay") self.assertEqual(qobj.experiments[0].instructions[5].params[0], 450450) def test_schedule_circuit_when_transpile_option_tells_dt(self): """dt is known to transpiler by transpile option""" qc = QuantumCircuit(2) qc.delay(0.1, 0, unit='ms') # 450000[dt] qc.delay(100, 0, unit='ns') # 450[dt] qc.h(0) qc.h(1) sc = transpile(qc, self.backend_without_dt, scheduling_method='alap', dt=self.dt) self.assertEqual(sc.duration, 450610) self.assertEqual(sc.unit, 'dt') self.assertEqual(sc.data[1][0].name, "delay") self.assertEqual(sc.data[1][0].duration, 450) self.assertEqual(sc.data[1][0].unit, 'dt') self.assertEqual(sc.data[2][0].name, "rz") self.assertEqual(sc.data[2][0].duration, 0) self.assertEqual(sc.data[2][0].unit, 'dt') self.assertEqual(sc.data[5][0].name, "delay") self.assertEqual(sc.data[5][0].duration, 450450) self.assertEqual(sc.data[5][0].unit, 'dt') def test_schedule_circuit_in_sec_when_no_one_tells_dt(self): """dt is unknown and all delays and gate times are in SI""" qc = QuantumCircuit(2) qc.delay(0.1, 0, unit='ms') qc.delay(100, 0, unit='ns') qc.h(0) qc.h(1) sc = transpile(qc, self.backend_without_dt, scheduling_method='alap') self.assertAlmostEqual(sc.duration, 450610 * self.dt) self.assertEqual(sc.unit, 's') self.assertEqual(sc.data[1][0].name, "delay") self.assertAlmostEqual(sc.data[1][0].duration, 1.0e-7) self.assertEqual(sc.data[1][0].unit, 's') self.assertEqual(sc.data[2][0].name, "rz") self.assertAlmostEqual(sc.data[2][0].duration, 160 * self.dt) self.assertEqual(sc.data[2][0].unit, 's') self.assertEqual(sc.data[5][0].name, "delay") self.assertAlmostEqual(sc.data[5][0].duration, 1.0e-4 + 1.0e-7) self.assertEqual(sc.data[5][0].unit, 's') with self.assertRaises(QiskitError): assemble(sc, self.backend_without_dt) def test_cannot_schedule_circuit_with_mixed_SI_and_dt_when_no_one_tells_dt( self): """dt is unknown but delays and gate times have a mix of SI and dt""" qc = QuantumCircuit(2) qc.delay(100, 0, unit='ns') qc.delay(30, 0, unit='dt') qc.h(0) qc.h(1) with self.assertRaises(QiskitError): transpile(qc, self.backend_without_dt, scheduling_method='alap') def test_transpile_single_delay_circuit(self): qc = QuantumCircuit(1) qc.delay(1234, 0) sc = transpile(qc, backend=self.backend_with_dt, scheduling_method='alap') self.assertEqual(sc.duration, 1234) self.assertEqual(sc.data[0][0].name, "delay") self.assertEqual(sc.data[0][0].duration, 1234) self.assertEqual(sc.data[0][0].unit, 'dt') def test_transpile_t1_circuit(self): qc = QuantumCircuit(1) qc.x(0) # 320 [dt] qc.delay(1000, 0, unit='ns') # 4500 [dt] qc.measure_all() # 19584 [dt] scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='alap') self.assertEqual(scheduled.duration, 23060) def test_transpile_delay_circuit_with_backend(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(100, 1, unit='ns') # 450 [dt] qc.cx(0, 1) # 1760 [dt] scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='alap') self.assertEqual(scheduled.duration, 2082) def test_transpile_delay_circuit_without_backend(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) scheduled = transpile(qc, scheduling_method='alap', instruction_durations=[('h', 0, 200), ('cx', [0, 1], 700)]) self.assertEqual(scheduled.duration, 1200) def test_transpile_circuit_with_custom_instruction(self): """See: https://github.com/Qiskit/qiskit-terra/issues/5154""" bell = QuantumCircuit(2, name="bell") bell.h(0) bell.cx(0, 1) qc = QuantumCircuit(2) qc.delay(500, 1) qc.append(bell.to_instruction(), [0, 1]) scheduled = transpile(qc, scheduling_method='alap', instruction_durations=[('bell', [0, 1], 1000)]) self.assertEqual(scheduled.duration, 1500) def test_transpile_delay_circuit_without_scheduling_method(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) transpiled = transpile(qc, backend=self.backend_with_dt) self.assertEqual(transpiled.duration, 2132) def test_transpile_delay_circuit_without_scheduling_method_or_durs(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) with self.assertRaises(TranspilerError): transpile(qc) def test_raise_error_if_transpile_with_scheduling_method_but_without_durations( self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) with self.assertRaises(TranspilerError): transpile(qc, scheduling_method="alap") def test_invalidate_schedule_circuit_if_new_instruction_is_appended(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500 * self.dt, 1, 's') qc.cx(0, 1) scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='alap') # append a gate to a scheduled circuit scheduled.h(0) self.assertEqual(scheduled.duration, None) def test_default_units_for_my_own_duration_users(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) # accept None for qubits scheduled = transpile(qc, basis_gates=['h', 'cx', 'delay'], scheduling_method='alap', instruction_durations=[('h', 0, 200), ('cx', None, 900)]) self.assertEqual(scheduled.duration, 1400) # prioritize specified qubits over None scheduled = transpile(qc, basis_gates=['h', 'cx', 'delay'], scheduling_method='alap', instruction_durations=[('h', 0, 200), ('cx', None, 900), ('cx', [0, 1], 800)]) self.assertEqual(scheduled.duration, 1300) def test_unit_seconds_when_using_backend_durations(self): qc = QuantumCircuit(2) qc.h(0) qc.delay(500 * self.dt, 1, 's') qc.cx(0, 1) # usual case scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='alap') self.assertEqual(scheduled.duration, 2132) # update durations durations = InstructionDurations.from_backend(self.backend_with_dt) durations.update([('cx', [0, 1], 1000 * self.dt, 's')]) scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='alap', instruction_durations=durations) self.assertEqual(scheduled.duration, 1500) def test_per_qubit_durations(self): """See: https://github.com/Qiskit/qiskit-terra/issues/5109""" qc = QuantumCircuit(3) qc.h(0) qc.delay(500, 1) qc.cx(0, 1) qc.h(1) sc = transpile(qc, scheduling_method='alap', instruction_durations=[('h', None, 200), ('cx', [0, 1], 700)]) self.assertEqual(sc.qubit_start_time(0), 300) self.assertEqual(sc.qubit_stop_time(0), 1200) self.assertEqual(sc.qubit_start_time(1), 500) self.assertEqual(sc.qubit_stop_time(1), 1400) self.assertEqual(sc.qubit_start_time(2), 0) self.assertEqual(sc.qubit_stop_time(2), 0) self.assertEqual(sc.qubit_start_time(0, 1), 300) self.assertEqual(sc.qubit_stop_time(0, 1), 1400) qc.measure_all() sc = transpile(qc, scheduling_method='alap', instruction_durations=[('h', None, 200), ('cx', [0, 1], 700), ('measure', None, 1000)]) q = sc.qubits self.assertEqual(sc.qubit_start_time(q[0]), 300) self.assertEqual(sc.qubit_stop_time(q[0]), 2400) self.assertEqual(sc.qubit_start_time(q[1]), 500) self.assertEqual(sc.qubit_stop_time(q[1]), 2400) self.assertEqual(sc.qubit_start_time(q[2]), 1400) self.assertEqual(sc.qubit_stop_time(q[2]), 2400) self.assertEqual(sc.qubit_start_time(*q), 300) self.assertEqual(sc.qubit_stop_time(*q), 2400) def test_change_dt_in_transpile(self): qc = QuantumCircuit(1, 1) qc.x(0) qc.measure(0, 0) # default case scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='asap') org_duration = scheduled.duration # halve dt in sec = double duration in dt scheduled = transpile(qc, backend=self.backend_with_dt, scheduling_method='asap', dt=self.dt / 2) self.assertEqual(scheduled.duration, org_duration * 2) @data('asap', 'alap') def test_duration_on_same_instruction_instance(self, scheduling_method): """See: https://github.com/Qiskit/qiskit-terra/issues/5771""" assert (self.backend_with_dt.properties().gate_length('cx', (0, 1)) != self.backend_with_dt.properties().gate_length('cx', (1, 2))) qc = QuantumCircuit(3) qc.cz(0, 1) qc.cz(1, 2) sc = transpile(qc, backend=self.backend_with_dt, scheduling_method=scheduling_method) cxs = [inst for inst, _, _ in sc.data if inst.name == 'cx'] self.assertNotEqual(cxs[0].duration, cxs[1].duration)