Ejemplo n.º 1
0
    def test_eigen_sorting(self):
        """Test estate mappings"""

        X = array([[0, 1], [1, 0]])
        Y = array([[0, -1j], [1j, 0]])
        Z = array([[1, 0], [0, -1]])

        simple_ham = {
            'h_str': ['a*X0', 'b*Y0', 'c*Z0'],
            'vars': {
                'a': 0.1,
                'b': 0.1,
                'c': 1
            },
            'qub': {
                '0': 2
            }
        }

        ham_model = HamiltonianModel.from_dict(simple_ham)

        # check norm
        for estate in ham_model._estates:
            self.assertAlmostEqual(norm(estate), 1)

        # check actually an eigenstate
        mat = 0.1 * X + 0.1 * Y + 1 * Z
        for idx, eval in enumerate(ham_model._evals):
            diff = mat @ ham_model._estates[:,
                                            idx] - eval * ham_model._estates[:,
                                                                             idx]
            self.assertAlmostEqual(norm(diff), 0)

        # Same test but with strongly off-diagonal hamiltonian, which should raise warning
        simple_ham = {
            'h_str': ['a*X0', 'b*Y0', 'c*Z0'],
            'vars': {
                'a': 100,
                'b': 32.1,
                'c': 0.12
            },
            'qub': {
                '0': 2
            }
        }

        ham_model = HamiltonianModel.from_dict(simple_ham)

        # check norm
        for estate in ham_model._estates:
            self.assertAlmostEqual(norm(estate), 1)

        # check actually an eigenstate
        mat = 100 * X + 32.1 * Y + 0.12 * Z
        for idx, eval in enumerate(ham_model._evals):
            diff = mat @ ham_model._estates[:,
                                            idx] - eval * ham_model._estates[:,
                                                                             idx]
            self.assertAlmostEqual(norm(diff), 0)
    def _system_model_2Q(self, j):
        """Constructs a model for a 2 qubit system with a U channel controlling coupling and
        no other Hamiltonian terms.

        Args:
            j (float): coupling strength

        Returns:
            PulseSystemModel: model for qubit system
        """

        hamiltonian = {}
        hamiltonian['h_str'] = [
            'a*X0||D0', 'a*X0||D1', '2*np.pi*j*0.25*(Z0*X1)||U0'
        ]
        hamiltonian['vars'] = {'a': 0, '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 = [[UchannelLO(0, 1.0 + 0.0j)]]
        subsystem_list = [0, 1]
        dt = 1.

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
Ejemplo n.º 3
0
    def _system_model_1Q(self, omega_0=5., r=0.02):
        """Constructs a standard model for a 1 qubit system.

        Args:
            omega_0 (float): qubit frequency
            r (float): drive strength

        Returns:
            PulseSystemModel: model for qubit system
        """

        hamiltonian = {}
        hamiltonian['h_str'] = [
            '2*np.pi*omega0*0.5*Z0', '2*np.pi*r*0.5*X0||D0'
        ]
        hamiltonian['vars'] = {'omega0': omega_0, 'r': r}
        hamiltonian['qub'] = {'0': 2}
        ham_model = HamiltonianModel.from_dict(hamiltonian)

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

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
    def _system_model_3d_oscillator(self, freq, anharm, r):
        """Model for a duffing oscillator truncated to 3 dimensions.

        Args:
            freq (float): frequency of the oscillator
            anharm (float): anharmonicity of the oscillator
            r (float): drive strength

        Returns:
            PulseSystemModel: model for oscillator system
        """
        hamiltonian = {}
        hamiltonian['h_str'] = [
            'np.pi*(2*v-alpha)*O0', 'np.pi*alpha*O0*O0', '2*np.pi*r*X0||D0'
        ]
        hamiltonian['vars'] = {'v': freq, 'alpha': anharm, 'r': r}
        hamiltonian['qub'] = {'0': 3}
        ham_model = HamiltonianModel.from_dict(hamiltonian)

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

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
    def _system_model_3Q(self, j, subsystem_list=[0, 2]):
        """Constructs a model for a 3 qubit system, with the goal that the restriction to
        [0, 2] and to qubits [1, 2] is the same as in _system_model_2Q

        Args:
            j (float): coupling strength
            subsystem_list (list): list of subsystems to include

        Returns:
            PulseSystemModel: model for qubit system
        """

        hamiltonian = {}
        hamiltonian['h_str'] = [
            '2*np.pi*j*0.25*(Z0*X2)||U0', '2*np.pi*j*0.25*(Z1*X2)||U1'
        ]
        hamiltonian['vars'] = {'j': j}
        hamiltonian['qub'] = {'0': 2, '1': 2, '2': 2}
        ham_model = HamiltonianModel.from_dict(hamiltonian,
                                               subsystem_list=subsystem_list)

        # set the U0 to have frequency of drive channel 0
        u_channel_lo = [[UchannelLO(0, 1.0 + 0.0j)],
                        [UchannelLO(0, 1.0 + 0.0j)]]
        dt = 1.

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
    def _system_model_1Q(self, omega_0, omega_a, qubit_dim=2):
        """Constructs a simple 1 qubit system model.

        Args:
            omega_0 (float): frequency of qubit
            omega_a (float): strength of drive term
            qubit_dim (int): dimension of qubit
        Returns:
            PulseSystemModel: model for qubit system
        """
        # make Hamiltonian
        hamiltonian = {}
        hamiltonian['h_str'] = ['-0.5*omega0*Z0', '0.5*omegaa*X0||D0']
        hamiltonian['vars'] = {'omega0': omega_0, 'omegaa': omega_a}
        hamiltonian['qub'] = {'0': qubit_dim}
        ham_model = HamiltonianModel.from_dict(hamiltonian)

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

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
Ejemplo n.º 7
0
    def _simple_system_model(self,
                             v0=5.0,
                             v1=5.1,
                             j=0.01,
                             r=0.02,
                             alpha0=-0.33,
                             alpha1=-0.33):
        hamiltonian = {}
        hamiltonian['h_str'] = [
            'np.pi*(2*v0-alpha0)*O0', 'np.pi*alpha0*O0*O0', '2*np.pi*r*X0||D0',
            '2*np.pi*r*X0||U1', '2*np.pi*r*X1||U0', 'np.pi*(2*v1-alpha1)*O1',
            'np.pi*alpha1*O1*O1', '2*np.pi*r*X1||D1',
            '2*np.pi*j*(Sp0*Sm1+Sm0*Sp1)'
        ]
        hamiltonian['qub'] = {'0': 3, '1': 3}
        hamiltonian['vars'] = {
            'v0': v0,
            'v1': v1,
            'j': j,
            'r': r,
            'alpha0': alpha0,
            'alpha1': alpha1
        }
        ham_model = HamiltonianModel.from_dict(hamiltonian)

        subsystem_list = [0, 1]
        dt = 1.

        return PulseSystemModel(hamiltonian=ham_model,
                                qubit_freq_est=self._default_qubit_lo_freq,
                                u_channel_lo=self._u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
Ejemplo n.º 8
0
    def _system_model_3Q(self,
                         omega_0,
                         omega_a,
                         omega_i,
                         qubit_dim=2,
                         subsystem_list=None):
        """Constructs a 3 qubit model. Purpose of this is for testing subsystem restrictions -
        It is set up so that the system restricted to [0, 2] and [1, 2] is the same (up to
        channel labelling).

        Args:
            omega_0 (float): frequency of qubit
            omega_a (float): strength of drive term
            omega_i (float): strength of interaction
            qubit_dim (int): dimension of qubit
        Returns:
            PulseSystemModel: model for qubit system
        """

        # make Hamiltonian
        hamiltonian = {}
        # qubit 0 terms
        hamiltonian['h_str'] = [
            '-0.5*omega0*Z0', '0.5*omegaa*X0||D0', '-0.5*omega0*Z1',
            '0.5*omegaa*X1||D1'
        ]
        # interaction terms
        hamiltonian['h_str'].append('omegai*(Sp0*Sm2+Sm0*Sp2)||U1')
        hamiltonian['h_str'].append('omegai*(Sp1*Sm2+Sm1*Sp2)||U2')
        hamiltonian['vars'] = {
            'omega0': omega_0,
            'omegaa': omega_a,
            'omegai': omega_i
        }
        hamiltonian['qub'] = {'0': qubit_dim, '1': qubit_dim, '2': qubit_dim}
        ham_model = HamiltonianModel.from_dict(hamiltonian, subsystem_list)

        u_channel_lo = [[{
            'q': 0,
            'scale': [1.0, 0.0]
        }], [{
            'q': 0,
            'scale': [-1.0, 0.0]
        }, {
            'q': 2,
            'scale': [1.0, 0.0]
        }], [{
            'q': 1,
            'scale': [-1.0, 0.0]
        }, {
            'q': 2,
            'scale': [1.0, 0.0]
        }]]
        dt = 1.

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
Ejemplo n.º 9
0
 def assert_hamiltonian_parse_exception(self, ham_dict, message):
     """Test that an attempt to parse a given ham_dict results in an exception with
     the given message.
     """
     try:
         ham_model = HamiltonianModel.from_dict(ham_dict)
     except Exception as exception:
         self.assertEqual(exception.message, message)
Ejemplo n.º 10
0
    def test_no_variables(self):
        """Test successful construction of Hamiltonian without variables"""

        # fully specified hamiltonian without variables
        ham_dict = {'h_str': ['2*np.pi*O0', '2*np.pi*X0||D0'], 'qub': {'0': 2}}
        ham_model = HamiltonianModel.from_dict(ham_dict)

        qubit_lo = ham_model.get_qubit_lo_from_drift()
        self.assertAlmostEqual(norm(qubit_lo - np.array([1.])), 0)
Ejemplo n.º 11
0
def two_level_ham(config, subsystem_list, add_y, no_control):
    # TODO fix 2q version


    bigy1 = Qobj(tensor(sigmay(), identity(2)).full())
    bigy2 = Qobj(tensor(identity(2), sigmay()).full())
    bigx1 = Qobj(tensor(sigmax(), identity(2)).full())
    bigx2 = Qobj(tensor(identity(2), sigmax()).full())
    hamiltonian = {}
    hamiltonian_backend = config.hamiltonian
    hamiltonian_dict = HamiltonianModel.from_dict(
        hamiltonian_backend, subsystem_list=subsystem_list)
    hamiltonian = {'H_c': {}, 'H_d': 0}
    for i, control_field in enumerate(hamiltonian_dict._system):
        matrix = (control_field[0])
        prefactor, control = prefactor_parser(control_field[1], hamiltonian_dict._variables)
        if prefactor == 0:
            continue
        if control:
            # prefactor = prefactor * 2
            if 'D' in control:
                # print("Double check that sigx2 and  sigy2 are right")
                if len(subsystem_list) == 1:
                    hamiltonian['H_c'][control] = sigmax() * prefactor
                if add_y:
                    if len(subsystem_list) == 1:
                        hamiltonian['H_c'][control + 'y'] = sigmay() * prefactor
                    elif len(subsystem_list) == 2:
                        if control == 'D0':
                            hamiltonian['H_c'][control] = Qobj(bigx1 * prefactor)
                            hamiltonian['H_c'][control + 'y'] = Qobj(bigy1 * prefactor)
                        elif control == 'D1':
                            hamiltonian['H_c'][control] = Qobj(bigx2 * prefactor)
                            hamiltonian['H_c'][control + 'y'] = Qobj(bigy2 * prefactor)
                        else:
                            raise NotImplementedError("Only q0 and q1 rn")
                    else:
                        raise NotImplementedError("Only 1-2q operations supported")
                else:
                    raise NotImplementedError("need to use y right now")
            elif no_control:
                print('not using control channels, skippping...')
            else:
                raise NotImplementedError("No use for control channels currently")
    if len(subsystem_list) == 1:
        hamiltonian['H_d'] = identity(2) * 0
    elif len(subsystem_list) == 2:
        hamiltonian['H_d'] = identity(4) * 0
    return hamiltonian
Ejemplo n.º 12
0
    def test_simulation_without_variables(self):
        r"""Test behavior of subsystem_list subsystem restriction.
        Same setup as test_x_gate, but with explicit Hamiltonian construction without
        variables
        """

        ham_dict = {
            'h_str': ['-np.pi*Z0', '0.01*np.pi*X0||D0'],
            'qub': {
                '0': 2
            }
        }
        ham_model = HamiltonianModel.from_dict(ham_dict)

        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)

        # set up schedule and qobj
        total_samples = 50
        schedule = self._simple_1Q_schedule(0, total_samples)
        qobj = assemble([schedule],
                        backend=self.backend_sim,
                        meas_level=2,
                        meas_return='single',
                        meas_map=[[0]],
                        qubit_lo_freq=[1.],
                        memory_slots=2,
                        shots=256)

        # set backend backend_options
        backend_options = {'seed': 9000}

        # run simulation
        result = self.backend_sim.run(
            qobj, system_model=system_model,
            backend_options=backend_options).result()

        # test results
        counts = result.get_counts()
        exp_counts = {'1': 256}
        self.assertDictAlmostEqual(counts, exp_counts)
Ejemplo n.º 13
0
    def _system_model_2Q(self,
                         v0=5.0,
                         v1=5.1,
                         j=0.01,
                         r=0.02,
                         alpha0=-0.33,
                         alpha1=-0.33,
                         qub_dim=3):
        """Constructs a simple 2 transmon PulseSystemModel."""

        hamiltonian = {}
        hamiltonian['h_str'] = []
        # Q0 terms
        hamiltonian['h_str'].append('np.pi*(2*v0-alpha0)*O0')
        hamiltonian['h_str'].append('np.pi*alpha0*O0*O0')
        hamiltonian['h_str'].append('2*np.pi*r*X0||D0')

        # Q1 terms
        hamiltonian['h_str'].append('np.pi*(2*v1-alpha1)*O1')
        hamiltonian['h_str'].append('np.pi*alpha1*O1*O1')
        hamiltonian['h_str'].append('2*np.pi*r*X1||D1')

        # Exchange coupling and ControlChannel terms
        hamiltonian['h_str'].append('2*np.pi*j*(Sp0*Sm1+Sm0*Sp1)')
        hamiltonian['h_str'].append('2*np.pi*r*X0||U0')
        hamiltonian['h_str'].append('2*np.pi*r*X1||U1')

        # set vars and qubit dimensions
        hamiltonian['vars'] = {'v0': v0, 'v1': v1, 'j': j,
                               'r': r, 'alpha0': alpha0, 'alpha1': alpha1}
        hamiltonian['qub'] = {'0' : qub_dim, '1' : qub_dim}

        ham_model = HamiltonianModel.from_dict(hamiltonian)


        # set up u channel freqs,
        u_channel_lo = [[{'q': 1, 'scale': [1.0, 0.0]}],
                        [{'q': 0, 'scale': [1.0, 0.0]}]]
        subsystem_list = [0, 1]
        dt = 1.

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
    def _system_model_2Q(self, omega_0, omega_a, omega_i, qubit_dim=2):
        """Constructs a simple 1 qubit system model.

        Args:
            omega_0 (float): frequency of qubit
            omega_a (float): strength of drive term
            omega_i (float): strength of interaction
            qubit_dim (int): dimension of qubit
        Returns:
            PulseSystemModel: model for qubit system
        """

        # make Hamiltonian
        hamiltonian = {}
        # qubit 0 terms
        hamiltonian['h_str'] = ['-0.5*omega0*Z0', '0.5*omegaa*X0||D0']
        # interaction term
        hamiltonian['h_str'].append('omegai*(Sp0*Sm1+Sm0*Sp1)||U1')
        hamiltonian['vars'] = {
            'omega0': omega_0,
            'omegaa': omega_a,
            'omegai': omega_i
        }
        hamiltonian['qub'] = {'0': qubit_dim, '1': qubit_dim}
        ham_model = HamiltonianModel.from_dict(hamiltonian)

        u_channel_lo = [[{
            'q': 0,
            'scale': [1.0, 0.0]
        }], [{
            'q': 0,
            'scale': [-1.0, 0.0]
        }, {
            'q': 1,
            'scale': [1.0, 0.0]
        }]]
        subsystem_list = [0, 1]
        dt = 1.

        return PulseSystemModel(hamiltonian=ham_model,
                                u_channel_lo=u_channel_lo,
                                subsystem_list=subsystem_list,
                                dt=dt)
    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))
