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
     self.simulator_backend = BasicAer.get_backend("qasm_simulator")
 def setUp(self):
     super().setUp()
     self.backend_with_dt = FakeParis()
     self.backend_without_dt = FakeVigo()
     self.dt = 2.2222222222222221e-10
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
        self.simulator_backend = BasicAer.get_backend("qasm_simulator")

    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", layout_method="trivial")
        self.assertEqual(sc.duration, 450610)
        self.assertEqual(sc.unit, "dt")
        self.assertEqual(sc.data[0][0].name, "delay")
        self.assertEqual(sc.data[0][0].duration, 450450)
        self.assertEqual(sc.data[0][0].unit, "dt")
        self.assertEqual(sc.data[1][0].name, "rz")
        self.assertEqual(sc.data[1][0].duration, 0)
        self.assertEqual(sc.data[1][0].unit, "dt")
        self.assertEqual(sc.data[4][0].name, "delay")
        self.assertEqual(sc.data[4][0].duration, 450450)
        self.assertEqual(sc.data[4][0].unit, "dt")
        qobj = assemble(sc, self.backend_with_dt)
        self.assertEqual(qobj.experiments[0].instructions[0].name, "delay")
        self.assertEqual(qobj.experiments[0].instructions[0].params[0], 450450)
        self.assertEqual(qobj.experiments[0].instructions[4].name, "delay")
        self.assertEqual(qobj.experiments[0].instructions[4].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,
            layout_method="trivial",
        )
        self.assertEqual(sc.duration, 450610)
        self.assertEqual(sc.unit, "dt")
        self.assertEqual(sc.data[0][0].name, "delay")
        self.assertEqual(sc.data[0][0].duration, 450450)
        self.assertEqual(sc.data[0][0].unit, "dt")
        self.assertEqual(sc.data[1][0].name, "rz")
        self.assertEqual(sc.data[1][0].duration, 0)
        self.assertEqual(sc.data[1][0].unit, "dt")
        self.assertEqual(sc.data[4][0].name, "delay")
        self.assertEqual(sc.data[4][0].duration, 450450)
        self.assertEqual(sc.data[4][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", layout_method="trivial"
        )
        self.assertAlmostEqual(sc.duration, 450610 * self.dt)
        self.assertEqual(sc.unit, "s")
        self.assertEqual(sc.data[0][0].name, "delay")
        self.assertAlmostEqual(sc.data[0][0].duration, 1.0e-4 + 1.0e-7)
        self.assertEqual(sc.data[0][0].unit, "s")
        self.assertEqual(sc.data[1][0].name, "rz")
        self.assertAlmostEqual(sc.data[1][0].duration, 160 * self.dt)
        self.assertEqual(sc.data[1][0].unit, "s")
        self.assertEqual(sc.data[4][0].name, "delay")
        self.assertAlmostEqual(sc.data[4][0].duration, 1.0e-4 + 1.0e-7)
        self.assertEqual(sc.data[4][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", layout_method="trivial"
        )
        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_with_dt_but_without_scheduling_method(self):
        qc = QuantumCircuit(1)
        qc.delay(100, 0, unit="ns")
        transpiled = transpile(qc, backend=self.backend_with_dt)
        self.assertEqual(transpiled.duration, None)  # not scheduled
        self.assertEqual(transpiled.data[0][0].duration, 450)  # time unit is converted ns -> dt

    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)
        not_scheduled = transpile(qc)
        self.assertEqual(not_scheduled.duration, None)

    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", layout_method="trivial"
        )
        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,
            layout_method="trivial",
        )
        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)

    def test_transpile_and_assemble_delay_circuit_for_simulator(self):
        """See: https://github.com/Qiskit/qiskit-terra/issues/5962"""
        qc = QuantumCircuit(1)
        qc.delay(100, 0, "ns")
        circ = transpile(qc, self.simulator_backend)
        self.assertEqual(circ.duration, None)  # not scheduled
        qobj = assemble(circ, self.simulator_backend)
        self.assertEqual(qobj.experiments[0].instructions[0].name, "delay")
        self.assertEqual(qobj.experiments[0].instructions[0].params[0], 1e-7)

    def test_transpile_and_assemble_t1_circuit_for_simulator(self):
        """Check if no scheduling is done in transpiling for simulator backends"""
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(0.1, 0, "us")
        qc.measure(0, 0)
        circ = transpile(qc, self.simulator_backend)
        self.assertEqual(circ.duration, None)  # not scheduled
        qobj = assemble(circ, self.simulator_backend)
        self.assertEqual(qobj.experiments[0].instructions[1].name, "delay")
        self.assertAlmostEqual(qobj.experiments[0].instructions[1].params[0], 1e-7)

    # Tests for circuits with parameterized delays

    def test_can_transpile_circuits_after_assigning_parameters(self):
        """Check if not scheduled but duration is converted in dt"""
        idle_dur = Parameter("t")
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(idle_dur, 0, "us")
        qc.measure(0, 0)
        qc = qc.assign_parameters({idle_dur: 0.1})
        circ = transpile(qc, self.backend_with_dt)
        self.assertEqual(circ.duration, None)  # not scheduled
        self.assertEqual(circ.data[1][0].duration, 450)  # converted in dt

    def test_can_transpile_and_assemble_circuits_with_assigning_parameters_inbetween(self):
        idle_dur = Parameter("t")
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(idle_dur, 0, "us")
        qc.measure(0, 0)
        circ = transpile(qc, self.backend_with_dt)
        circ = circ.assign_parameters({idle_dur: 0.1})
        qobj = assemble(circ, self.backend_with_dt)
        self.assertEqual(qobj.experiments[0].instructions[1].name, "delay")
        self.assertEqual(qobj.experiments[0].instructions[1].params[0], 450)

    def test_can_transpile_circuits_with_unbounded_parameters(self):
        idle_dur = Parameter("t")
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(idle_dur, 0, "us")
        qc.measure(0, 0)
        # not assign parameter
        circ = transpile(qc, self.backend_with_dt)
        self.assertEqual(circ.duration, None)  # not scheduled
        self.assertEqual(circ.data[1][0].unit, "dt")  # converted in dt
        self.assertEqual(circ.data[1][0].duration, idle_dur * 1e-6 / self.dt)  # still parameterized

    def test_fail_to_assemble_circuits_with_unbounded_parameters(self):
        idle_dur = Parameter("t")
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(idle_dur, 0, "us")
        qc.measure(0, 0)
        qc = transpile(qc, self.backend_with_dt)
        with self.assertRaises(QiskitError):
            assemble(qc, self.backend_with_dt)

    @data("asap", "alap")
    def test_can_schedule_circuits_with_bounded_parameters(self, scheduling_method):
        idle_dur = Parameter("t")
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(idle_dur, 0, "us")
        qc.measure(0, 0)
        qc = qc.assign_parameters({idle_dur: 0.1})
        circ = transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method)
        self.assertIsNotNone(circ.duration)  # scheduled

    @data("asap", "alap")
    def test_fail_to_schedule_circuits_with_unbounded_parameters(self, scheduling_method):
        idle_dur = Parameter("t")
        qc = QuantumCircuit(1, 1)
        qc.x(0)
        qc.delay(idle_dur, 0, "us")
        qc.measure(0, 0)
        # not assign parameter
        with self.assertRaises(TranspilerError):
            transpile(qc, self.backend_with_dt, scheduling_method=scheduling_method)
 def test_from_backend_for_backend_with_dt(self):
     durations = InstructionDurations.from_backend(FakeParis())
     self.assertGreater(durations.dt, 0)
     self.assertGreater(durations.get('u2', 0), 0)
 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
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)
 def test_from_backend_for_backend_with_dt(self):
     backend = FakeParis()
     gate = self._find_gate_with_length(backend)
     durations = InstructionDurations.from_backend(backend)
     self.assertGreater(durations.dt, 0)
     self.assertGreater(durations.get(gate, 0), 0)