def _schedule_2Q_interaction(self, total_samples):
        """Creates schedule for testing two qubit interaction. Specifically, do a pi pulse on qub 0
        so it starts in the `1` state (drive channel) and then apply constant pulses to each
        qubit (on control channel 1). This will allow us to test a swap gate.

        Args:
            total_samples (int): length of pulses
        Returns:
            schedule (pulse schedule): schedule for 2q experiment
        """

        # create acquire schedule
        acq_sched = Schedule(name='acq_sched')
        acq_sched |= Acquire(total_samples, AcquireChannel(0), MemorySlot(0))
        acq_sched += Acquire(total_samples, AcquireChannel(1), MemorySlot(1))

        # set up const pulse
        const_pulse = SamplePulse(np.ones(total_samples), name='const_pulse')

        # add commands to schedule
        schedule = Schedule(name='2q_schedule')
        schedule |= Play(const_pulse, DriveChannel(0))
        schedule += Play(const_pulse, ControlChannel(1)) << schedule.duration
        schedule |= acq_sched << schedule.duration

        return schedule
Пример #2
0
    def test_can_construct_valid_acquire_command(self):
        """Test if valid acquire command can be constructed."""
        kernel_opts = {
            'start_window': 0,
            'stop_window': 10
        }
        kernel = Kernel(name='boxcar', **kernel_opts)

        discriminator_opts = {
            'neighborhoods': [{'qubits': 1, 'channels': 1}],
            'cal': 'coloring',
            'resample': False
        }
        discriminator = Discriminator(name='linear_discriminator', **discriminator_opts)

        acq = Acquire(10, AcquireChannel(0), MemorySlot(0),
                      kernel=kernel, discriminator=discriminator, name='acquire')

        self.assertEqual(acq.duration, 10)
        self.assertEqual(acq.discriminator.name, 'linear_discriminator')
        self.assertEqual(acq.discriminator.params, discriminator_opts)
        self.assertEqual(acq.kernel.name, 'boxcar')
        self.assertEqual(acq.kernel.params, kernel_opts)
        self.assertIsInstance(acq.id, int)
        self.assertEqual(acq.name, 'acquire')
        self.assertEqual(acq.operands, (10, AcquireChannel(0), MemorySlot(0), None))
Пример #3
0
    def test_isntructions_hash(self):
        """Test hashing for acquire instruction."""
        kernel_opts = {'start_window': 0, 'stop_window': 10}
        kernel = Kernel(name='boxcar', **kernel_opts)

        discriminator_opts = {
            'neighborhoods': [{
                'qubits': 1,
                'channels': 1
            }],
            'cal': 'coloring',
            'resample': False
        }
        discriminator = Discriminator(name='linear_discriminator',
                                      **discriminator_opts)
        acq_1 = Acquire(10,
                        AcquireChannel(0),
                        MemorySlot(0),
                        kernel=kernel,
                        discriminator=discriminator,
                        name='acquire')
        acq_2 = Acquire(10,
                        AcquireChannel(0),
                        MemorySlot(0),
                        kernel=kernel,
                        discriminator=discriminator,
                        name='acquire')

        hash_1 = hash(acq_1)
        hash_2 = hash(acq_2)

        self.assertEqual(hash_1, hash_2)
    def test_measure_combined(self):
        """
        Test to check for measure on the same qubit which generated another measure schedule.

        The measures on different qubits are combined, but measures on the same qubit
        adds another measure to the schedule.
        """
        q = QuantumRegister(2)
        c = ClassicalRegister(2)
        qc = QuantumCircuit(q, c)
        qc.u2(3.14, 1.57, q[0])
        qc.cx(q[0], q[1])
        qc.measure(q[0], c[0])
        qc.measure(q[1], c[1])
        qc.measure(q[1], c[1])
        sched = schedule(qc, self.backend, method="as_soon_as_possible")
        expected = Schedule(
            self.inst_map.get('u2', [0], 3.14,
                              1.57), (28, self.inst_map.get('cx', [0, 1])),
            (50, self.inst_map.get('measure', [0, 1])),
            (60, self.inst_map.get(
                'measure', [0, 1]).filter(channels=[MeasureChannel(1)])),
            (60, Acquire(10, AcquireChannel(0), MemorySlot(0))),
            (60, Acquire(10, AcquireChannel(1), MemorySlot(1))))
        self.assertEqual(sched.instructions, expected.instructions)
