From 26949c5756b034ac8649a6df9e4338521675b726 Mon Sep 17 00:00:00 2001 From: Tobias Hangleiter Date: Sun, 3 May 2020 17:50:34 +0200 Subject: [PATCH] Switch tests to new numpy.random API --- tests/test_basis.py | 45 +++++++-------- tests/test_core.py | 72 ++++++++++++------------ tests/test_plotting.py | 15 +++-- tests/test_precision.py | 21 +++---- tests/test_sequencing.py | 45 ++++++++------- tests/test_util.py | 115 +++++++++++++++++++++------------------ tests/testutil.py | 18 +++--- 7 files changed, 176 insertions(+), 155 deletions(-) diff --git a/tests/test_basis.py b/tests/test_basis.py index 7e2e228..e8b64c6 100644 --- a/tests/test_basis.py +++ b/tests/test_basis.py @@ -51,7 +51,7 @@ def test_basis_constructor(self): # Too many elements with self.assertRaises(ValueError): - _ = ff.Basis(np.random.randn(5, 2, 2)) + _ = ff.Basis(testutil.rng.randn(5, 2, 2)) # Properly normalized self.assertEqual(ff.Basis.pauli(1), ff.Basis(ff.util.P_np)) @@ -70,8 +70,8 @@ def test_basis_constructor(self): def test_basis_properties(self): """Basis orthonormal and of correct dimensions""" - d = np.random.randint(2, 17) - n = np.random.randint(1, 5) + d = testutil.rng.randint(2, 17) + n = testutil.rng.randint(1, 5) ggm_basis = ff.Basis.ggm(d) pauli_basis = ff.Basis.pauli(n) @@ -87,11 +87,12 @@ def test_basis_properties(self): if not btype == 'Pauli': self.assertEqual(d, base.d) # Check if __contains__ works as expected - self.assertTrue(base[np.random.randint(0, d**2)] in base) + self.assertTrue(base[testutil.rng.randint(0, d**2)] in base) else: self.assertEqual(2**n, base.d) # Check if __contains__ works as expected - self.assertTrue(base[np.random.randint(0, (2**n)**2)] in base) + self.assertTrue(base[testutil.rng.randint(0, (2**n)**2)] + in base) # Check if all elements of each basis are orthonormal and hermitian self.assertArrayEqual(base.T, base.view(np.ndarray).swapaxes(-1, -2)) @@ -129,13 +130,13 @@ def test_basis_properties(self): def test_basis_expansion_and_normalization(self): """Correct expansion of operators and normalization of bases""" for _ in range(10): - d = np.random.randint(2, 16) + d = testutil.rng.randint(2, 16) ggm_basis = ff.Basis.ggm(d) basis = ff.Basis( - np.einsum('i,ijk->ijk', np.random.randn(d**2), ggm_basis), + np.einsum('i,ijk->ijk', testutil.rng.randn(d**2), ggm_basis), skip_check=True ) - M = np.random.randn(d, d) + 1j*np.random.randn(d, d) + M = testutil.rng.randn(d, d) + 1j*testutil.rng.randn(d, d) M -= np.trace(M)/d coeffs = ff.basis.expand(M, basis, normalized=False) self.assertArrayAlmostEqual(M, np.einsum('i,ijk', coeffs, basis)) @@ -146,8 +147,8 @@ def test_basis_expansion_and_normalization(self): ff.basis.ggm_expand(M, traceless=True), atol=1e-14) - n = np.random.randint(1, 50) - M = np.random.randn(n, d, d) + 1j*np.random.randn(n, d, d) + n = testutil.rng.randint(1, 50) + M = testutil.rng.randn(n, d, d) + 1j*testutil.rng.randn(n, d, d) coeffs = ff.basis.expand(M, basis, normalized=False) self.assertArrayAlmostEqual(M, np.einsum('li,ijk->ljk', coeffs, basis)) @@ -180,11 +181,11 @@ def test_basis_generation_from_partial_ggm(self): # Do 100 test runs with random elements from a GGM basis in (2 ... 8) # dimensions for _ in range(50): - d = np.random.randint(2, 9) + d = testutil.rng.randint(2, 9) b = ff.Basis.ggm(d) inds = [i for i in range(d**2)] - tup = tuple(inds.pop(np.random.randint(0, len(inds))) - for _ in range(np.random.randint(1, d**2))) + tup = tuple(inds.pop(testutil.rng.randint(0, len(inds))) + for _ in range(testutil.rng.randint(1, d**2))) elems = b[tup, ...] basis = ff.Basis(elems) self.assertTrue(basis.isorthonorm) @@ -198,12 +199,12 @@ def test_basis_generation_from_partial_pauli(self): # Do 100 test runs with random elements from a Pauli basis in (2 ... 8) # dimensions for _ in range(50): - n = np.random.randint(1, 4) + n = testutil.rng.randint(1, 4) d = 2**n b = ff.Basis.pauli(n) inds = [i for i in range(d**2)] - tup = tuple(inds.pop(np.random.randint(0, len(inds))) - for _ in range(np.random.randint(1, d**2))) + tup = tuple(inds.pop(testutil.rng.randint(0, len(inds))) + for _ in range(testutil.rng.randint(1, d**2))) elems = b[tup, ...] basis = ff.Basis(elems) self.assertTrue(basis.isorthonorm) @@ -225,7 +226,7 @@ def test_basis_generation_from_partial_random(self): # Do 25 test runs with random elements from a random basis in # (2 ... 8) dimensions for _ in range(25): - d = np.random.randint(2, 7) + d = testutil.rng.randint(2, 7) # Get a random traceless hermitian operator oper = testutil.rand_herm_traceless(d) # ... and build a basis from it @@ -237,8 +238,8 @@ def test_basis_generation_from_partial_random(self): # Choose random elements from that basis and generate a new basis # from it inds = [i for i in range(d**2)] - tup = tuple(inds.pop(np.random.randint(0, len(inds))) - for _ in range(np.random.randint(1, d**2))) + tup = tuple(inds.pop(testutil.rng.randint(0, len(inds))) + for _ in range(testutil.rng.randint(1, d**2))) elems = b[tup, ...] basis = ff.Basis(elems) self.assertTrue(basis.isorthonorm) @@ -249,7 +250,7 @@ def test_basis_generation_from_partial_random(self): # Test runs with non-traceless opers for _ in range(25): - d = np.random.randint(2, 7) + d = testutil.rng.randint(2, 7) # Get a random hermitian operator oper = testutil.rand_herm(d) # ... and build a basis from it @@ -261,8 +262,8 @@ def test_basis_generation_from_partial_random(self): # Choose random elements from that basis and generate a new basis # from it inds = [i for i in range(d**2)] - tup = tuple(inds.pop(np.random.randint(0, len(inds))) - for _ in range(np.random.randint(1, d**2))) + tup = tuple(inds.pop(testutil.rng.randint(0, len(inds))) + for _ in range(testutil.rng.randint(1, d**2))) elems = b[tup, ...] basis = ff.Basis(elems) self.assertTrue(basis.isorthonorm) diff --git a/tests/test_core.py b/tests/test_core.py index 584e279..a58b33c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -26,7 +26,6 @@ from random import sample import numpy as np -from numpy.random import choice, randint, randn import filter_functions as ff from filter_functions.numeric import ( @@ -61,7 +60,7 @@ def test_pulse_sequence_constructor(self): # dt not a sequence ff.PulseSequence(H_c, H_n, dt[0]) - idx = randint(0, 5) + idx = testutil.rng.randint(0, 5) with self.assertRaises(ValueError): # negative dt dt[idx] *= -1 @@ -92,7 +91,7 @@ def test_pulse_sequence_constructor(self): # Noise Hamiltonian not list or tuple ff.PulseSequence(H_c, np.array(H_n), dt) - idx = randint(0, 3) + idx = testutil.rng.randint(0, 3) with self.assertRaises(TypeError): # Control Hamiltonian element not list or tuple H_c[idx] = dict(H_c[idx]) @@ -231,19 +230,19 @@ def test_pulse_sequence_constructor(self): def test_pulse_sequence_attributes(self): """Test attributes of single instance""" X, Y, Z = ff.util.P_np[1:] - n_dt = randint(1, 10) + n_dt = testutil.rng.randint(1, 10) # trivial case - A = ff.PulseSequence([[X, randn(n_dt), 'X']], - [[Z, randn(n_dt), 'Z']], - np.abs(randn(n_dt))) + A = ff.PulseSequence([[X, testutil.rng.randn(n_dt), 'X']], + [[Z, testutil.rng.randn(n_dt), 'Z']], + np.abs(testutil.rng.randn(n_dt))) self.assertFalse(A == 1) self.assertTrue(A != 1) # different number of time steps - B = ff.PulseSequence([[X, randn(n_dt+1), 'X']], - [[Z, randn(n_dt+1), 'Z']], - np.abs(randn(n_dt+1))) + B = ff.PulseSequence([[X, testutil.rng.randn(n_dt+1), 'X']], + [[Z, testutil.rng.randn(n_dt+1), 'Z']], + np.abs(testutil.rng.randn(n_dt+1))) self.assertFalse(A == B) self.assertTrue(A != B) @@ -251,7 +250,7 @@ def test_pulse_sequence_attributes(self): B = ff.PulseSequence( list(zip(A.c_opers, A.c_coeffs, A.c_oper_identifiers)), list(zip(A.n_opers, A.n_coeffs, A.n_oper_identifiers)), - np.abs(randn(n_dt)) + np.abs(testutil.rng.randn(n_dt)) ) self.assertFalse(A == B) self.assertTrue(A != B) @@ -267,7 +266,8 @@ def test_pulse_sequence_attributes(self): # different control coeffs B = ff.PulseSequence( - list(zip(A.c_opers, [randn(n_dt)], A.c_oper_identifiers)), + list(zip(A.c_opers, [testutil.rng.randn(n_dt)], + A.c_oper_identifiers)), list(zip(A.n_opers, A.n_coeffs, A.n_oper_identifiers)), A.dt ) @@ -286,7 +286,8 @@ def test_pulse_sequence_attributes(self): # different noise coeffs B = ff.PulseSequence( list(zip(A.c_opers, A.c_coeffs, A.c_oper_identifiers)), - list(zip(A.n_opers, [randn(n_dt)], A.n_oper_identifiers)), + list(zip(A.n_opers, [testutil.rng.randn(n_dt)], + A.n_oper_identifiers)), A.dt ) self.assertFalse(A == B) @@ -364,30 +365,30 @@ def test_pulse_sequence_attributes(self): def test_pulse_sequence_attributes_concat(self): """Test attributes of concatenated sequence.""" X, Y, Z = ff.util.P_np[1:] - n_dt_1 = randint(5, 11) - x_coeff_1 = randn(n_dt_1) - z_coeff_1 = randn(n_dt_1) - dt_1 = np.abs(randn(n_dt_1)) - n_dt_2 = randint(5, 11) - y_coeff_2 = randn(n_dt_2) - z_coeff_2 = randn(n_dt_2) - dt_2 = np.abs(randn(n_dt_2)) + n_dt_1 = testutil.rng.randint(5, 11) + x_coeff_1 = testutil.rng.randn(n_dt_1) + z_coeff_1 = testutil.rng.randn(n_dt_1) + dt_1 = np.abs(testutil.rng.randn(n_dt_1)) + n_dt_2 = testutil.rng.randint(5, 11) + y_coeff_2 = testutil.rng.randn(n_dt_2) + z_coeff_2 = testutil.rng.randn(n_dt_2) + dt_2 = np.abs(testutil.rng.randn(n_dt_2)) pulse_1 = ff.PulseSequence([[X, x_coeff_1]], [[Z, z_coeff_1]], dt_1) pulse_2 = ff.PulseSequence([[Y, y_coeff_2]], [[Z, z_coeff_2]], dt_2) - pulse_3 = ff.PulseSequence([[Y, randn(2)], - [X, randn(2)]], - [[Z, np.abs(randn(2))]], + pulse_3 = ff.PulseSequence([[Y, testutil.rng.randn(2)], + [X, testutil.rng.randn(2)]], + [[Z, np.abs(testutil.rng.randn(2))]], [1, 1]) pulse_12 = pulse_1 @ pulse_2 pulse_21 = pulse_2 @ pulse_1 with self.assertRaises(TypeError): - _ = pulse_1 @ randn(2, 2) + _ = pulse_1 @ testutil.rng.randn(2, 2) # Concatenate pulses with same operators but different labels with self.assertRaises(ValueError): @@ -437,13 +438,13 @@ 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), - replace=False) + letters = testutil.rng.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( - list(zip([X, Y, Z], np.random.randn(3, 2), ids, labels)), - list(zip([X, Y, Z], np.random.randn(3, 2), ids, labels)), + list(zip([X, Y, Z], testutil.rng.randn(3, 2), ids, labels)), + list(zip([X, Y, Z], testutil.rng.randn(3, 2), ids, labels)), [1, 1] ) @@ -452,7 +453,8 @@ 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,))): + for d, n_dt in zip(testutil.rng.randint(2, 10, (3,)), + testutil.rng.randint(10, 200, (3,))): 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 @@ -574,7 +576,7 @@ def test_pulse_correlation_filter_function(self): infid_1 = ff.infidelity(pulse_1, S, omega, which='foobar') for _ in range(10): - n_nops = randint(1, 4) + n_nops = testutil.rng.randint(1, 4) identifiers = sample(['B_0', 'B_1', 'B_2'], n_nops) infid_X = ff.infidelity(pulses['X'], S, omega, which='total', @@ -605,9 +607,9 @@ def test_calculate_error_vector_correlation_functions(self): """Test raises of numeric.error_transfer_matrix""" pulse = testutil.rand_pulse_sequence(2, 1, 1, 1) - omega = randn(43) + omega = testutil.rng.randn(43) # single spectrum - S = randn(78) + S = testutil.rng.randn(78) for i in range(4): with self.assertRaises(ValueError): calculate_error_vector_correlation_functions( @@ -652,8 +654,8 @@ def S(omega): test_convergence=True) # Test with non-default args - identifiers = choice(complicated_pulse.n_oper_identifiers, - randint(1, 4)) + identifiers = testutil.rng.choice(complicated_pulse.n_oper_identifiers, + testutil.rng.randint(1, 4)) n, infids, (fig, ax) = ff.infidelity(complicated_pulse, S, omega, test_convergence=True, diff --git a/tests/test_plotting.py b/tests/test_plotting.py index f961ea7..acd0a6c 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -33,7 +33,6 @@ import numpy as np import pytest import qutip as qt -from numpy.random import randint import filter_functions as ff from filter_functions.plotting import (get_bloch_vector, get_states_from_prop, @@ -102,7 +101,8 @@ def test_plot_pulse_train(self): # Call with custom args c_oper_identifiers = sample( - complicated_pulse.c_oper_identifiers.tolist(), randint(2, 4) + complicated_pulse.c_oper_identifiers.tolist(), + testutil.rng.randint(2, 4) ) fig, ax = plt.subplots() @@ -142,7 +142,8 @@ def test_plot_filter_function(self): # Non-default args n_oper_identifiers = sample( - complicated_pulse.n_oper_identifiers.tolist(), randint(2, 4) + complicated_pulse.n_oper_identifiers.tolist(), + testutil.rng.randint(2, 4) ) fig, ax = plt.subplots() @@ -205,7 +206,8 @@ def test_plot_pulse_correlation_filter_function(self): # Non-default args n_oper_identifiers = sample( - complicated_pulse.n_oper_identifiers.tolist(), randint(2, 4) + complicated_pulse.n_oper_identifiers.tolist(), + testutil.rng.randint(2, 4) ) fig, ax = plt.subplots() @@ -274,12 +276,13 @@ def test_plot_error_transfer_matrix(self): # Non-default args n_oper_inds = sample(range(len(complicated_pulse.n_opers)), - randint(2, 4)) + testutil.rng.randint(2, 4)) n_oper_identifiers = complicated_pulse.n_oper_identifiers[n_oper_inds] basis_labels = [] for i in range(4): - basis_labels.append(string.ascii_uppercase[randint(0, 26)]) + basis_labels.append( + string.ascii_uppercase[testutil.rng.randint(0, 26)]) omega = ff.util.get_sample_frequencies(complicated_pulse, n_samples=50, spacing='log') diff --git a/tests/test_precision.py b/tests/test_precision.py index 615e22a..118c31c 100644 --- a/tests/test_precision.py +++ b/tests/test_precision.py @@ -24,7 +24,6 @@ import numpy as np import qutip as qt -from numpy.random import randint, randn import filter_functions as ff from filter_functions import analytic @@ -37,7 +36,7 @@ class PrecisionTest(testutil.TestCase): def test_FID(self): """FID""" - tau = abs(randn()) + tau = abs(testutil.rng.randn()) FID_pulse = ff.PulseSequence([[ff.util.P_np[1]/2, [0]]], [[ff.util.P_np[3]/2, [1]]], [tau]) @@ -68,7 +67,7 @@ def test_SE(self): # Test again with a factor of one between the noise operators and # coefficients - r = randn() + r = testutil.rng.randn() H_n = [[ff.util.P_np[3]/2*r, np.ones_like(dt)/r]] SE_pulse = ff.PulseSequence(H_c, H_n, dt) @@ -274,7 +273,7 @@ def test_infidelity_cnot(self): def test_infidelity(self): """Benchmark infidelity results against previous version's results""" - np.random.seed(123456789) + testutil.rng.seed(123456789) spectra = [ lambda S0, omega: S0*omega**0, @@ -297,9 +296,9 @@ def test_infidelity(self): [[0.65826575772, 0.069510589685+0.069510589685j], [0.069510589685-0.069510589685j, 1.042914346335]], [3.687399348243, 3.034914820757], - [2.590545568435, 3.10093804628 ], + [2.590545568435, 3.10093804628], [0.55880380219, 0.782544974968], - [3.687399348243, 3.10093804628 ], + [3.687399348243, 3.10093804628], [[2.590545568435, -0.114514760108-0.114514760108j], [-0.114514760108+0.114514760108j, 3.10093804628]], [2.864567451344, 1.270260393902], @@ -316,7 +315,7 @@ def test_infidelity(self): pulse.n_oper_identifiers = np.array(['B_0', 'B_2']) omega = np.geomspace(0.1, 10, 51) - S0 = np.abs(randn()) + S0 = np.abs(testutil.rng.randn()) for spec in spectra: S, omega_t = ff.util.symmetrize_spectrum(spec(S0, omega), omega) @@ -373,7 +372,8 @@ def test_infidelity(self): with self.assertRaises(ValueError): # S wrong dimensions - ff.infidelity(pulse, np.random.randn(2, 3, 4, len(omega)), omega) + ff.infidelity(pulse, testutil.rng.randn(2, 3, 4, len(omega)), + omega) with self.assertRaises(NotImplementedError): # smallness parameter for correlated noise source @@ -384,7 +384,7 @@ def test_infidelity(self): 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): + for n_dt in testutil.rng.randint(1, 11, 10): 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 = pulse.n_oper_identifiers @@ -464,7 +464,8 @@ def test_multi_qubit_error_transfer_matrix(self): """Test the calculation of the multi-qubit transfer matrix""" n_cops = 4 n_nops = 2 - for d, n_dt in zip(randint(3, 9, 10), randint(1, 11, 10)): + for d, n_dt in zip(testutil.rng.randint(3, 9, 10), + testutil.rng.randint(1, 11, 10)): f, n = np.modf(np.log2(d)) btype = 'Pauli' if f == 0.0 else 'GGM' pulse = testutil.rand_pulse_sequence(d, n_dt, n_cops, n_nops, diff --git a/tests/test_sequencing.py b/tests/test_sequencing.py index b2d478a..a35b02c 100644 --- a/tests/test_sequencing.py +++ b/tests/test_sequencing.py @@ -27,7 +27,6 @@ from random import sample import numpy as np -from numpy.random import choice, randint, randn import filter_functions as ff from filter_functions.util import P_np, get_sample_frequencies, tensor @@ -219,7 +218,7 @@ def test_concatenate_4_spin_echos(self): H_n_CPMG = [[P_np[3], np.ones_like(dt_CPMG)]] CPMG = ff.PulseSequence(H_c_CPMG, H_n_CPMG, dt_CPMG) - SE[randint(0, len(SE)-1)].cache_filter_function(omega) + SE[testutil.rng.randint(0, len(SE)-1)].cache_filter_function(omega) CPMG.cache_filter_function(omega) CPMG_concat_1 = ff.concatenate(SE) @@ -227,7 +226,7 @@ def test_concatenate_4_spin_echos(self): for se in SE: se.cleanup('all') - SE[randint(0, len(SE)-1)].cache_filter_function(omega) + SE[testutil.rng.randint(0, len(SE)-1)].cache_filter_function(omega) CPMG_concat_2 = SE[0] @ SE[1] @ SE[2] @ SE[3] self.assertEqual(CPMG, CPMG_concat_1) @@ -314,40 +313,43 @@ def test_concatenate_split_cnot(self): def test_different_n_opers(self): """Test behavior when concatenating with different n_opers""" - for d, n_dt in zip(randint(2, 5, 20), randint(1, 11, 20)): + for d, n_dt in zip(testutil.rng.randint(2, 5, 20), + testutil.rng.randint(1, 11, 20)): opers = testutil.rand_herm_traceless(d, 10) letters = np.array(sample(list(string.ascii_letters), 10)) - n_idx = sample(range(10), randint(2, 5)) - c_idx = sample(range(10), randint(2, 5)) + n_idx = sample(range(10), testutil.rng.randint(2, 5)) + c_idx = sample(range(10), testutil.rng.randint(2, 5)) n_opers = opers[n_idx] c_opers = opers[c_idx] n_coeffs = np.ones((n_opers.shape[0], n_dt)) - n_coeffs *= np.abs(randn(n_opers.shape[0], 1)) - c_coeffs = randn(c_opers.shape[0], n_dt) - dt = np.abs(randn(n_dt)) + n_coeffs *= np.abs(testutil.rng.randn(n_opers.shape[0], 1)) + c_coeffs = testutil.rng.randn(c_opers.shape[0], n_dt) + dt = np.abs(testutil.rng.randn(n_dt)) n_ids = np.array([''.join(l) for l in letters[n_idx]]) c_ids = np.array([''.join(l) for l in letters[c_idx]]) pulse_1 = ff.PulseSequence(list(zip(c_opers, c_coeffs, c_ids)), list(zip(n_opers, n_coeffs, n_ids)), dt) - permutation = np.random.permutation(range(n_opers.shape[0])) + permutation = testutil.rng.permutation(range(n_opers.shape[0])) pulse_2 = ff.PulseSequence(list(zip(c_opers, c_coeffs, c_ids)), list(zip(n_opers[permutation], n_coeffs[permutation], n_ids[permutation])), dt) - more_n_idx = sample(range(10), randint(2, 5)) + more_n_idx = sample(range(10), testutil.rng.randint(2, 5)) more_n_opers = opers[more_n_idx] more_n_coeffs = np.ones((more_n_opers.shape[0], n_dt)) - more_n_coeffs *= np.abs(randn(more_n_opers.shape[0], 1)) + more_n_coeffs *= np.abs(testutil.rng.randn( + more_n_opers.shape[0], 1)) more_n_ids = np.array([''.join(l) for l in letters[more_n_idx]]) pulse_3 = ff.PulseSequence(list(zip(c_opers, c_coeffs, c_ids)), list(zip(more_n_opers, more_n_coeffs, more_n_ids)), dt) - nontrivial_n_coeffs = np.abs(randn(n_opers.shape[0], n_dt)) + nontrivial_n_coeffs = np.abs(testutil.rng.randn( + n_opers.shape[0], n_dt)) pulse_4 = ff.PulseSequence(list(zip(c_opers, c_coeffs, c_ids)), list(zip(more_n_opers, nontrivial_n_coeffs, @@ -466,7 +468,7 @@ def test_extend_with_identity(self): """Test extending a pulse to more qubits""" ID, X, Y, Z = P_np n_dt = 10 - coeffs = randn(3, n_dt) + coeffs = testutil.rng.randn(3, n_dt) ids = ['X', 'Y', 'Z'] pulse = ff.PulseSequence( list(zip((X, Y, Z), coeffs, ids)), @@ -475,8 +477,8 @@ def test_extend_with_identity(self): ) omega = get_sample_frequencies(pulse, spacing='log', n_samples=50) - for N in randint(2, 5, 4): - for target in randint(0, N-1, 2): + for N in testutil.rng.randint(2, 5, 4): + for target in testutil.rng.randint(0, N-1, 2): pulse.cleanup('all') ext_opers = tensor(*np.insert(np.tile(ID, (N-1, 3, 1, 1)), target, (X, Y, Z), axis=0)) @@ -491,7 +493,8 @@ def test_extend_with_identity(self): ) # Use custom mapping for identifiers and or labels - letters = choice(list(string.ascii_letters), size=(3, 5)) + letters = testutil.rng.choice(list(string.ascii_letters), + size=(3, 5)) mapped_ids = np.array([''.join(l) for l in letters]) mapping = {i: new_id for i, new_id in zip(ids, mapped_ids)} ext_pulse_mapped_identifiers = ff.PulseSequence( @@ -512,7 +515,7 @@ def test_extend_with_identity(self): np.ones(n_dt), basis=ff.Basis.pauli(N) ) - calc_FF = randint(0, 2) + calc_FF = testutil.rng.randint(0, 2) if calc_FF: # Expect things to be cached in extended pulse if original # also was cached @@ -692,7 +695,7 @@ def test_accuracy(self): XXX = tensor(X, X, X) n_dt = 10 - coeffs = np.random.randn(3, n_dt) + coeffs = testutil.rng.randn(3, n_dt) X_pulse = ff.PulseSequence( [[X, coeffs[0], 'X']], list(zip((X, Y, Z), np.ones((3, n_dt)), ('X', 'Y', 'Z'))), @@ -995,7 +998,7 @@ def test_caching(self): def test_accuracy(self): paulis = np.array(P_np) I, X, Y, Z = paulis - amps = randn(randint(1, 11)) + amps = testutil.rng.randn(testutil.rng.randint(1, 11)) pulse = ff.PulseSequence( [[tensor(X, Y, Z), amps]], [[tensor(X, I, I), np.ones_like(amps), 'XII'], @@ -1008,7 +1011,7 @@ def test_accuracy(self): pulse.cache_filter_function(omega) for _ in range(100): - order = np.random.permutation(range(3)) + order = testutil.rng.permutation(range(3)) reordered_pulse = ff.PulseSequence( [[tensor(*paulis[1:][order]), amps]], [[tensor(*paulis[[1, 0, 0]][order]), np.ones_like(amps), diff --git a/tests/test_util.py b/tests/test_util.py index ac77393..1001dab 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -23,7 +23,6 @@ """ import numpy as np import qutip as qt -from numpy.random import randint, randn, random from filter_functions import PulseSequence, util from tests import testutil @@ -32,12 +31,12 @@ class UtilTest(testutil.TestCase): def test_abs2(self): - x = randn(20, 100) + 1j*randn(20, 100) + x = testutil.rng.randn(20, 100) + 1j*testutil.rng.randn(20, 100) self.assertArrayAlmostEqual(np.abs(x)**2, util.abs2(x)) def test_cexp(self): """Fast complex exponential.""" - x = randn(50, 100) + x = testutil.rng.randn(50, 100) a = util.cexp(x) b = np.exp(1j*x) self.assertArrayAlmostEqual(a, b) @@ -70,14 +69,14 @@ def test_get_indices_from_identifiers(self): def test_tensor(self): shapes = [(1, 2, 3, 4, 5), (5, 4, 3, 2, 1)] - A = randn(*shapes[0]) - B = randn(*shapes[1]) + A = testutil.rng.randn(*shapes[0]) + B = testutil.rng.randn(*shapes[1]) with self.assertRaises(ValueError): util.tensor(A, B) shapes = [(3, 2, 1), (3, 4, 2)] - A = randn(*shapes[0]) - B = randn(*shapes[1]) + A = testutil.rng.randn(*shapes[0]) + B = testutil.rng.randn(*shapes[1]) with self.assertRaises(ValueError): util.tensor(A, B, rank=1) @@ -85,32 +84,33 @@ def test_tensor(self): self.assertEqual(util.tensor(A, B, rank=3).shape, (9, 8, 2)) shapes = [(10, 1, 3, 2), (10, 1, 2, 3)] - A = randn(*shapes[0]) - B = randn(*shapes[1]) + A = testutil.rng.randn(*shapes[0]) + B = testutil.rng.randn(*shapes[1]) self.assertEqual(util.tensor(A, B).shape, (10, 1, 6, 6)) shapes = [(3, 5, 4, 4), (3, 5, 4, 4)] - A = randn(*shapes[0]) - B = randn(*shapes[1]) + A = testutil.rng.randn(*shapes[0]) + B = testutil.rng.randn(*shapes[1]) self.assertEqual(util.tensor(A, B).shape, (3, 5, 16, 16)) - d = randint(2, 9) + d = testutil.rng.randint(2, 9) eye = np.eye(d) for i in range(d): for j in range(d): A, B = eye[i:i+1, :], eye[:, j:j+1] self.assertArrayEqual(util.tensor(A, B, rank=1), np.kron(A, B)) - i, j = randint(0, 4, (2,)) + i, j = testutil.rng.randint(0, 4, (2,)) A, B = util.P_np[i], util.P_np[j] self.assertArrayEqual(util.tensor(A, B), np.kron(A, B)) - args = [randn(4, 1, 2), randn(3, 2), randn(4, 3, 5)] + args = [testutil.rng.randn(4, 1, 2), testutil.rng.randn(3, 2), + testutil.rng.randn(4, 3, 5)] self.assertEqual(util.tensor(*args, rank=1).shape, (4, 3, 20)) self.assertEqual(util.tensor(*args, rank=2).shape, (4, 9, 20)) self.assertEqual(util.tensor(*args, rank=3).shape, (16, 9, 20)) - args = [randn(2, 3, 4), randn(4, 3)] + args = [testutil.rng.randn(2, 3, 4), testutil.rng.randn(4, 3)] with self.assertRaises(ValueError) as err: util.tensor(*args, rank=1) @@ -147,7 +147,9 @@ def test_tensor_insert(self): self.assertEqual(msg, str(err.exception)) # Test broadcasting and rank != 2 - A, B, C = randn(2, 3, 1, 2), randn(2, 3, 1, 2), randn(3, 1, 3) + A, B, C = (testutil.rng.randn(2, 3, 1, 2), + testutil.rng.randn(2, 3, 1, 2), + testutil.rng.randn(3, 1, 3)) arr = util.tensor(A, C, rank=1) r = util.tensor_insert(arr, B, pos=1, rank=1, @@ -163,7 +165,9 @@ def test_tensor_insert(self): util.tensor_insert(arr, B, pos=1, rank=1, arr_dims=[[2], [2, 1]]) - A, B, C = randn(2, 3, 1, 2), randn(2, 3, 2, 2), randn(3, 2, 1) + A, B, C = (testutil.rng.randn(2, 3, 1, 2), + testutil.rng.randn(2, 3, 2, 2), + testutil.rng.randn(3, 2, 1)) arr = util.tensor(A, C, rank=3) r = util.tensor_insert(arr, B, pos=1, rank=3, arr_dims=[[3, 3], [1, 2], [2, 1]]) @@ -178,13 +182,15 @@ def test_tensor_insert(self): util.tensor_insert(arr, B, pos=1, rank=2, arr_dims=[[3, 3, 1], [1, 2], [2]]) - A, B, C = randn(2, 1), randn(1, 2, 3), randn(1) + A, B, C = (testutil.rng.randn(2, 1), + testutil.rng.randn(1, 2, 3), + testutil.rng.randn(1)) arr = util.tensor(A, C, rank=1) r = util.tensor_insert(arr, B, pos=0, rank=1, arr_dims=[[1, 1]]) self.assertArrayAlmostEqual(r, util.tensor(A, B, C, rank=1)) - arrs, args = randn(2, 2, 2), randn(2, 2, 2) + arrs, args = testutil.rng.randn(2, 2, 2), testutil.rng.randn(2, 2, 2) arr_dims = [[2, 2], [2, 2]] r = util.tensor_insert(util.tensor(*arrs), *args, pos=(0, 1), @@ -209,7 +215,8 @@ def test_tensor_insert(self): arr_dims=arr_dims) # Test exception for wrong shapes - arrs, args = randn(2, 4, 3, 2), randn(2, 2, 3, 4) + arrs, args = (testutil.rng.randn(2, 4, 3, 2), + testutil.rng.randn(2, 2, 3, 4)) with self.assertRaises(ValueError) as err: util.tensor_insert(util.tensor(*arrs), *args, pos=(1, 2), arr_dims=[[3, 3], [2, 2]]) @@ -223,12 +230,12 @@ def test_tensor_insert(self): self.assertEqual(cause_msg, str(err.exception.__cause__)) # Do some random tests - for rank, n_args, n_broadcast in zip(randint(1, 4, 10), - randint(3, 6, 10), - randint(1, 11, 10)): - arrs = randn(n_args, n_broadcast, *[2]*rank) - split_idx = randint(1, n_args-1) - ins_idx = randint(split_idx-n_args, n_args-split_idx) + for rank, n_args, n_broadcast in zip(testutil.rng.randint(1, 4, 10), + testutil.rng.randint(3, 6, 10), + testutil.rng.randint(1, 11, 10)): + arrs = testutil.rng.randn(n_args, n_broadcast, *[2]*rank) + split_idx = testutil.rng.randint(1, n_args-1) + ins_idx = testutil.rng.randint(split_idx-n_args, n_args-split_idx) ins_arrs = arrs[:split_idx] arr = util.tensor(*arrs[split_idx:], rank=rank) sorted_arrs = np.insert(arrs[split_idx:], ins_idx, ins_arrs, @@ -240,7 +247,7 @@ def test_tensor_insert(self): self.assertArrayAlmostEqual( r, util.tensor(*sorted_arrs, rank=rank)) - pos = randint(-split_idx+1, split_idx, split_idx) + pos = testutil.rng.randint(-split_idx+1, split_idx, split_idx) r = util.tensor_insert(arr, *ins_arrs, pos=pos, rank=rank, arr_dims=arr_dims) sorted_arrs = np.insert(arrs[split_idx:], pos, ins_arrs, axis=0) @@ -316,7 +323,8 @@ def test_tensor_merge(self): ins_dims=[[2, 3], [2, 2]]) # Incompatible shapes - arrs, args = randn(2, 4, 3, 2), randn(2, 2, 3, 4) + arrs, args = (testutil.rng.randn(2, 4, 3, 2), + testutil.rng.randn(2, 2, 3, 4)) with self.assertRaises(ValueError) as err: util.tensor_merge(util.tensor(*arrs), util.tensor(*args), pos=(1, 2), arr_dims=[[3, 3], [2, 2]], @@ -328,8 +336,8 @@ def test_tensor_merge(self): self.assertEqual(msg, str(err.exception)) # Test rank 1 and broadcasting - arr = np.random.randn(2, 10, 3, 4) - ins = np.random.randn(2, 10, 3, 2) + arr = testutil.rng.randn(2, 10, 3, 4) + ins = testutil.rng.randn(2, 10, 3, 2) r = util.tensor_merge(util.tensor(*arr, rank=1), util.tensor(*ins, rank=1), pos=[0, 1], arr_dims=[[4, 4]], ins_dims=[[2, 2]], rank=1) @@ -338,14 +346,14 @@ def test_tensor_merge(self): ) # Do some random tests - for rank, n_args, n_broadcast in zip(randint(1, 4, 10), - randint(3, 6, 10), - randint(1, 11, 10)): - arrs = randn(n_args, n_broadcast, *[2]*rank) - split_idx = randint(1, n_args-1) + for rank, n_args, n_broadcast in zip(testutil.rng.randint(1, 4, 10), + testutil.rng.randint(3, 6, 10), + testutil.rng.randint(1, 11, 10)): + arrs = testutil.rng.randn(n_args, n_broadcast, *[2]*rank) + split_idx = testutil.rng.randint(1, n_args-1) arr = util.tensor(*arrs[split_idx:], rank=rank) ins = util.tensor(*arrs[:split_idx], rank=rank) - pos = randint(0, split_idx, split_idx) + pos = testutil.rng.randint(0, split_idx, split_idx) sorted_arrs = np.insert(arrs[split_idx:], pos, arrs[:split_idx], axis=0) @@ -365,7 +373,7 @@ def test_tensor_transpose(self): order = np.arange(4) for _ in range(20): - order = np.random.permutation(order) + order = testutil.rng.permutation(order) r = util.tensor_transpose(arr, order, arr_dims) self.assertArrayAlmostEqual(r, util.tensor(*paulis[order])) @@ -398,12 +406,12 @@ def test_tensor_transpose(self): # wrong order (floats instead of ints) r = util.tensor_transpose(arr, (0., 1., 2., 3.), arr_dims) - # Random tests - for rank, n_args, n_broadcast in zip(randint(1, 4, 10), - randint(3, 6, 10), - randint(1, 11, 10)): - arrs = randn(n_args, n_broadcast, *[2]*rank) - order = np.random.permutation(n_args) + # random tests + for rank, n_args, n_broadcast in zip(testutil.rng.randint(1, 4, 10), + testutil.rng.randint(3, 6, 10), + testutil.rng.randint(1, 11, 10)): + arrs = testutil.rng.randn(n_args, n_broadcast, *[2]*rank) + order = testutil.rng.permutation(n_args) arr_dims = [[2]*n_args]*rank r = util.tensor_transpose(util.tensor(*arrs, rank=rank), @@ -413,7 +421,7 @@ def test_tensor_transpose(self): r, util.tensor(*arrs[order], rank=rank)) def test_mdot(self): - arr = randn(3, 2, 4, 4) + arr = testutil.rng.randn(3, 2, 4, 4) self.assertArrayEqual(util.mdot(arr, 0), arr[0] @ arr[1] @ arr[2]) self.assertArrayEqual(util.mdot(arr, 1), arr[:, 0] @ arr[:, 1]) @@ -422,8 +430,9 @@ def test_remove_float_errors(self): scale = 1 if eps_scale is None else eps_scale for dtype in (float, complex): arr = np.zeros((10, 10), dtype=dtype) - arr += scale*np.finfo(arr.dtype).eps*random(arr.shape) - arr[randint(0, 2, arr.shape, dtype=bool)] *= -1 + arr += scale*np.finfo(arr.dtype).eps *\ + testutil.rng.random(arr.shape) + arr[testutil.rng.randint(0, 2, arr.shape, dtype=bool)] *= -1 arr = util.remove_float_errors(arr, eps_scale) self.assertArrayEqual(arr, np.zeros(arr.shape, dtype=dtype)) @@ -431,10 +440,10 @@ def test_oper_equiv(self): with self.assertRaises(ValueError): util.oper_equiv(*[np.ones((1, 2, 3))]*2) - for d in randint(2, 10, (5,)): + for d in testutil.rng.randint(2, 10, (5,)): psi = qt.rand_ket(d) U = qt.rand_dm(d) - phase = randn() + phase = testutil.rng.randn() result = util.oper_equiv(psi, psi*np.exp(1j*phase)) self.assertTrue(result[0]) @@ -474,12 +483,12 @@ def test_oper_equiv(self): self.assertFalse(result[0]) def test_dot_HS(self): - U, V = randint(0, 100, (2, 2, 2)) + U, V = testutil.rng.randint(0, 100, (2, 2, 2)) S = util.dot_HS(U, V) T = util.dot_HS(U, V, eps=0) self.assertArrayEqual(S, T) - for d in randint(2, 10, (5,)): + for d in testutil.rng.randint(2, 10, (5,)): U = qt.rand_herm(d) V = qt.rand_herm(d) self.assertArrayAlmostEqual(util.dot_HS(U, V), (U.dag()*V).tr()) @@ -490,7 +499,7 @@ def test_dot_HS(self): self.assertEqual(util.dot_HS(U, U + 1e-14, eps=1e-10), d) def test_all_array_equal(self): - for n in randint(2, 10, (10,)): + for n in testutil.rng.randint(2, 10, (10,)): gen = (np.ones((10, 10)) for _ in range(n)) lst = [np.ones((10, 10)) for _ in range(n)] self.assertTrue(util.all_array_equal(gen)) @@ -505,7 +514,7 @@ def test_get_sample_frequencies(self): pulse = PulseSequence( [[util.P_np[1], [np.pi/2]]], [[util.P_np[1], [1]]], - [abs(np.random.randn())] + [abs(testutil.rng.randn())] ) # Default args omega = util.get_sample_frequencies(pulse) @@ -532,7 +541,7 @@ def test_symmetrize_spectrum(self): pulse = PulseSequence( [[util.P_np[1], [np.pi/2]]], [[util.P_np[1], [1]]], - [abs(np.random.randn())] + [abs(testutil.rng.randn())] ) asym_omega = util.get_sample_frequencies(pulse, symmetric=False, diff --git a/tests/testutil.py b/tests/testutil.py index ed1c664..9a1e35d 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -28,13 +28,15 @@ import numpy as np import qutip as qt -from numpy.random import randn +from numpy.random import RandomState from numpy.testing import assert_allclose, assert_array_equal from scipy.io import loadmat from scipy.linalg import expm from filter_functions import Basis, PulseSequence, util +rng = RandomState() + class TestCase(unittest.TestCase): @@ -130,7 +132,7 @@ def cdd_even(l, t): def rand_herm(d: int, n: int = 1) -> np.ndarray: """n random Hermitian matrices of dimension d""" - A = randn(n, d, d) + 1j*randn(n, d, d) + A = rng.randn(n, d, d) + 1j*rng.randn(n, d, d) return (A + A.conj().transpose([0, 2, 1]))/2 @@ -154,19 +156,19 @@ def rand_pulse_sequence(d: int, n_dt: int, n_cops: int = 3, n_nops: int = 3, btype: str = 'GGM', seed=None): """Random pulse sequence instance""" if seed is not None: - np.random.seed(seed) + rng.seed(seed) c_opers = rand_herm_traceless(d, n_cops) n_opers = rand_herm_traceless(d, n_nops) - c_coeffs = np.random.randn(n_cops, n_dt) - n_coeffs = np.random.rand(n_nops, n_dt) + c_coeffs = rng.randn(n_cops, n_dt) + n_coeffs = rng.rand(n_nops, n_dt) letters = np.array(list(string.ascii_letters)) - c_identifiers = np.random.choice(letters, n_cops, replace=False) - n_identifiers = np.random.choice(letters, n_nops, replace=False) + c_identifiers = rng.choice(letters, n_cops, replace=False) + n_identifiers = rng.choice(letters, n_nops, replace=False) - dt = 1 - np.random.rand(n_dt) # (0, 1] instead of [0, 1) + dt = 1 - rng.rand(n_dt) # (0, 1] instead of [0, 1) if btype == 'GGM': basis = Basis.ggm(d) else: