Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
13 changes: 8 additions & 5 deletions test/terra/backends/test_pulse_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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,
Expand Down
61 changes: 42 additions & 19 deletions test/terra/openpulse/test_duffing_model_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"""
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
18 changes: 14 additions & 4 deletions test/terra/openpulse/test_system_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@
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):
"""Tests for PulseSystemModel"""

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 = {}
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down