diff --git a/qiskit/providers/aer/pulse/system_models/duffing_model_generators.py b/qiskit/providers/aer/pulse/system_models/duffing_model_generators.py index 7d980c73dc..4fc5431971 100644 --- a/qiskit/providers/aer/pulse/system_models/duffing_model_generators.py +++ b/qiskit/providers/aer/pulse/system_models/duffing_model_generators.py @@ -17,6 +17,7 @@ from warnings import warn from collections.abc import Iterable +from qiskit.providers.models.backendconfiguration import UchannelLO from .hamiltonian_model import HamiltonianModel from .pulse_system_model import PulseSystemModel @@ -123,7 +124,6 @@ def duffing_system_model(dim_oscillators, anharm_symbol = 'alpha' drive_symbol = 'r' coupling_symbol = 'j' - coupling_edges = coupling_dict.keys() # construct coupling graph, and raise warning if coupling_edges contains duplicate edges @@ -142,8 +142,13 @@ def duffing_system_model(dim_oscillators, sorted_coupling_edges = coupling_graph.sorted_graph # populate coupling strengths in sorted order (vertex indices are now also sorted within edges, # so this needs to be accounted for when retrieving weights from coupling_dict) - coupling_strengths = [coupling_dict.get(edge) or coupling_dict.get((edge[1], edge[0])) for - edge in sorted_coupling_edges] + coupling_strengths = [] + for edge in sorted_coupling_edges: + edge_strength = coupling_dict.get(edge) + if edge_strength is None: + edge_strength = coupling_dict.get((edge[1], edge[0])) + coupling_strengths.append(edge_strength) + coupling_symbols = _str_list_generator(coupling_symbol + '{0}{1}', *zip(*sorted_coupling_edges)) cr_idx_dict = coupling_graph.two_way_graph_dict @@ -269,7 +274,7 @@ def _cr_lo_list(cr_idx_dict): # populate list of u channel lo for cr gates lo_list = [0] * len(cr_idx_dict) for system_pair, u_idx in cr_idx_dict.items(): - lo_list[u_idx] = [{'scale': [1.0, 0.0], 'q': system_pair[1]}] + lo_list[u_idx] = [UchannelLO(system_pair[1], 1.0 + 0.0j)] return lo_list diff --git a/qiskit/providers/aer/pulse/system_models/pulse_system_model.py b/qiskit/providers/aer/pulse/system_models/pulse_system_model.py index 33759e1bc2..db139926da 100644 --- a/qiskit/providers/aer/pulse/system_models/pulse_system_model.py +++ b/qiskit/providers/aer/pulse/system_models/pulse_system_model.py @@ -217,9 +217,9 @@ def calculate_channel_frequencies(self, qubit_lo_freq=None): elif key[0] == 'U': freqs[key] = 0 for u_lo_idx in self.u_channel_lo[chidx]: - if u_lo_idx['q'] < len(qubit_lo_freq): - qfreq = qubit_lo_freq[u_lo_idx['q']] - qscale = u_lo_idx['scale'][0] + if u_lo_idx.q < len(qubit_lo_freq): + qfreq = qubit_lo_freq[u_lo_idx.q] + qscale = u_lo_idx.scale.real freqs[key] += qfreq * qscale else: raise ValueError("Channel is not D or U") diff --git a/test/terra/backends/test_pulse_simulator.py b/test/terra/backends/test_pulse_simulator.py index d6fcad4f2b..80471ee357 100644 --- a/test/terra/backends/test_pulse_simulator.py +++ b/test/terra/backends/test_pulse_simulator.py @@ -30,6 +30,7 @@ ControlChannel, AcquireChannel, MemorySlot) from qiskit.providers.aer.pulse.system_models.pulse_system_model import PulseSystemModel from qiskit.providers.aer.pulse.system_models.hamiltonian_model import HamiltonianModel +from qiskit.providers.models.backendconfiguration import UchannelLO class TestPulseSimulator(common.QiskitAerTestCase): @@ -882,8 +883,10 @@ def _system_model_2Q(self, omega_0, omega_a, omega_i, qubit_dim=2): 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]}]] + 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. @@ -925,9 +928,9 @@ def _system_model_3Q(self, omega_0, omega_a, omega_i, qubit_dim=2, subsystem_lis 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]}]] + 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, diff --git a/test/terra/openpulse/test_duffing_model_generators.py b/test/terra/openpulse/test_duffing_model_generators.py index d21cf108e8..efcf43bcbe 100644 --- a/test/terra/openpulse/test_duffing_model_generators.py +++ b/test/terra/openpulse/test_duffing_model_generators.py @@ -20,6 +20,7 @@ from qiskit.providers.aer.pulse.system_models.hamiltonian_model import HamiltonianModel from qiskit.providers.aer.pulse.system_models import duffing_model_generators as model_gen from qiskit.providers.aer.pulse.qutip_extra_lite.qobj_generators import get_oper +from qiskit.providers.models.backendconfiguration import UchannelLO class TestDuffingModelGenerators(QiskitAerTestCase): """Tests for functions in duffing_model_generators.py""" @@ -55,13 +56,13 @@ def test_duffing_system_model1(self): # check u_channel_lo is correct self.assertEqual(system_model.u_channel_lo, - [[{'scale': [1.0, 0.0], 'q' : 1}], [{'scale': [1.0, 0.0], 'q' : 0}]]) + [[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], - [{'scale': [1.0, 0.0], 'q' : q_pair[1]}]) + [UchannelLO(q_pair[1], 1.0+0.0j)]) # check correct hamiltonian ham_model = system_model.hamiltonian @@ -136,16 +137,16 @@ def test_duffing_system_model2(self): # check u_channel_lo is correct self.assertEqual(system_model.u_channel_lo, - [[{'scale': [1.0, 0.0], 'q' : 1}], - [{'scale': [1.0, 0.0], 'q' : 0}], - [{'scale': [1.0, 0.0], 'q' : 2}], - [{'scale': [1.0, 0.0], 'q' : 1}]]) + [[UchannelLO(1, 1.0+0.0j)], + [UchannelLO(0, 1.0+0.0j)], + [UchannelLO(2, 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], - [{'scale': [1.0, 0.0], 'q' : q_pair[1]}]) + [UchannelLO(q_pair[1], 1.0+0.0j)]) # check correct hamiltonian ham_model = system_model.hamiltonian @@ -234,17 +235,17 @@ def test_duffing_system_model3(self): # check u_channel_lo is correct self.assertEqual(system_model.u_channel_lo, - [[{'scale': [1.0, 0.0], 'q' : 1}], [{'scale': [1.0, 0.0], 'q' : 0}], - [{'scale': [1.0, 0.0], 'q' : 2}], [{'scale': [1.0, 0.0], 'q' : 0}], - [{'scale': [1.0, 0.0], 'q' : 3}], [{'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' : 3}], [{'scale': [1.0, 0.0], 'q' : 1}]]) + [[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], - [{'scale': [1.0, 0.0], 'q' : q_pair[1]}]) + [UchannelLO(q_pair[1], 1.0+0.0j)]) # check correct hamiltonian ham_model = system_model.hamiltonian @@ -404,20 +405,42 @@ def test_duffing_hamiltonian_dict(self): self.assertEqual(output['qub'], expected['qub']) + def test_calculate_channel_frequencies(self): + """test calculate_channel_frequencies of resulting PulseSystemModel objects""" + + 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.0} + dt = 1.3 + + system_model = model_gen.duffing_system_model(dim_oscillators, + oscillator_freqs, + anharm_freqs, + drive_strengths, + coupling_dict, + dt) + + channel_freqs = system_model.calculate_channel_frequencies([5.0, 5.1]) + expected = {'D0' : 5.0, 'D1' : 5.1, 'U0' : 5.1, 'U1': 5.0} + self.assertEqual(dict(channel_freqs), expected) + + def test_cr_lo_list(self): """Test _cr_lo_list""" cr_dict = {(0,1): 0, (1,0) : 1, (3,4) : 2} - expected = [[{'scale' : [1.0, 0], 'q' : 1}], - [{'scale' : [1.0, 0], 'q' : 0}], - [{'scale' : [1.0, 0], 'q' : 4}]] + 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 = [[{'scale' : [1.0, 0], 'q' : 1}], - [{'scale' : [1.0, 0], 'q' : 0}], - [{'scale' : [1.0, 0], 'q' : 4}]] + 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_single_term_generators(self): diff --git a/test/terra/openpulse/test_system_models.py b/test/terra/openpulse/test_system_models.py index ff6625adc2..4ead4608db 100644 --- a/test/terra/openpulse/test_system_models.py +++ b/test/terra/openpulse/test_system_models.py @@ -25,6 +25,8 @@ from qiskit.compiler import assemble from qiskit.providers.aer.pulse.system_models.pulse_system_model import PulseSystemModel from qiskit.providers.aer.pulse.system_models.hamiltonian_model import HamiltonianModel +from qiskit.test.mock import FakeArmonk +from qiskit.providers.models.backendconfiguration import UchannelLO class BaseTestPulseSystemModel(QiskitAerTestCase): @@ -32,8 +34,9 @@ class BaseTestPulseSystemModel(QiskitAerTestCase): def setUp(self): self._default_qubit_lo_freq = [4.9, 5.0] - self._u_channel_lo = [[{'q': 0, 'scale': [1.0, 0.0]}], - [{'q': 0, 'scale': [-1.0, 0.0]}, {'q': 1, 'scale': [1.0, 0.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 _simple_system_model(self, v0=5.0, v1=5.1, j=0.01, r=0.02, alpha0=-0.33, alpha1=-0.33): hamiltonian = {} @@ -150,6 +153,13 @@ def test_qubit_lo_from_hamiltonian(self): self.assertAlmostEqual(freqs['U0'], 5.101980390271) self.assertAlmostEqual(freqs['U1'], -0.203960780543) + def test_qubit_lo_from_configurable_backend(self): + backend = FakeArmonk() + test_model = PulseSystemModel.from_backend(backend) + qubit_lo_from_hamiltonian = test_model.hamiltonian.get_qubit_lo_from_drift() + freqs = test_model.calculate_channel_frequencies(qubit_lo_from_hamiltonian) + self.assertAlmostEqual(freqs['D0'], 4.974286046328553) + def _compute_u_lo_freqs(self, qubit_lo_freq): """ Given qubit_lo_freq, return the computed u_channel_lo. @@ -158,8 +168,8 @@ def _compute_u_lo_freqs(self, qubit_lo_freq): for scales in self._u_channel_lo: u_lo_freq = 0 for u_lo_idx in scales: - qfreq = qubit_lo_freq[u_lo_idx['q']] - qscale = u_lo_idx['scale'][0] + qfreq = qubit_lo_freq[u_lo_idx.q] + qscale = u_lo_idx.scale.real u_lo_freq += qfreq * qscale u_lo_freqs.append(u_lo_freq) return u_lo_freqs