def setUp(self): self._default_qubit_lo_freq = [4.9, 5.0] self._u_channel_lo = [] self._u_channel_lo.append([UchannelLO(0, 1.0 + 0.0j)]) self._u_channel_lo.append( [UchannelLO(0, -1.0 + 0.0j), UchannelLO(1, 1.0 + 0.0j)])
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_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 = [[UchannelLO(0, 1.0 + 0.0j)]] u_channel_lo.append( [UchannelLO(0, -1.0 + 0.0j), UchannelLO(2, 1.0 + 0.0j)]) u_channel_lo.append( [UchannelLO(1, -1.0 + 0.0j), UchannelLO(2, 1.0 + 0.0j)]) dt = 1. return PulseSystemModel(hamiltonian=ham_model, u_channel_lo=u_channel_lo, subsystem_list=subsystem_list, dt=dt)
def test_set_system_model_from_backend(self): """Test setting system model when constructing from backend.""" armonk_backend = FakeArmonk() system_model = self._system_model_1Q() # these are 1q systems so this doesn't make sense but can still be used to test system_model.u_channel_lo = [[UchannelLO(0, 1.0 + 0.0j)]] armonk_sim = None # construct backend and catch warning with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") armonk_sim = PulseSimulator.from_backend(backend=armonk_backend, system_model=system_model) self.assertEqual(len(w), 1) self.assertTrue('inconsistencies' in str(w[-1].message)) # check that system model properties have been imported self.assertEqual(armonk_sim.configuration().dt, system_model.dt) self.assertEqual(armonk_sim.configuration().u_channel_lo, system_model.u_channel_lo)
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)
def _system_model_2Q(self, omega_0, omega_a, omega_i, qubit_dim=2): """Constructs a simple 2 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 = [[UchannelLO(0, 1.0 + 0.0j)], [ UchannelLO(0, -1.0 + 0.0j), UchannelLO(1, 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)
def test_cr_lo_list(self): """Test _cr_lo_list""" cr_dict = {(0, 1): 0, (1, 0): 1, (3, 4): 2} expected = [[UchannelLO(1, 1.0 + 0.0j)], [UchannelLO(0, 1.0 + 0.0j)], [UchannelLO(4, 1.0 + 0.0j)]] self.assertEqual(model_gen._cr_lo_list(cr_dict), expected) cr_dict = {(0, 1): 0, (3, 4): 2, (1, 0): 1} expected = [[UchannelLO(1, 1.0 + 0.0j)], [UchannelLO(0, 1.0 + 0.0j)], [UchannelLO(4, 1.0 + 0.0j)]] self.assertEqual(model_gen._cr_lo_list(cr_dict), expected)
def test_set_system_model_options(self): """Test setting of options that need to be changed in multiple places.""" athens_backend = FakeAthens() athens_sim = PulseSimulator.from_backend(athens_backend) # u channel lo set_attr = [[UchannelLO(0, 1.0 + 0.0j)]] athens_sim.set_options(u_channel_lo=set_attr) sim_attr = athens_sim.configuration().u_channel_lo model_attr = athens_sim._system_model.u_channel_lo self.assertTrue(sim_attr == set_attr and model_attr == set_attr) # dt set_attr = 5. athens_sim.set_options(dt=set_attr) sim_attr = athens_sim.configuration().dt model_attr = athens_sim._system_model.dt self.assertTrue(sim_attr == set_attr and model_attr == set_attr)
def test_set_system_model_after_construction(self): """Test setting the system model after construction.""" system_model = self._system_model_1Q() # these are 1q systems so this doesn't make sense but can still be used to test system_model.u_channel_lo = [[UchannelLO(0, 1.0 + 0.0j)]] # first test setting after construction with no hamiltonian test_sim = PulseSimulator() with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") test_sim.set_options(system_model=system_model) self.assertEqual(len(w), 0) # check that system model properties have been imported self.assertEqual(test_sim._system_model, system_model) self.assertEqual(test_sim.configuration().dt, system_model.dt) self.assertEqual(test_sim.configuration().u_channel_lo, system_model.u_channel_lo) # next, construct a pulse simulator with a config containing a Hamiltonian and observe # warnings armonk_backend = FakeArmonk() test_sim = PulseSimulator(configuration=armonk_backend.configuration()) # add system model and verify warning is raised with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") armonk_sim = test_sim.set_options(system_model=system_model) self.assertEqual(len(w), 1) self.assertTrue('inconsistencies' in str(w[-1].message)) self.assertEqual(test_sim.configuration().dt, system_model.dt) self.assertEqual(test_sim.configuration().u_channel_lo, system_model.u_channel_lo)
def test_set_system_model_in_constructor(self): """Test setting system model when constructing.""" system_model = self._system_model_1Q() # these are 1q systems so this doesn't make sense but can still be used to test system_model.u_channel_lo = [[UchannelLO(0, 1.0 + 0.0j)]] # construct directly test_sim = None # construct backend and verify no warnings with warnings.catch_warnings(record=True) as w: # Cause all warnings to always be triggered. warnings.simplefilter("always") test_sim = PulseSimulator(system_model=system_model) self.assertEqual(len(w), 0) # check that system model properties have been imported self.assertEqual(test_sim.configuration().dt, system_model.dt) self.assertEqual(test_sim.configuration().u_channel_lo, system_model.u_channel_lo)
def test_duffing_system_model1(self): """First test of duffing_system_model, 2 qubits, 2 dimensional""" dim_oscillators = 2 oscillator_freqs = [5.0, 5.1] anharm_freqs = [-0.33, -0.33] drive_strengths = [1.1, 1.2] coupling_dict = {(0,1): 0.02} dt = 1.3 system_model = model_gen.duffing_system_model(dim_oscillators, oscillator_freqs, anharm_freqs, drive_strengths, coupling_dict, dt) cr_idx_dict = {label: idx for idx, label in enumerate(system_model.control_channel_labels)} # check basic parameters self.assertEqual(system_model.subsystem_list, [0, 1]) self.assertEqual(system_model.dt, 1.3) # check that cr_idx_dict is correct self.assertEqual(cr_idx_dict, {(0,1): 0, (1,0): 1}) self.assertEqual(system_model.control_channel_index((0,1)), 0) # check u_channel_lo is correct self.assertEqual(system_model.u_channel_lo, [[UchannelLO(1, 1.0+0.0j)], [UchannelLO(0, 1.0+0.0j)]]) # check consistency of system_model.u_channel_lo with cr_idx_dict # this should in principle be redundant with the above two checks for q_pair, idx in cr_idx_dict.items(): self.assertEqual(system_model.u_channel_lo[idx], [UchannelLO(q_pair[1], 1.0+0.0j)]) # check correct hamiltonian ham_model = system_model.hamiltonian expected_vars = {'v0': 5.0, 'v1': 5.1, 'alpha0': -0.33, 'alpha1': -0.33, 'r0': 1.1, 'r1': 1.2, 'j01': 0.02} self.assertEqual(ham_model._variables, expected_vars) self.assertEqual(ham_model._subsystem_dims, {0: 2, 1: 2}) self._compare_str_lists(list(ham_model._channels), ['D0', 'D1', 'U0', 'U1']) # check that Hamiltonian terms have been imported correctly # constructing the expected_terms requires some knowledge of how the strings get generated # and then parsed O0 = self._operator_array_from_str(2, ['I', 'O']) O1 = self._operator_array_from_str(2, ['O', 'I']) OO0 = O0 & O0 OO1 = O1 & O1 X0 = self._operator_array_from_str(2, ['I', 'X']) X1 = self._operator_array_from_str(2, ['X', 'I']) exchange = self._operator_array_from_str(2, ['Sm', 'Sp']) + self._operator_array_from_str(2, ['Sp', 'Sm']) expected_terms = [('np.pi*(2*v0-alpha0)', O0), ('np.pi*(2*v1-alpha1)', O1), ('np.pi*alpha0', OO0), ('np.pi*alpha1', OO1), ('2*np.pi*r0*D0', X0), ('2*np.pi*r1*D1', X1), ('2*np.pi*j01', exchange), ('2*np.pi*r0*U0', X0), ('2*np.pi*r1*U1', X1)] # first check the number of terms is correct, then loop through # each expected term and verify that it is present and consistent self.assertEqual(len(ham_model._system), len(expected_terms)) for expected_string, expected_op in expected_terms: idx = 0 found = False while idx < len(ham_model._system) and found is False: op, string = ham_model._system[idx] if expected_string == string: found = True self.assertTrue(array_equal(expected_op, op)) idx += 1 self.assertTrue(found)
def test_duffing_system_model3(self): """Third test of duffing_system_model, 4 qubits, 2 dimensional""" # do similar tests for different model dim_oscillators = 2 oscillator_freqs = [5.0, 5.1, 5.2, 5.3] anharm_freqs = [-0.33, -0.33, -0.32, -0.31] drive_strengths = [1.1, 1.2, 1.3, 1.4] coupling_dict = {(0,2): 0.03, (1,0): 0.02, (0,3): 0.14, (3,1): 0.18, (1,2) : 0.33} dt = 1.3 system_model = model_gen.duffing_system_model(dim_oscillators, oscillator_freqs, anharm_freqs, drive_strengths, coupling_dict, dt) cr_idx_dict = {label: idx for idx, label in enumerate(system_model.control_channel_labels)} # check basic parameters self.assertEqual(system_model.subsystem_list, [0, 1, 2, 3]) self.assertEqual(system_model.dt, 1.3) # check that cr_idx_dict is correct self.assertEqual(cr_idx_dict, {(0,1): 0, (1,0): 1, (0,2): 2, (2,0): 3, (0,3): 4, (3,0): 5, (1,2): 6, (2,1): 7, (1,3): 8, (3,1): 9}) self.assertEqual(system_model.control_channel_index((1,2)), 6) # check u_channel_lo is correct self.assertEqual(system_model.u_channel_lo, [[UchannelLO(1, 1.0+0.0j)], [UchannelLO(0, 1.0+0.0j)], [UchannelLO(2, 1.0+0.0j)], [UchannelLO(0, 1.0+0.0j)], [UchannelLO(3, 1.0+0.0j)], [UchannelLO(0, 1.0+0.0j)], [UchannelLO(2, 1.0+0.0j)], [UchannelLO(1, 1.0+0.0j)], [UchannelLO(3, 1.0+0.0j)], [UchannelLO(1, 1.0+0.0j)]]) # check consistency of system_model.u_channel_lo with cr_idx_dict # this should in principle be redundant with the above two checks for q_pair, idx in cr_idx_dict.items(): self.assertEqual(system_model.u_channel_lo[idx], [UchannelLO(q_pair[1], 1.0+0.0j)]) # check correct hamiltonian ham_model = system_model.hamiltonian expected_vars = {'v0': 5.0, 'v1': 5.1, 'v2': 5.2, 'v3': 5.3, 'alpha0': -0.33, 'alpha1': -0.33, 'alpha2': -0.32, 'alpha3': -0.31, 'r0': 1.1, 'r1': 1.2, 'r2': 1.3, 'r3': 1.4, 'j01': 0.02, 'j02': 0.03, 'j03': 0.14, 'j12': 0.33, 'j13': 0.18} self.assertEqual(ham_model._variables, expected_vars) self.assertEqual(ham_model._subsystem_dims, {0: 2, 1: 2, 2: 2, 3: 2}) self._compare_str_lists(list(ham_model._channels), ['D0', 'D1', 'D3', 'D4', 'U0', 'U1', 'U2', 'U3', 'U4', 'U5', 'U6', 'U7', 'U8', 'U9']) # check that Hamiltonian terms have been imported correctly # constructing the expected_terms requires some knowledge of how the strings get generated # and then parsed O0 = self._operator_array_from_str(2, ['I', 'I', 'I', 'O']) O1 = self._operator_array_from_str(2, ['I', 'I', 'O', 'I']) O2 = self._operator_array_from_str(2, ['I', 'O', 'I', 'I']) O3 = self._operator_array_from_str(2, ['O', 'I', 'I', 'I']) OO0 = O0 & O0 OO1 = O1 & O1 OO2 = O2 & O2 OO3 = O3 & O3 X0 = self._operator_array_from_str(2, ['I','I', 'I', 'A']) + self._operator_array_from_str(2, ['I', 'I', 'I', 'C']) X1 = self._operator_array_from_str(2, ['I', 'I', 'A', 'I']) + self._operator_array_from_str(2, ['I', 'I', 'C', 'I']) X2 = self._operator_array_from_str(2, ['I', 'A', 'I', 'I']) + self._operator_array_from_str(2, ['I', 'C', 'I', 'I']) X3 = self._operator_array_from_str(2, ['A', 'I', 'I', 'I']) + self._operator_array_from_str(2, ['C', 'I', 'I', 'I']) exchange01 = self._operator_array_from_str(2, ['I', 'I', 'Sm', 'Sp']) + self._operator_array_from_str(2, ['I', 'I', 'Sp', 'Sm']) exchange02 = self._operator_array_from_str(2, ['I', 'Sm', 'I', 'Sp']) + self._operator_array_from_str(2, ['I', 'Sp', 'I', 'Sm']) exchange03 = self._operator_array_from_str(2, ['Sm', 'I', 'I', 'Sp']) + self._operator_array_from_str(2, ['Sp', 'I', 'I', 'Sm']) exchange12 = self._operator_array_from_str(2, ['I', 'Sm', 'Sp', 'I']) + self._operator_array_from_str(2, ['I', 'Sp', 'Sm', 'I']) exchange13 = self._operator_array_from_str(2, ['Sm', 'I', 'Sp', 'I']) + self._operator_array_from_str(2, ['Sp', 'I', 'Sm', 'I']) expected_terms = [('np.pi*(2*v0-alpha0)', O0), ('np.pi*(2*v1-alpha1)', O1), ('np.pi*(2*v2-alpha2)', O2), ('np.pi*(2*v3-alpha3)', O3), ('np.pi*alpha0', OO0), ('np.pi*alpha1', OO1), ('np.pi*alpha2', OO2), ('np.pi*alpha3', OO3), ('2*np.pi*r0*D0', X0), ('2*np.pi*r1*D1', X1), ('2*np.pi*r2*D2', X2), ('2*np.pi*r3*D3', X3), ('2*np.pi*j01', exchange01), ('2*np.pi*j02', exchange02), ('2*np.pi*j03', exchange03), ('2*np.pi*j12', exchange12), ('2*np.pi*j13', exchange13), ('2*np.pi*r0*U0', X0), ('2*np.pi*r1*U1', X1), ('2*np.pi*r0*U2', X0), ('2*np.pi*r2*U3', X2), ('2*np.pi*r0*U4', X0), ('2*np.pi*r3*U5', X3), ('2*np.pi*r1*U6', X1), ('2*np.pi*r2*U7', X2), ('2*np.pi*r1*U8', X1), ('2*np.pi*r3*U9', X3)] # first check the number of terms is correct, then loop through # each expected term and verify that it is present and consistent self.assertEqual(len(ham_model._system), len(expected_terms)) for expected_string, expected_op in expected_terms: idx = 0 found = False while idx < len(ham_model._system) and found is False: op, string = ham_model._system[idx] if expected_string == string: found = True self.assertTrue(array_equal(expected_op, op)) idx += 1 self.assertTrue(found)