Ejemplo n.º 16
0
    def test_subsystem_list_from_dict(self):
        """Test correct restriction of a Hamiltonian dict to a subset of systems"""

        # construct 2 duffing oscillator hamiltonian
        v0 = 5.0
        v1 = 5.1
        j = 0.01
        r = 0.02
        alpha0 = -0.33
        alpha1 = -0.33

        hamiltonian = {}
        hamiltonian['h_str'] = [
            'np.pi*(2*v0-alpha0)*O0', 'np.pi*alpha0*O0*O0', '2*np.pi*r*X0||D0',
            '2*np.pi*r*X0||U1', '2*np.pi*r*X1||U0', 'np.pi*(2*v1-alpha1)*O1',
            'np.pi*alpha1*O1*O1', '2*np.pi*r*X1||D1',
            '2*np.pi*j*(Sp0*Sm1+Sm0*Sp1)'
        ]
        hamiltonian['qub'] = {'0': 3, '1': 3}
        hamiltonian['vars'] = {
            'v0': v0,
            'v1': v1,
            'j': j,
            'r': r,
            'alpha0': alpha0,
            'alpha1': alpha1
        }

        # restrict to qubit 0 and verify some properties
        ham_model0 = HamiltonianModel.from_dict(hamiltonian,
                                                subsystem_list=[0])
        evals_expected0 = np.array([
            0, np.pi * (2 * v0 - alpha0) + np.pi * alpha0,
            (2 * np.pi * (2 * v0 - alpha0)) + (4 * np.pi * alpha0)
        ])
        eval_diff = norm(evals_expected0 - ham_model0._evals)
        self.assertAlmostEqual(eval_diff, 0)

        channel_labels0 = ham_model0._channels.keys()
        for key in ['D0', 'U1']:
            self.assertTrue(key in channel_labels0)
        self.assertEqual(len(channel_labels0), 2)

        qubit_lo_freq0 = ham_model0.get_qubit_lo_from_drift()
        expected_freq0 = np.array([
            (np.pi * (2 * v0 - alpha0) + np.pi * alpha0) / (2 * np.pi)
        ])
        self.assertAlmostEqual(norm(qubit_lo_freq0 - expected_freq0), 0)

        # restrict to qubit 1 and verify some properties
        ham_model1 = HamiltonianModel.from_dict(hamiltonian,
                                                subsystem_list=[1])
        evals_expected1 = np.array([
            0, np.pi * (2 * v1 - alpha1) + np.pi * alpha1,
            (2 * np.pi * (2 * v1 - alpha1)) + (4 * np.pi * alpha1)
        ])
        eval_diff = norm(evals_expected1 - ham_model1._evals)
        self.assertAlmostEqual(eval_diff, 0)

        channel_labels1 = ham_model1._channels.keys()
        for key in ['D1', 'U0']:
            self.assertTrue(key in channel_labels1)
        self.assertEqual(len(channel_labels1), 2)

        qubit_lo_freq1 = ham_model1.get_qubit_lo_from_drift()
        expected_freq1 = np.array(
            [0, (np.pi * (2 * v1 - alpha1) + np.pi * alpha1) / (2 * np.pi)])
        self.assertAlmostEqual(norm(qubit_lo_freq1 - expected_freq1), 0)
    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))
