Skip to content

Commit

Permalink
Add rand_pulse_sequence function
Browse files Browse the repository at this point in the history
Makes tests more readable
  • Loading branch information
thangleiter committed May 3, 2020
1 parent a6efb1e commit 6433fed
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 202 deletions.
50 changes: 19 additions & 31 deletions tests/test_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"""
This module tests the operator basis module.
"""

from copy import copy
from itertools import product

import numpy as np
Expand Down Expand Up @@ -229,7 +229,7 @@ def test_basis_generation_from_partial_random(self):
# Get a random traceless hermitian operator
oper = testutil.rand_herm_traceless(d)
# ... and build a basis from it
b = ff.Basis(np.array([oper]))
b = ff.Basis(oper)
self.assertTrue(b.isorthonorm)
self.assertTrue(b.isherm)
self.assertTrue(b.istraceless)
Expand All @@ -253,7 +253,7 @@ def test_basis_generation_from_partial_random(self):
# Get a random hermitian operator
oper = testutil.rand_herm(d)
# ... and build a basis from it
b = ff.Basis(np.array([oper]))
b = ff.Basis(oper)
self.assertTrue(b.isorthonorm)
self.assertTrue(b.isherm)
self.assertFalse(b.istraceless)
Expand All @@ -274,55 +274,43 @@ def test_basis_generation_from_partial_random(self):
def test_filter_functions(self):
"""Filter functions equal for different bases"""
# Set up random Hamiltonian
c_oper = testutil.rand_herm(4)
c_opers = (c_oper,)
c_coeffs = ([0, 1, 0],)
H_c = list(zip(c_opers, c_coeffs))

dt = np.ones(3)

n_oper = testutil.rand_herm_traceless(4)
n_oper[np.diag_indices(n_oper.shape[-1])] = 0
n_oper = ff.basis.normalize(n_oper)

H_n = [[n_oper, np.ones_like(dt)]]

omega = np.concatenate([-np.logspace(3, -3, 100),
np.logspace(-3, 3, 100)])
base_pulse = testutil.rand_pulse_sequence(4, 3, 1, 1)
omega = ff.util.get_sample_frequencies(base_pulse, n_samples=200)

pauli_basis = ff.Basis.pauli(2)
ggm_basis = ff.Basis.ggm(4)
from_random_basis = ff.Basis([n_oper])
from_random_basis = ff.Basis(base_pulse.n_opers)
bases = (pauli_basis, ggm_basis, from_random_basis)

# Get Pulses
pulses = [ff.PulseSequence(H_c, H_n, dt, basis=b) for b in bases]
F = [pulse.get_filter_function(omega).sum(0) for pulse in pulses]
# Get Pulses with different bases
F = []
for b in bases:
pulse = copy(base_pulse)
pulse.basis = b
F.append(pulse.get_filter_function(omega).sum(0))

for pair in product(F, F):
self.assertArrayAlmostEqual(*pair)

def test_control_matrix(self):
"""Test control matrix for traceless and non-traceless bases"""
c_opers = testutil.rand_herm(3, 4)
c_coeffs = np.random.randn(4, 10)

n_opers_traceless = testutil.rand_herm_traceless(3, 4)
n_opers = testutil.rand_herm(3, 4)
n_coeffs = np.abs(np.random.randn(4, 10))

dt = np.abs(np.random.randn(10))
n_opers_traceless = testutil.rand_herm_traceless(3, 4)

basis = ff.Basis(testutil.rand_herm(3), traceless=False)
basis_traceless = ff.Basis(testutil.rand_herm_traceless(3),
traceless=True)

base_pulse = testutil.rand_pulse_sequence(3, 10, 4, 4)

omega = np.logspace(-1, 1, 51)

for i, base in enumerate((basis, basis_traceless)):
for j, n_ops in enumerate((n_opers, n_opers_traceless)):
pulse = ff.PulseSequence(list(zip(c_opers, c_coeffs)),
list(zip(n_ops, n_coeffs)),
dt, base)
pulse = copy(base_pulse)
pulse.n_opers = n_ops
pulse.basis = base

R = pulse.get_control_matrix(omega)

Expand Down
47 changes: 19 additions & 28 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@ class CoreTest(testutil.TestCase):