Пример #5
0
 def test_measure(self):
     """Test macro - measure."""
     sched = macros.measure(qubits=[0], backend=self.backend)
     expected = Schedule(
         self.inst_map.get('measure',
                           [0, 1]).filter(channels=[MeasureChannel(0)]),
         Acquire(10, AcquireChannel(0), MemorySlot(0)),
         Acquire(10, AcquireChannel(1), MemorySlot(1)))
     self.assertEqual(sched.instructions, expected.instructions)
Пример #6
0
 def test_measure(self):
     """Test utility function - measure."""
     acquire = Acquire(duration=10)
     sched = measure(qubits=[0], backend=self.backend)
     expected = Schedule(
         self.inst_map.get('measure',
                           [0, 1]).filter(channels=[MeasureChannel(0)]),
         acquire(AcquireChannel(0), MemorySlot(0)),
         acquire(AcquireChannel(1), MemorySlot(1)))
     self.assertEqual(sched.instructions, expected.instructions)
Пример #7
0
 def test_measure_sched_with_qubit_mem_slots(self):
     """Test measure with custom qubit_mem_slots."""
     sched = macros.measure(qubits=[0],
                            backend=self.backend,
                            qubit_mem_slots={0: 1})
     expected = Schedule(
         self.inst_map.get('measure', [0, 1]).filter(channels=[MeasureChannel(0)]),
         Acquire(10, AcquireChannel(0), MemorySlot(1)),
         Acquire(10, AcquireChannel(1), MemorySlot(0)))
     self.assertEqual(sched.instructions, expected.instructions)