Ejemplo n.º 18
0
def convert_qutip_ham(config, subsystem_list, add_y=True, no_control=True, two_level=False, omegad_mult=None):
    """Convert an IBM backend to a qutip formatted hamiltonian.

    Args:
        config (backend.configuration): Backend configuration to get the hamiltonian from 
        subsystem_list (List[int]): List of qubits which the gate will act on (so far only tested on [0] or [0,1])
        add_y (bool, optional): Whether or not to perform the RWA and get a sigmay term. Defaults to True.
        no_control (bool, optional): Whether or not to ignore the control channels. Defaults to True.
        two_level (bool, optional): Whether to use a two level model or not. Defaults to False.
        omegad_mult (bool, optional): Whether to multiply the drive terms by a factor (see the writeup). Defaults to None.

    Raises:
        NotImplementedError: Only tested with qubits 0 and 1 right now, but could just remove this error
        NotImplementedError: No 3+ qubit operations examined yet.
        NotImplementedError: Right now we aren't using the control channels.

    Returns:
        [type]: [description]
    """

    if two_level:
        return two_level_ham(config, subsystem_list, add_y, no_control)

    a = Qobj([[0, 1, 0], [0, 0, sqrt(2)], [0, 0, 0]])
    adag = Qobj([[0, 0, 0], [1, 0, 0], [0, sqrt(2), 0]])

    geny = complex(0, 1) * (adag - a)

    bigy1 = Qobj(tensor(geny, identity(3)).full())
    bigy2 = Qobj(tensor(identity(3), geny).full())
    hamiltonian_backend = config.hamiltonian
    if omegad_mult:
        for i in range(input_backend.configuration().n_qubits):
            hamiltonian_backend['vars']['omegad' + str(i)] = hamiltonian_backend['vars']['omegad' + str(i)]  * omegad_mult
    hamiltonian_dict = HamiltonianModel.from_dict(
        hamiltonian_backend, subsystem_list=subsystem_list)
    hamiltonian = {'H_c': {}, 'iH_c': {}, 'H_d': 0}
    for i, control_field in enumerate(hamiltonian_dict._system):
        matrix = (control_field[0])
        prefactor, control = prefactor_parser(control_field[1], hamiltonian_dict._variables)
        if prefactor == 0:
            continue
        if control:
            # prefactor = prefactor * 2
            if 'D' in control:
                hamiltonian['H_c'][control] = Qobj(matrix.full() * prefactor)
                if add_y:
                    if len(subsystem_list) == 1:
                        hamiltonian['H_c'][control + 'y'] = Qobj(geny * prefactor)
                    elif len(subsystem_list) == 2:
                        print("Double checkthat sigx2 and  sigy2 are right")
                        if control == 'D0':
                            hamiltonian['H_c'][control + 'y'] = Qobj(bigy1 * prefactor)
                        elif control == 'D1':
                            hamiltonian['H_c'][control + 'y'] = Qobj(bigy2 * prefactor)
                        else:
                            raise NotImplementedError("Only q0 and q1 rn")
                    else:
                        raise NotImplementedError("Only 1-2q operations supported")
            elif no_control:
                print('not using control channels, skippping...')
            else:
                raise NotImplementedError("No use for control channels currently")
        elif hamiltonian['H_d'] == 0:
            hamiltonian['H_d'] = matrix * prefactor
        else:
            hamiltonian['H_d'] += matrix * prefactor
    if hamiltonian['H_d'] != 0:
        hamiltonian['H_d'] = Qobj(hamiltonian['H_d'].full())
        if hamiltonian['H_d'] == 0:
            hamiltonian['H_d'] = Qobj(np.zeros((3, 3)))
    else:
        print("Drift hamiltonian is 0, (Likely due to missing variables in backend db), do not trust results.")
        hamiltonian['H_d'] = Qobj(np.zeros((3, 3)))

    return hamiltonian