def test_pulse_sequence_constructor(self):
"""Test constructing a PulseSequence."""
identifiers = ('X', 'Y', 'Z')
H_c = list(zip(ff.util.P_np[1:], randn(3, 5), identifiers))
H_n = list(zip(ff.util.P_np[1:], np.abs(randn(3, 5)), identifiers))
base_pulse = testutil.rand_pulse_sequence(2, 5, 3, 3)
H_c = list(zip(base_pulse.c_opers, base_pulse.c_coeffs,
base_pulse.c_oper_identifiers))
H_n = list(zip(base_pulse.n_opers, base_pulse.n_coeffs,
base_pulse.n_oper_identifiers))
dt = base_pulse.dt

for i in range(3):
H_c[i] = list(H_c[i])
H_n[i] = list(H_n[i])
dt = np.abs(randn(5))

with self.assertRaises(TypeError):
# Not enough positional arguments
Expand Down Expand Up @@ -313,7 +316,7 @@ def test_pulse_sequence_attributes(self):
list(zip(A.c_opers, A.c_coeffs, A.c_oper_identifiers)),
list(zip(A.n_opers, A.n_coeffs, A.n_oper_identifiers)),
A.dt,
ff.Basis([elem])
ff.Basis(elem)
)
self.assertFalse(A == B)
self.assertTrue(A != B)
Expand Down Expand Up @@ -434,7 +437,8 @@ def test_pulse_sequence_attributes_concat(self):
self.assertArrayEqual(total_Q_liouville, pulse._total_Q_liouville)