Пример #8
0
 def test_measure_sched_with_meas_map(self):
     """Test measure with custom meas_map as list and dict."""
     sched_with_meas_map_list = macros.measure(qubits=[0],
                                               backend=self.backend,
                                               meas_map=[[0, 1]])
     sched_with_meas_map_dict = macros.measure(qubits=[0],
                                               backend=self.backend,
                                               meas_map={0: [0, 1], 1: [0, 1]})
     expected = Schedule(
         self.inst_map.get('measure', [0, 1]).filter(channels=[MeasureChannel(0)]),
         Acquire(10, AcquireChannel(0), MemorySlot(0)),
         Acquire(10, AcquireChannel(1), MemorySlot(1)))
     self.assertEqual(sched_with_meas_map_list.instructions, expected.instructions)
     self.assertEqual(sched_with_meas_map_dict.instructions, expected.instructions)
 def test_user_mapping_for_memslots(self):
     """
     Test that the new schedule only has required `MeasureChannel`s and that the
     `MemorySlot`s are mapped according to the input circuit.
     """
     q = QuantumRegister(2)
     c = ClassicalRegister(2)
     qc = QuantumCircuit(q, c)
     qc.measure(q[0], c[1])
     sched = schedule(qc, self.backend)
     expected = Schedule(
         self.cmd_def.get('measure', [0, 1]).filter(channels=[MeasureChannel(0)]),
         Acquire(duration=10)([AcquireChannel(0), AcquireChannel(1)],
                              [MemorySlot(1), MemorySlot(0)]))
     self.assertEqual(sched.instructions, expected.instructions)
    def _3Q_constant_sched(self,
                           total_samples,
                           amp=1.,
                           u_idx=0,
                           subsystem_list=[0, 2]):
        """Creates a runnable schedule for the 3Q system after the system is restricted to
        2 qubits.

        Args:
            total_samples (int): length of pulse
            amp (float): amplitude of constant pulse (can be complex)
            u_idx (int): index of U channel
            subsystem_list (list): list of qubits to restrict to

        Returns:
            schedule (pulse schedule): schedule with a drive pulse followed by an acquire
        """

        # set up constant pulse for doing a pi pulse
        drive_pulse = Waveform(amp * np.ones(total_samples))
        schedule = Schedule()
        schedule |= Play(drive_pulse, ControlChannel(u_idx))
        for idx in subsystem_list:
            schedule |= Acquire(total_samples, AcquireChannel(idx),
                                MemorySlot(idx)) << total_samples

        return schedule
    def test_set_phase_rwa(self):
        """Test SetPhase command using an RWA approximate solution."""
        omega_0 = 5.123
        r = 0.01

        system_model = self._system_model_1Q(omega_0, r)

        sched = Schedule()
        sched += SetPhase(np.pi / 2, DriveChannel(0))
        sched += Play(Waveform(np.ones(100)), DriveChannel(0))

        sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration

        y0 = np.array([1., 1.]) / np.sqrt(2)
        pulse_sim = PulseSimulator(system_model=system_model,
                                   initial_state=y0)
        qobj = assemble([sched],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[omega_0],
                        memory_slots=2,
                        shots=1)
        results = pulse_sim.run(qobj).result()
        pulse_sim_yf = results.get_statevector()

        #run independent simulation
        phases = np.exp(
            (-1j * 2 * np.pi * omega_0 * np.array([1, -1]) / 2) * 100)
        approx_yf = phases * (expm(-1j * (np.pi / 2) * self.Y) @ y0)

        self.assertGreaterEqual(state_fidelity(pulse_sim_yf, approx_yf), 0.99)
    def _1Q_frame_change_schedule(self, phi, fc_phi, total_samples, dur_drive1,
                                  dur_drive2):
        """Creates schedule for frame change test. Does a pulse w/ phase phi of duration dur_drive1,
        then frame change of phase fc_phi, then another pulse of phase phi of duration dur_drive2.
        The different durations for the pulses allow manipulation of rotation angles on Bloch sphere

        Args:
            phi (float): drive phase (phi in Hamiltonian)
            fc_phi (float): phase for frame change
            total_samples (int): length of pulses
            dur_drive1 (int): duration of first pulse
            dur_drive2 (int): duration of second pulse

        Returns:
            schedule (pulse schedule): schedule for frame change test
        """
        phase = np.exp(1j * phi)
        drive_pulse_1 = SamplePulse(phase * np.ones(dur_drive1),
                                    name='drive_pulse_1')
        drive_pulse_2 = SamplePulse(phase * np.ones(dur_drive2),
                                    name='drive_pulse_2')

        # add commands to schedule
        schedule = Schedule(name='fc_schedule')
        schedule |= Play(drive_pulse_1, DriveChannel(0))
        schedule += ShiftPhase(fc_phi, DriveChannel(0))
        schedule += Play(drive_pulse_2, DriveChannel(0))
        schedule |= Acquire(total_samples, AcquireChannel(0),
                            MemorySlot(0)) << schedule.duration

        return schedule
    def _simple_1Q_schedule(self,
                            phi,
                            total_samples,
                            shape="square",
                            gauss_sigma=0):
        """Creates schedule for single pulse test
        Args:
            phi (float): drive phase (phi in Hamiltonian)
            total_samples (int): length of pulses
            shape (str): shape of the pulse; defaults to square pulse
            gauss_sigma (float): std dev for gaussian pulse if shape=="gaussian"
        Returns:
            schedule (pulse schedule): schedule for this test
        """

        # set up pulse command
        phase = np.exp(1j * phi)
        drive_pulse = None
        if shape == "square":
            const_pulse = np.ones(total_samples)
            drive_pulse = SamplePulse(phase * const_pulse, name='drive_pulse')
        if shape == "gaussian":
            times = 1.0 * np.arange(total_samples)
            gaussian = np.exp(-times**2 / 2 / gauss_sigma**2)
            drive_pulse = SamplePulse(phase * gaussian, name='drive_pulse')

        # add commands into a schedule for first qubit
        schedule = Schedule(name='drive_pulse')
        schedule |= Play(drive_pulse, DriveChannel(0))
        schedule |= Acquire(total_samples, AcquireChannel(0),
                            MemorySlot(0)) << schedule.duration

        return schedule
 def test_user_mapping_for_memslots_3Q(self):
     """Test measuring two of three qubits."""
     backend = FakeOpenPulse3Q()
     cmd_def = backend.defaults().build_cmd_def()
     q = QuantumRegister(3)
     c = ClassicalRegister(3)
     qc = QuantumCircuit(q, c)
     qc.measure(q[1], c[2])
     qc.measure(q[2], c[0])
     sched = schedule(qc, backend)
     expected = Schedule(
         cmd_def.get('measure', [0, 1, 2]).filter(
             channels=[MeasureChannel(1), MeasureChannel(2)]),
         Acquire(duration=10)([AcquireChannel(0), AcquireChannel(1), AcquireChannel(2)],
                              [MemorySlot(1), MemorySlot(2), MemorySlot(0)]))
     self.assertEqual(sched.instructions, expected.instructions)
    def test_gaussian_drive(self):
        """Test gaussian drive pulse using meas_level_2. Set omega_d0=omega_0 (drive on resonance),
        phi=0, omega_a = pi/time
        """

        # set omega_0, omega_d0 equal (use qubit frequency) -> drive on resonance
        total_samples = 100
        omega_0 = 1.
        omega_d = omega_0

        # Require omega_a*time = pi to implement pi pulse (x gate)
        # num of samples gives time
        r = np.pi / total_samples

        # initial state and seed
        y0 = np.array([1., 0.])
        seed = 9000

        # Test gaussian drive results for a few different sigma
        gauss_sigmas = [total_samples / 6, total_samples / 3, total_samples]

        # set up pulse simulator
        pulse_sim = PulseSimulator(system_model=self._system_model_1Q(omega_0, r))

        for gauss_sigma in gauss_sigmas:
            with self.subTest(gauss_sigma=gauss_sigma):
                times = 1.0 * np.arange(total_samples)
                gaussian_samples = np.exp(-times**2 / 2 / gauss_sigma**2)
                drive_pulse = Waveform(gaussian_samples, name='drive_pulse')

                # construct schedule
                schedule = Schedule()
                schedule |= Play(drive_pulse, DriveChannel(0))
                schedule |= Acquire(1, AcquireChannel(0),
                                    MemorySlot(0)) << schedule.duration

                qobj = assemble([schedule],
                                backend=pulse_sim,
                                meas_level=2,
                                meas_return='single',
                                meas_map=[[0]],
                                qubit_lo_freq=[omega_d],
                                memory_slots=2,
                                shots=1)

                result = pulse_sim.run(qobj, initial_state=y0, seed=seed).result()
                pulse_sim_yf = result.get_statevector()

                # run independent simulation
                yf = simulate_1q_model(y0, omega_0, r, np.array([omega_d]),
                                       gaussian_samples, 1.)

                # Check fidelity of statevectors
                self.assertGreaterEqual(state_fidelity(pulse_sim_yf, yf),
                                        1 - (10**-5))
Пример #16
0
    def _2Q_constant_sched(self, total_samples, amp=1., u_idx=0):
        """Creates a runnable schedule with a single pulse on a U channel for two qubits.

        Args:
            total_samples (int): length of pulse
            amp (float): amplitude of constant pulse (can be complex)
            u_idx (int): index of U channel

        Returns:
            schedule (pulse schedule): schedule with a drive pulse followed by an acquire
        """

        # set up constant pulse for doing a pi pulse
        drive_pulse = SamplePulse(amp * np.ones(total_samples))
        schedule = Schedule()
        schedule |= Play(drive_pulse, ControlChannel(u_idx))
        schedule |= Acquire(total_samples, AcquireChannel(0), MemorySlot(0)) << total_samples
        schedule |= Acquire(total_samples, AcquireChannel(1), MemorySlot(1)) << total_samples

        return schedule
Пример #17
0
 def test_multiple_measure_in_3Q(self):
     """Test multiple measure, user memslot mapping, 3Q."""
     backend = FakeOpenPulse3Q()
     cmd_def = backend.defaults().build_cmd_def()
     q = QuantumRegister(3)
     c = ClassicalRegister(5)
     qc = QuantumCircuit(q, c)
     qc.measure(q[0], c[2])
     qc.measure(q[0], c[4])
     sched = schedule(qc, backend)
     expected = Schedule(
         cmd_def.get('measure',
                     [0, 1, 2]).filter(channels=[MeasureChannel(0)]),
         Acquire(duration=10)(
             [AcquireChannel(0),
              AcquireChannel(1),
              AcquireChannel(2)],
             [MemorySlot(2), MemorySlot(0),
              MemorySlot(1)]),
         (10, cmd_def.get('measure',
                          [0, 1, 2]).filter(channels=[MeasureChannel(0)])),
         (10, Acquire(duration=10)(
             [AcquireChannel(0),
              AcquireChannel(1),
              AcquireChannel(2)],
             [MemorySlot(4), MemorySlot(0),
              MemorySlot(1)])))
     self.assertEqual(sched.instructions, expected.instructions)
    def test_set_phase(self):
        """Test SetPhase command. Similar to the ShiftPhase test but includes a mixing of
        ShiftPhase and SetPhase instructions to test relative vs absolute changes"""

        omega_0 = 1.3981
        r = 1.

        system_model = self._system_model_1Q(omega_0, r)

        # intermix shift and set phase instructions to verify absolute v.s. relative changes
        sched = Schedule()
        amp1 = 0.12
        sched += Play(Waveform([amp1]), DriveChannel(0))
        phi1 = 0.12374 * np.pi
        sched += ShiftPhase(phi1, DriveChannel(0))
        amp2 = 0.492
        sched += Play(Waveform([amp2]), DriveChannel(0))
        phi2 = 0.5839 * np.pi
        sched += SetPhase(phi2, DriveChannel(0))
        amp3 = 0.12 + 0.21 * 1j
        sched += Play(Waveform([amp3]), DriveChannel(0))
        phi3 = 0.1 * np.pi
        sched += ShiftPhase(phi3, DriveChannel(0))
        amp4 = 0.2 + 0.3 * 1j
        sched += Play(Waveform([amp4]), DriveChannel(0))

        sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration

        y0 = np.array([1., 0.])
        pulse_sim = PulseSimulator(system_model=system_model,
                                   initial_state=y0)
        qobj = assemble([sched],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[omega_0],
                        memory_slots=2,
                        shots=1)
        results = pulse_sim.run(qobj).result()
        pulse_sim_yf = results.get_statevector()

        #run independent simulation
        samples = np.array([[amp1], [amp2 * np.exp(1j * phi1)],
                            [amp3 * np.exp(1j * phi2)],
                            [amp4 * np.exp(1j * (phi2 + phi3))]])
        indep_yf = simulate_1q_model(y0, omega_0, r, np.array([omega_0]),
                                     samples, 1.)

        self.assertGreaterEqual(state_fidelity(pulse_sim_yf, indep_yf),
                                1 - (10**-5))
    def test_calibrated_measurements(self):
        """Test scheduling calibrated measurements."""
        q = QuantumRegister(2)
        c = ClassicalRegister(2)
        qc = QuantumCircuit(q, c)
        qc.append(U2Gate(0, 0), [q[0]])
        qc.measure(q[0], c[0])

        meas_sched = Play(Gaussian(1200, 0.2, 4), MeasureChannel(0))
        meas_sched |= Acquire(1200, AcquireChannel(0), MemorySlot(0))
        qc.add_calibration("measure", [0], meas_sched)

        sched = schedule(qc, self.backend)
        expected = Schedule(self.inst_map.get("u2", [0], 0, 0), (2, meas_sched))
        self.assertEqual(sched.instructions, expected.instructions)
    def test_clbits_of_calibrated_measurements(self):
        """Test that calibrated measurements are only used when the classical bits also match."""
        q = QuantumRegister(2)
        c = ClassicalRegister(2)
        qc = QuantumCircuit(q, c)
        qc.measure(q[0], c[1])

        meas_sched = Play(Gaussian(1200, 0.2, 4), MeasureChannel(0))
        meas_sched |= Acquire(1200, AcquireChannel(0), MemorySlot(0))
        qc.add_calibration("measure", [0], meas_sched)

        sched = schedule(qc, self.backend)
        # Doesn't use the calibrated schedule because the classical memory slots do not match
        expected = Schedule(macros.measure([0], self.backend, qubit_mem_slots={0: 1}))
        self.assertEqual(sched.instructions, expected.instructions)