# Test custom identifiers
letters = np.random.choice(list(string.ascii_letters), size=(6, 5))
letters = np.random.choice(list(string.ascii_letters), size=(6, 5),
replace=False)
ids = [''.join(l) for l in letters[:3]]
labels = [''.join(l) for l in letters[3:]]
pulse = ff.PulseSequence(
Expand All @@ -449,14 +453,10 @@ def test_pulse_sequence_attributes_concat(self):
def test_filter_function(self):
"""Test the filter function calculation and related methods"""
for d, n_dt in zip(randint(2, 10, (3,)), randint(10, 200, (3,))):
c_opers = testutil.rand_herm(d, 4)
c_coeffs = randn(4, n_dt)
n_opers = testutil.rand_herm_traceless(d, 6)
n_coeffs = randn(6, n_dt)
dt = np.abs(randn(n_dt))
total_pulse = ff.PulseSequence(list(zip(c_opers, c_coeffs)),
list(zip(n_opers, n_coeffs)),
dt)
total_pulse = testutil.rand_pulse_sequence(d, n_dt, 4, 6)
c_opers, c_coeffs = total_pulse.c_opers, total_pulse.c_coeffs
n_opers, n_coeffs = total_pulse.n_opers, total_pulse.n_coeffs
dt = total_pulse.dt

total_HD, total_HV, _ = diagonalize(
np.einsum('il,ijk->ljk', c_coeffs, c_opers), total_pulse.dt
Expand Down Expand Up @@ -603,9 +603,7 @@ def test_pulse_correlation_filter_function(self):

def test_calculate_error_vector_correlation_functions(self):
"""Test raises of numeric.error_transfer_matrix"""
pulse = ff.PulseSequence([[ff.util.P_np[1], [np.pi/2]]],
[[ff.util.P_np[1], [1]]],
[1])
pulse = testutil.rand_pulse_sequence(2, 1, 1, 1)

omega = randn(43)
# single spectrum
Expand All @@ -632,16 +630,8 @@ def test_infidelity_convergence(self):
def S(omega):
return omega**0

simple_pulse = ff.PulseSequence(
[[ff.util.P_qt[1], [np.pi/2]]],
[[ff.util.P_qt[1], [1]]],
[1]
)
complicated_pulse = ff.PulseSequence(
list(zip(ff.util.P_qt[1:], randn(3, 100))),
list(zip(ff.util.P_qt[1:], np.abs(randn(3, 100)))),
np.abs(randn(100))
)
simple_pulse = testutil.rand_pulse_sequence(2, 1, 1, 1)
complicated_pulse = testutil.rand_pulse_sequence(2, 100, 3, 3)

with self.assertRaises(TypeError):
n, infids, (fig, ax) = ff.infidelity(simple_pulse, S, [],
Expand All @@ -662,7 +652,8 @@ def S(omega):
test_convergence=True)

# Test with non-default args
identifiers = choice(['B_0', 'B_1', 'B_2'], randint(1, 4))
identifiers = choice(complicated_pulse.n_oper_identifiers,
randint(1, 4))

n, infids, (fig, ax) = ff.infidelity(complicated_pulse,
S, omega, test_convergence=True,
Expand Down
33 changes: 4 additions & 29 deletions tests/test_plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import numpy as np
import pytest
import qutip as qt
from numpy.random import randint, randn
from numpy.random import randint

import filter_functions as ff
from filter_functions.plotting import (get_bloch_vector, get_states_from_prop,
Expand All @@ -45,28 +45,9 @@
plot_pulse_train)
from tests import testutil

simple_pulse = ff.PulseSequence(
[[qt.sigmax(), [np.pi/2]]],
[[qt.sigmax(), [1]]],
[1],
basis=ff.Basis.pauli(1)
)
complicated_pulse = ff.PulseSequence(
list(zip(ff.util.P_qt[1:], randn(3, 100))),
list(zip(ff.util.P_qt[1:], np.abs(randn(3, 100)))),
np.abs(randn(100))
)
two_qubit_pulse = ff.PulseSequence(
[[qt.tensor(qt.sigmaz(), qt.qeye(2)), [np.pi/2]]],
[[qt.tensor(qt.sigmax(), qt.qeye(2)), [1]],
[qt.tensor(qt.sigmay(), qt.qeye(2)), [1]],
[qt.tensor(qt.sigmaz(), qt.qeye(2)), [1]],
[qt.tensor(qt.qeye(2), qt.sigmax()), [1]],
[qt.tensor(qt.qeye(2), qt.sigmay()), [1]],
[qt.tensor(qt.qeye(2), qt.sigmaz()), [1]]],
[1],
ff.Basis.pauli(2)
)
simple_pulse = testutil.rand_pulse_sequence(2, 1, 1, 1, btype='Pauli')
complicated_pulse = testutil.rand_pulse_sequence(2, 100, 3, 3)
two_qubit_pulse = testutil.rand_pulse_sequence(4, 1, 1, 6, btype='Pauli')


class PlottingTest(testutil.TestCase):
Expand All @@ -92,12 +73,6 @@ def test_get_states_from_prop(self):
self.assertArrayAlmostEqual(states_piecewise, states_total)

def test_plot_bloch_vector_evolution(self):
two_qubit_pulse = ff.PulseSequence(
[[qt.tensor(qt.sigmax(), qt.sigmax()), [np.pi/2]]],
[[qt.tensor(qt.sigmax(), qt.sigmax()), [1]]],
[1]
)

# Call with default args
b = plot_bloch_vector_evolution(simple_pulse)
# Call with custom args
Expand Down
80 changes: 31 additions & 49 deletions tests/test_precision.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,35 +290,30 @@ def test_infidelity(self):
]

ref_infids = (
[0.136323822128, 0.503088456605],
[0.203378761555, 0.518332209649],
[0.053296418553, 0.136876219234],
[0.136323822128, 0.518332209649],
[[0.203378761555, -0.055616969909 - 0.055616969909j],
[-0.055616969909 + 0.055616969909j, 0.518332209649]],
[3.546546324306, 2.647853348679],
[3.280981606059, 2.337134644933],
[0.762362817296, 0.579758833611],
[3.546546324306, 2.337134644933],
[[3.280981606059, -0.41174629763 - 0.41174629763j],
[-0.41174629763 + 0.41174629763j, 2.337134644933]],
[5.412527279325, 1.491940249915],
[3.036289753366, 1.227000243671],
[0.556478695119, 0.294389833858],
[5.412527279325, 1.227000243671],
[[3.036289753366, -0.090100013088-0.090100013088j],
[-0.090100013088+0.090100013088j, 1.227000243671]]
[0.448468950307, 0.941871479562],
[0.65826575772, 1.042914346335],
[0.163303005479, 0.239032549377],
[0.448468950307, 1.042914346335],
[[0.65826575772, 0.069510589685+0.069510589685j],
[0.069510589685-0.069510589685j, 1.042914346335]],
[3.687399348243, 3.034914820757],
[2.590545568435, 3.10093804628 ],
[0.55880380219, 0.782544974968],
[3.687399348243, 3.10093804628 ],
[[2.590545568435, -0.114514760108-0.114514760108j],
[-0.114514760108+0.114514760108j, 3.10093804628]],
[2.864567451344, 1.270260393902],
[1.847740998731, 1.559401345443],
[0.362116177417, 0.388022992097],
[2.864567451344, 1.559401345443],
[[1.847740998731, 0.088373663409+0.088373663409j],
[0.088373663409-0.088373663409j, 1.559401345443]]
)

count = 0
for d in (2, 3, 4):
c_opers = testutil.rand_herm(d, 2)
n_opers = testutil.rand_herm_traceless(d, 3)
pulse = ff.PulseSequence(
list(zip(c_opers, randn(2, 10))),
list(zip(n_opers, np.abs(randn(3, 10)))),
np.abs(randn(10))
)
pulse = testutil.rand_pulse_sequence(d, 10, 2, 3)
pulse.n_oper_identifiers = np.array(['B_0', 'B_2'])

omega = np.geomspace(0.1, 10, 51)
S0 = np.abs(randn())
Expand Down Expand Up @@ -390,14 +385,9 @@ def test_single_qubit_error_transfer_matrix(self):
"""Test the calculation of the single-qubit transfer matrix"""
d = 2
for n_dt in randint(1, 11, 10):
pulse = ff.PulseSequence(
list(zip(ff.util.P_np[1:], randn(3, n_dt))),
list(zip(ff.util.P_np[2:], np.abs(randn(3, n_dt)))),
np.abs(randn(n_dt)),
basis=ff.Basis.pauli(1)
)
pulse = testutil.rand_pulse_sequence(d, n_dt, 3, 2, btype='Pauli')
omega = ff.util.get_sample_frequencies(pulse, n_samples=51)
n_oper_identifiers = ['B_0', 'B_1']
n_oper_identifiers = pulse.n_oper_identifiers
traces = pulse.basis.four_element_traces.todense()

# Single spectrum
Expand Down Expand Up @@ -472,21 +462,13 @@ def test_single_qubit_error_transfer_matrix(self):

def test_multi_qubit_error_transfer_matrix(self):
"""Test the calculation of the multi-qubit transfer matrix"""
for d, n_dt in zip(randint(3, 13, 10), randint(1, 11, 10)):
n_cops = 4
n_nops = 2
for d, n_dt in zip(randint(3, 9, 10), randint(1, 11, 10)):
f, n = np.modf(np.log2(d))
if f == 0.0:
basis = ff.Basis.pauli(int(n))
else:
basis = ff.Basis.ggm(d)

c_opers = testutil.rand_herm(d, randint(2, 4))
n_opers = testutil.rand_herm_traceless(d, randint(2, 4))
pulse = ff.PulseSequence(
list(zip(c_opers, randn(len(c_opers), n_dt))),
list(zip(n_opers, np.abs(randn(len(n_opers), n_dt)))),
np.abs(randn(n_dt)),
basis
)
btype = 'Pauli' if f == 0.0 else 'GGM'
pulse = testutil.rand_pulse_sequence(d, n_dt, n_cops, n_nops,
btype)
omega = ff.util.get_sample_frequencies(pulse, n_samples=51)

# Assert fidelity is same as computed by infidelity()
Expand All @@ -500,7 +482,7 @@ def test_multi_qubit_error_transfer_matrix(self):
I_transfer = np.einsum('...ii', U)/d**2
self.assertArrayAlmostEqual(I_transfer, I_fidelity)

S = np.outer(1e-2*(np.arange(len(n_opers)) + 1),
S = np.outer(1e-2*(np.arange(n_nops) + 1),
400/(omega**2 + 400))
U = ff.error_transfer_matrix(pulse, S, omega)
# Calculate U in loop
Expand All @@ -512,8 +494,8 @@ def test_multi_qubit_error_transfer_matrix(self):
self.assertArrayAlmostEqual(I_transfer, I_fidelity)

S = np.einsum('i,j,o->ijo',
1e-2*(np.arange(len(n_opers)) + 1),
1e-2*(np.arange(len(n_opers)) + 1),
1e-2*(np.arange(n_nops) + 1),
1e-2*(np.arange(n_nops) + 1),
400/(omega**2 + 400))
U = ff.error_transfer_matrix(pulse, S, omega)
# Calculate U in loop
Expand Down
Loading

0 comments on commit 6433fed

Please sign in to comment.