Пример #21
0
    def test_measure_with_custom_inst_map(self):
        """Test measure with custom inst_map, meas_map with measure_name."""
        q0_sched = Play(GaussianSquare(1200, 1, 0.4, 1150), MeasureChannel(0))
        q0_sched += Acquire(1200, AcquireChannel(0), MemorySlot(0))
        inst_map = InstructionScheduleMap()
        inst_map.add('my_sched', 0, q0_sched)
        sched = macros.measure(qubits=[0],
                               measure_name='my_sched',
                               inst_map=inst_map,
                               meas_map=[[0]])
        self.assertEqual(sched.instructions, q0_sched.instructions)

        with self.assertRaises(PulseError):
            macros.measure(qubits=[0],
                           measure_name="name",
                           inst_map=inst_map,
                           meas_map=[[0]])
Пример #22
0
    def _1Q_schedule(self, total_samples=100, amp=1., num_acquires=1):
        """Creates a schedule for a single qubit.

        Args:
            total_samples (int): number of samples in the drive pulse
            amp (complex): amplitude of drive pulse
            num_acquires (int): number of acquire instructions to include in the schedule

        Returns:
            schedule (pulse schedule):
        """

        schedule = Schedule()
        schedule |= Play(Waveform(amp * np.ones(total_samples)), DriveChannel(0))
        for _ in range(num_acquires):
            schedule |= Acquire(total_samples, AcquireChannel(0),
                                MemorySlot(0)) << schedule.duration
        return schedule
Пример #23
0
    def _1Q_constant_sched(self, total_samples, amp=1.):
        """Creates a runnable schedule for 1Q with a constant drive pulse of a given length.

        Args:
            total_samples (int): length of pulse
            amp (float): amplitude of constant pulse (can be complex)

        Returns:
            schedule (pulse schedule): schedule with a drive pulse followed by an acquire
        """

        # set up constant pulse for doing a pi pulse
        drive_pulse = SamplePulse(amp * np.ones(total_samples))
        schedule = Schedule()
        schedule |= Play(drive_pulse, DriveChannel(0))
        schedule |= Acquire(total_samples, AcquireChannel(0), MemorySlot(0)) << schedule.duration

        return schedule
    def test_subset_calibrated_measurements(self):
        """Test that measurement calibrations can be added and used for some qubits, even
        if the other qubits do not also have calibrated measurements."""
        qc = QuantumCircuit(3, 3)
        qc.measure(0, 0)
        qc.measure(1, 1)
        qc.measure(2, 2)
        meas_scheds = []
        for qubit in [0, 2]:
            meas = (Play(Gaussian(1200, 0.2, 4), MeasureChannel(qubit)) +
                    Acquire(1200, AcquireChannel(qubit), MemorySlot(qubit)))
            meas_scheds.append(meas)
            qc.add_calibration('measure', [qubit], meas)

        meas = macros.measure([1], FakeOpenPulse3Q())
        meas = meas.exclude(channels=[AcquireChannel(0), AcquireChannel(2)])
        sched = schedule(qc, FakeOpenPulse3Q())
        expected = Schedule(meas_scheds[0], meas_scheds[1], meas)
        self.assertEqual(sched.instructions, expected.instructions)
Пример #25
0
def model_and_pi_schedule():
    """Return a simple model and schedule for pulse simulation"""

    # construct model
    model = duffing_system_model(dim_oscillators=2,
                                 oscillator_freqs=[5.0],
                                 anharm_freqs=[0],
                                 drive_strengths=[0.01],
                                 coupling_dict={},
                                 dt=1.0)

    # note: parameters set so that area under curve is 1/4
    sample_pulse = SamplePulse(np.ones(50))

    # construct schedule
    schedule = Schedule(name='test_sched')
    schedule |= Play(sample_pulse, DriveChannel(0))
    schedule += Acquire(10, AcquireChannel(0),
                        MemorySlot(0)) << schedule.duration

    return model, schedule
Пример #26
0
def model_and_pi_schedule():
    """Return a simple model and schedule for pulse simulation"""

    # construct model
    model = duffing_system_model(dim_oscillators=2,
                                 oscillator_freqs=[5.0],
                                 anharm_freqs=[0],
                                 drive_strengths=[1.0],
                                 coupling_dict={},
                                 dt=1.0)

    # note: parameters set so that area under curve is 1/4
    gauss_pulse = Gaussian(duration=10,
                           amp=(1.0 / 4) / 2.506627719963857,
                           sigma=1)

    # construct schedule
    schedule = Schedule(name='test_sched')
    schedule |= Play(gauss_pulse, DriveChannel(0))
    schedule += Acquire(10, AcquireChannel(0),
                        MemorySlot(0)) << schedule.duration

    return model, schedule
    def test_2Q_exchange(self):
        r"""Test a more complicated 2q simulation"""

        q_freqs = [5., 5.1]
        r = 0.02
        j = 0.02
        total_samples = 25

        hamiltonian = {}
        hamiltonian['h_str'] = [
            '2*np.pi*v0*0.5*Z0', '2*np.pi*v1*0.5*Z1', '2*np.pi*r*0.5*X0||D0',
            '2*np.pi*r*0.5*X1||D1', '2*np.pi*j*0.5*I0*I1',
            '2*np.pi*j*0.5*X0*X1', '2*np.pi*j*0.5*Y0*Y1', '2*np.pi*j*0.5*Z0*Z1'
        ]
        hamiltonian['vars'] = {
            'v0': q_freqs[0],
            'v1': q_freqs[1],
            'r': r,
            'j': j
        }
        hamiltonian['qub'] = {'0': 2, '1': 2}
        ham_model = HamiltonianModel.from_dict(hamiltonian)

        # set the U0 to have frequency of drive channel 0
        u_channel_lo = []
        subsystem_list = [0, 1]
        dt = 1.

        system_model = PulseSystemModel(hamiltonian=ham_model,
                                        u_channel_lo=u_channel_lo,
                                        subsystem_list=subsystem_list,
                                        dt=dt)

        # try some random schedule
        schedule = Schedule()
        drive_pulse = Waveform(np.ones(total_samples))
        schedule += Play(drive_pulse, DriveChannel(0))
        schedule |= Play(drive_pulse, DriveChannel(1)) << 2 * total_samples

        schedule |= Acquire(total_samples, AcquireChannel(0),
                            MemorySlot(0)) << 3 * total_samples
        schedule |= Acquire(total_samples, AcquireChannel(1),
                            MemorySlot(1)) << 3 * total_samples

        y0 = np.array([1., 0., 0., 0.])
        pulse_sim = PulseSimulator(system_model=system_model,
                                   initial_state=y0,
                                   seed=9000)

        qobj = assemble([schedule],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=q_freqs,
                        memory_slots=2,
                        shots=1000)
        result = pulse_sim.run(qobj).result()
        pulse_sim_yf = result.get_statevector()

        # set up and run independent simulation
        d0_samps = np.concatenate(
            (np.ones(total_samples), np.zeros(2 * total_samples)))
        d1_samps = np.concatenate(
            (np.zeros(2 * total_samples), np.ones(total_samples)))
        samples = np.array([d0_samps, d1_samps]).transpose()
        q_freqs = np.array(q_freqs)
        yf = simulate_2q_exchange_model(y0, q_freqs, r, j, q_freqs, samples,
                                        1.)

        # Check fidelity of statevectors
        self.assertGreaterEqual(state_fidelity(pulse_sim_yf, yf), 1 - (10**-5))
    def test_delay_instruction(self):
        """Test for delay instruction."""

        # construct system model specifically for this
        hamiltonian = {}
        hamiltonian['h_str'] = ['0.5*r*X0||D0', '0.5*r*Y0||D1']
        hamiltonian['vars'] = {'r': np.pi}
        hamiltonian['qub'] = {'0': 2}
        ham_model = HamiltonianModel.from_dict(hamiltonian)

        u_channel_lo = []
        subsystem_list = [0]
        dt = 1.

        system_model = PulseSystemModel(hamiltonian=ham_model,
                                        u_channel_lo=u_channel_lo,
                                        subsystem_list=subsystem_list,
                                        dt=dt)

        # construct a schedule that should result in a unitary -Z if delays are correctly handled
        # i.e. do a pi rotation about x, sandwiched by pi/2 rotations about y in opposite directions
        # so that the x rotation is transformed into a z rotation.
        # if delays are not handled correctly this process should fail
        sched = Schedule()
        sched += Play(Waveform([0.5]), DriveChannel(1))
        sched += Delay(1, DriveChannel(1))
        sched += Play(Waveform([-0.5]), DriveChannel(1))

        sched += Delay(1, DriveChannel(0))
        sched += Play(Waveform([1.]), DriveChannel(0))

        sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration

        # Result of schedule should be the unitary -1j*Z, so check rotation of an X eigenstate
        pulse_sim = PulseSimulator(system_model=system_model,
                                   initial_state=np.array([1., 1.]) / np.sqrt(2))

        qobj = assemble([sched],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[0., 0.],
                        memory_slots=2,
                        shots=1)

        results = pulse_sim.run(qobj).result()

        statevector = results.get_statevector()
        expected_vector = np.array([-1j, 1j]) / np.sqrt(2)

        self.assertGreaterEqual(state_fidelity(statevector, expected_vector),
                                1 - (10**-5))

        # verify validity of simulation when no delays included
        sched = Schedule()
        sched += Play(Waveform([0.5]), DriveChannel(1))
        sched += Play(Waveform([-0.5]), DriveChannel(1))

        sched += Play(Waveform([1.]), DriveChannel(0))

        sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration

        qobj = assemble([sched],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[0., 0.],
                        memory_slots=2,
                        shots=1)

        results = pulse_sim.run(qobj).result()

        statevector = results.get_statevector()
        U = expm(1j * np.pi * self.Y / 4) @ expm(-1j * np.pi *
                                                 (self.Y / 4 + self.X / 2))
        expected_vector = U @ np.array([1., 1.]) / np.sqrt(2)

        self.assertGreaterEqual(state_fidelity(statevector, expected_vector),
                                1 - (10**-5))
Пример #29
0
def measure(qubits: List[int],
            backend=None,
            inst_map: Optional[InstructionScheduleMap] = None,
            meas_map: Optional[Union[List[List[int]], Dict[int,
                                                           List[int]]]] = None,
            qubit_mem_slots: Optional[Dict[int, int]] = None,
            measure_name: str = 'measure') -> Schedule:
    """
    Return a schedule which measures the requested qubits according to the given
    instruction mapping and measure map, or by using the defaults provided by the backend.

    By default, the measurement results for each qubit are trivially mapped to the qubit
    index. This behavior is overridden by qubit_mem_slots. For instance, to measure
    qubit 0 into MemorySlot(1), qubit_mem_slots can be provided as {0: 1}.

    Args:
        qubits: List of qubits to be measured.
        backend (BaseBackend): A backend instance, which contains hardware-specific data
            required for scheduling.
        inst_map: Mapping of circuit operations to pulse schedules. If None, defaults to the
                  ``instruction_schedule_map`` of ``backend``.
        meas_map: List of sets of qubits that must be measured together. If None, defaults to
                  the ``meas_map`` of ``backend``.
        qubit_mem_slots: Mapping of measured qubit index to classical bit index.
        measure_name: Name of the measurement schedule.

    Returns:
        A measurement schedule corresponding to the inputs provided.

    Raises:
        PulseError: If both ``inst_map`` or ``meas_map``, and ``backend`` is None.
    """
    schedule = Schedule(
        name="Default measurement schedule for qubits {}".format(qubits))
    try:
        inst_map = inst_map or backend.defaults().instruction_schedule_map
        meas_map = meas_map or backend.configuration().meas_map
    except AttributeError:
        raise PulseError(
            'inst_map or meas_map, and backend cannot be None simultaneously')
    if isinstance(meas_map, List):
        meas_map = format_meas_map(meas_map)

    measure_groups = set()
    for qubit in qubits:
        measure_groups.add(tuple(meas_map[qubit]))
    for measure_group_qubits in measure_groups:
        if qubit_mem_slots is not None:
            unused_mem_slots = set(measure_group_qubits) - set(
                qubit_mem_slots.values())
        try:
            default_sched = inst_map.get(measure_name, measure_group_qubits)
        except PulseError:
            raise PulseError(
                "We could not find a default measurement schedule called '{}'. "
                "Please provide another name using the 'measure_name' keyword "
                "argument. For assistance, the instructions which are defined are: "
                "{}".format(measure_name, inst_map.instructions))

        for time, inst in default_sched.instructions:
            if qubit_mem_slots and isinstance(inst,
                                              (Acquire, AcquireInstruction)):
                if inst.channel.index in qubit_mem_slots:
                    mem_slot = MemorySlot(qubit_mem_slots[inst.channel.index])
                else:
                    mem_slot = MemorySlot(unused_mem_slots.pop())
                schedule = schedule.insert(
                    time,
                    Acquire(inst.duration, inst.channel, mem_slot=mem_slot))
            elif qubit_mem_slots is None and isinstance(
                    inst, (Acquire, AcquireInstruction)):
                schedule = schedule.insert(time, inst)
            # Measurement pulses should only be added if its qubit was measured by the user
            elif inst.channels[0].index in qubits:
                schedule = schedule.insert(time, inst)

    return schedule
    def test_shift_phase(self):
        """Test ShiftPhase command."""

        omega_0 = 1.123
        r = 1.

        system_model = self._system_model_1Q(omega_0, r)

        # run a schedule in which a shifted phase causes a pulse to cancel itself.
        # Also do it in multiple phase shifts to test accumulation
        sched = Schedule()
        amp1 = 0.12
        sched += Play(Waveform([amp1]), DriveChannel(0))
        phi1 = 0.12374 * np.pi
        sched += ShiftPhase(phi1, DriveChannel(0))
        amp2 = 0.492
        sched += Play(Waveform([amp2]), DriveChannel(0))
        phi2 = 0.5839 * np.pi
        sched += ShiftPhase(phi2, DriveChannel(0))
        amp3 = 0.12 + 0.21 * 1j
        sched += Play(Waveform([amp3]), DriveChannel(0))

        sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration

        y0 = np.array([1., 0])

        pulse_sim = PulseSimulator(system_model=system_model,
                                   initial_state=y0)
        qobj = assemble([sched],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[omega_0],
                        memory_slots=2,
                        shots=1)
        results = pulse_sim.run(qobj).result()
        pulse_sim_yf = results.get_statevector()

        #run independent simulation
        samples = np.array([[amp1], [amp2 * np.exp(1j * phi1)],
                            [amp3 * np.exp(1j * (phi1 + phi2))]])
        indep_yf = simulate_1q_model(y0, omega_0, r, np.array([omega_0]),
                                     samples, 1.)

        self.assertGreaterEqual(state_fidelity(pulse_sim_yf, indep_yf),
                                1 - (10**-5))

        # run another schedule with only a single shift phase to verify
        sched = Schedule()
        amp1 = 0.12
        sched += Play(Waveform([amp1]), DriveChannel(0))
        phi1 = 0.12374 * np.pi
        sched += ShiftPhase(phi1, DriveChannel(0))
        amp2 = 0.492
        sched += Play(Waveform([amp2]), DriveChannel(0))
        sched |= Acquire(1, AcquireChannel(0), MemorySlot(0)) << sched.duration

        qobj = assemble([sched],
                        backend=pulse_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[omega_0],
                        memory_slots=2,
                        shots=1)

        results = pulse_sim.run(qobj).result()
        pulse_sim_yf = results.get_statevector()

        #run independent simulation
        samples = np.array([[amp1], [amp2 * np.exp(1j * phi1)]])
        indep_yf = simulate_1q_model(y0, omega_0, r, np.array([omega_0]),
                                     samples, 1.)

        self.assertGreaterEqual(state_fidelity(pulse_sim_yf, indep_yf),
                                1 - (10**-5))