def test_infidelity_convergence(self): omega = { 'omega_IR': 0, 'omega_UV': 2, 'spacing': 'linear', 'n_min': 10, 'n_max': 50, 'n_points': 4 } def spectrum(omega): return omega**0 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 = ff.infidelity(simple_pulse, spectrum, [], test_convergence=True) with self.assertRaises(TypeError): n, infids = ff.infidelity(simple_pulse, [1, 2, 3], dict(spacing='foobar'), test_convergence=True) with self.assertRaises(ValueError): n, infids = ff.infidelity(simple_pulse, spectrum, dict(spacing='foobar'), test_convergence=True) # Test with default args n, infids = ff.infidelity(simple_pulse, spectrum, {}, test_convergence=True) # Test with non-default args identifiers = rng.choice(complicated_pulse.n_oper_identifiers, rng.randint(1, 4)) n, infids = ff.infidelity(complicated_pulse, spectrum, omega, test_convergence=True, n_oper_identifiers=identifiers)
def test_pulse_sequence_attributes_concat(self): """Test attributes of concatenated sequence.""" X, Y, Z = util.paulis[1:] n_dt_1 = rng.randint(5, 11) x_coeff_1 = rng.standard_normal(n_dt_1) z_coeff_1 = rng.standard_normal(n_dt_1) dt_1 = np.abs(rng.standard_normal(n_dt_1)) n_dt_2 = rng.randint(5, 11) y_coeff_2 = rng.standard_normal(n_dt_2) z_coeff_2 = rng.standard_normal(n_dt_2) dt_2 = np.abs(rng.standard_normal(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, rng.standard_normal(2)], [X, rng.standard_normal(2)]], [[Z, np.abs(rng.standard_normal(2))]], [1, 1]) # Concatenate with different noise opers pulses = [testutil.rand_pulse_sequence(2, 1) for _ in range(2)] pulses[0].omega = np.arange(10) pulses[1].omega = np.arange(10) newpulse = ff.concatenate(pulses, calc_filter_function=True) self.assertTrue(newpulse.is_cached('filter function')) pulse_12 = pulse_1 @ pulse_2 pulse_21 = pulse_2 @ pulse_1 with self.assertRaises(TypeError): _ = pulse_1 @ rng.standard_normal((2, 2)) # Concatenate pulses with same operators but different labels with self.assertRaises(ValueError): pulse_1 @ pulse_3 # Test nbytes property _ = pulse_1.nbytes self.assertArrayEqual(pulse_12.dt, [*dt_1, *dt_2]) self.assertArrayEqual(pulse_21.dt, [*dt_2, *dt_1]) self.assertArrayEqual(pulse_12.c_opers, [X, Y]) self.assertArrayEqual(pulse_21.c_opers, [Y, X]) self.assertArrayEqual(pulse_12.c_oper_identifiers, ['A_0_0', 'A_0_1']) self.assertArrayEqual(pulse_21.c_oper_identifiers, ['A_0_0', 'A_0_1']) self.assertArrayEqual(pulse_12.c_coeffs, [[*x_coeff_1, *np.zeros(n_dt_2)], [*np.zeros(n_dt_1), *y_coeff_2]]) self.assertArrayEqual(pulse_21.c_coeffs, [[*y_coeff_2, *np.zeros(n_dt_1)], [*np.zeros(n_dt_2), *x_coeff_1]]) self.assertArrayEqual(pulse_12.n_opers, [Z]) self.assertArrayEqual(pulse_21.n_opers, [Z]) self.assertArrayEqual(pulse_12.n_oper_identifiers, ['B_0']) self.assertArrayEqual(pulse_21.n_oper_identifiers, ['B_0']) self.assertArrayEqual(pulse_12.n_coeffs, [[*z_coeff_1, *z_coeff_2]]) self.assertArrayEqual(pulse_21.n_coeffs, [[*z_coeff_2, *z_coeff_1]]) omega = np.linspace(-100, 100, 101) pulses = (pulse_1, pulse_2, pulse_12, pulse_21) for pulse in pulses: self.assertIsNone(pulse._total_phases) self.assertIsNone(pulse._total_propagator) self.assertIsNone(pulse._total_propagator_liouville) total_phases = pulse.get_total_phases(omega) total_propagator = pulse.total_propagator total_propagator_liouville = pulse.total_propagator_liouville self.assertArrayEqual(total_phases, pulse._total_phases) self.assertArrayEqual(total_propagator, pulse._total_propagator) self.assertArrayEqual(total_propagator_liouville, pulse._total_propagator_liouville) # Test custom identifiers letters = rng.choice(list(string.ascii_letters), size=(6, 5), replace=False) ids = [''.join(c) for c in letters[:3]] labels = [''.join(c) for c in letters[3:]] pulse = ff.PulseSequence( list(zip([X, Y, Z], rng.standard_normal((3, 2)), ids, labels)), list(zip([X, Y, Z], rng.standard_normal((3, 2)), ids, labels)), [1, 1] ) self.assertArrayEqual(pulse.c_oper_identifiers, sorted(ids)) self.assertArrayEqual(pulse.n_oper_identifiers, sorted(ids))
def test_extend_with_identity(self): """Test extending a pulse to more qubits""" ID, X, Y, Z = util.paulis n_dt = 10 coeffs = rng.standard_normal((3, n_dt)) ids = ['X', 'Y', 'Z'] pulse = ff.PulseSequence( list(zip((X, Y, Z), coeffs, ids)), list(zip((X, Y, Z), np.ones((3, n_dt)), ids)), np.ones(n_dt), basis=ff.Basis.pauli(1) ) omega = util.get_sample_frequencies(pulse, spacing='log', n_samples=50) for N in rng.randint(2, 5, 4): for target in rng.randint(0, N-1, 2): pulse.cleanup('all') ext_opers = util.tensor(*np.insert(np.tile(ID, (N-1, 3, 1, 1)), target, (X, Y, Z), axis=0)) # By default, extend should add the target qubit as suffix to # identifiers ext_ids = [i + f'_{target}' for i in ids] ext_pulse = ff.PulseSequence( list(zip(ext_opers, coeffs, ext_ids)), list(zip(ext_opers, np.ones((3, n_dt)), ext_ids)), np.ones(n_dt), basis=ff.Basis.pauli(N) ) # Use custom mapping for identifiers and or labels letters = 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( list(zip(ext_opers, coeffs, mapped_ids, ext_ids)), list(zip(ext_opers, np.ones((3, n_dt)), mapped_ids, ext_ids)), np.ones(n_dt), basis=ff.Basis.pauli(N) ) ext_pulse_mapped_labels = ff.PulseSequence( list(zip(ext_opers, coeffs, ext_ids, mapped_ids)), list(zip(ext_opers, np.ones((3, n_dt)), ext_ids, mapped_ids)), np.ones(n_dt), basis=ff.Basis.pauli(N) ) ext_pulse_mapped_identifiers_labels = ff.PulseSequence( list(zip(ext_opers, coeffs, mapped_ids)), list(zip(ext_opers, np.ones((3, n_dt)), mapped_ids)), np.ones(n_dt), basis=ff.Basis.pauli(N) ) calc_filter_functionF = rng.randint(0, 2) if calc_filter_functionF: # Expect things to be cached in extended pulse if original # also was cached pulse.cache_filter_function(omega) ext_pulse.cache_filter_function(omega) test_ext_pulse = ff.extend([(pulse, target)], N, d_per_qubit=2) test_ext_pulse_mapped_identifiers = ff.extend( [(pulse, target, mapping)], N, d_per_qubit=2 ) test_ext_pulse_mapped_labels = ff.extend( [(pulse, target, None, mapping)], N, d_per_qubit=2 ) test_ext_pulse_mapped_identifiers_labels = ff.extend( [(pulse, target, mapping, mapping)], N, d_per_qubit=2 ) self.assertEqual(ext_pulse, test_ext_pulse) self.assertEqual(ext_pulse_mapped_identifiers, test_ext_pulse_mapped_identifiers) self.assertEqual(ext_pulse_mapped_labels, test_ext_pulse_mapped_labels) self.assertEqual(ext_pulse_mapped_identifiers_labels, test_ext_pulse_mapped_identifiers_labels) if calc_filter_functionF: self.assertCorrectDiagonalization(test_ext_pulse, atol=1e-14) self.assertArrayAlmostEqual(test_ext_pulse._propagators, ext_pulse._propagators, atol=1e-14) self.assertArrayAlmostEqual( test_ext_pulse._total_propagator_liouville, ext_pulse._total_propagator_liouville, atol=1e-14 ) self.assertArrayAlmostEqual( test_ext_pulse._total_propagator, ext_pulse._total_propagator, atol=1e-14 ) self.assertArrayAlmostEqual(test_ext_pulse._total_phases, ext_pulse._total_phases) self.assertArrayAlmostEqual(test_ext_pulse._control_matrix, ext_pulse._control_matrix, atol=1e-12) self.assertArrayAlmostEqual( test_ext_pulse._filter_function, ext_pulse._filter_function, atol=1e-12 ) else: self.assertIsNone(test_ext_pulse._eigvals) self.assertIsNone(test_ext_pulse._eigvecs) self.assertIsNone(test_ext_pulse._propagators) self.assertIsNone( test_ext_pulse._total_propagator_liouville) self.assertIsNone(test_ext_pulse._total_propagator) self.assertIsNone(test_ext_pulse._total_phases) self.assertIsNone(test_ext_pulse._control_matrix) self.assertIsNone(test_ext_pulse._filter_function) pulse.cleanup('all') ext_pulse.cleanup('all')
def test_pulse_sequence_attributes_concat(self): """Test attributes of concatenated sequence.""" X, Y, Z = util.paulis[1:] n_dt_1 = rng.integers(5, 11) x_coeff_1 = rng.standard_normal(n_dt_1) z_coeff_1 = rng.standard_normal(n_dt_1) dt_1 = np.abs(rng.standard_normal(n_dt_1)) n_dt_2 = rng.integers(5, 11) y_coeff_2 = rng.standard_normal(n_dt_2) z_coeff_2 = rng.standard_normal(n_dt_2) dt_2 = np.abs(rng.standard_normal(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, rng.standard_normal(2)], [X, rng.standard_normal(2)]], [[Z, np.abs(rng.standard_normal(2))]], [1, 1]) pulse_4 = ff.PulseSequence( [[Y, rng.standard_normal(2)], [X, rng.standard_normal(2)]], [[Z, np.ones(2)]], [1, 1]) pulse_5 = ff.PulseSequence([[Y, np.zeros(5), 'A_0']], [[Y, np.zeros(5), 'B_1']], 1 - rng.random(5)) # Concatenate with different noise opers pulses = [testutil.rand_pulse_sequence(2, 1) for _ in range(2)] pulses[0].omega = np.arange(10) pulses[1].omega = np.arange(10) newpulse = ff.concatenate(pulses, calc_filter_function=True) self.assertTrue(newpulse.is_cached('filter function')) with self.assertRaises(TypeError): _ = pulse_1 @ rng.standard_normal((2, 2)) # Concatenate pulses with same operators but different labels with self.assertRaises(ValueError): pulse_1 @ pulse_3 # Test nbytes property _ = pulse_1.nbytes pulse_12 = pulse_1 @ pulse_2 pulse_21 = pulse_2 @ pulse_1 pulse_45 = pulse_4 @ pulse_5 self.assertArrayEqual(pulse_12.dt, [*dt_1, *dt_2]) self.assertArrayEqual(pulse_21.dt, [*dt_2, *dt_1]) self.assertIs(pulse_12._t, None) self.assertIs(pulse_21._t, None) self.assertEqual(pulse_12._tau, pulse_1.tau + pulse_2.tau) self.assertEqual(pulse_21._tau, pulse_1.tau + pulse_2.tau) self.assertAlmostEqual(pulse_12.duration, pulse_1.duration + pulse_2.duration) self.assertAlmostEqual(pulse_21.duration, pulse_2.duration + pulse_1.duration) self.assertAlmostEqual(pulse_12.duration, pulse_21.duration) self.assertArrayAlmostEqual( pulse_12.t, [*pulse_1.t, *(pulse_2.t[1:] + pulse_1.tau)]) self.assertArrayAlmostEqual( pulse_21.t, [*pulse_2.t, *(pulse_1.t[1:] + pulse_2.tau)]) self.assertArrayEqual(pulse_12.c_opers, [X, Y]) self.assertArrayEqual(pulse_21.c_opers, [Y, X]) self.assertArrayEqual(pulse_12.c_oper_identifiers, ['A_0_0', 'A_0_1']) self.assertArrayEqual(pulse_21.c_oper_identifiers, ['A_0_0', 'A_0_1']) self.assertArrayEqual( pulse_12.c_coeffs, [[*x_coeff_1, *np.zeros(n_dt_2)], [*np.zeros(n_dt_1), *y_coeff_2]]) self.assertArrayEqual( pulse_21.c_coeffs, [[*y_coeff_2, *np.zeros(n_dt_1)], [*np.zeros(n_dt_2), *x_coeff_1]]) self.assertArrayEqual(pulse_12.n_opers, [Z]) self.assertArrayEqual(pulse_21.n_opers, [Z]) self.assertArrayEqual(pulse_12.n_oper_identifiers, ['B_0']) self.assertArrayEqual(pulse_21.n_oper_identifiers, ['B_0']) self.assertArrayEqual(pulse_12.n_coeffs, [[*z_coeff_1, *z_coeff_2]]) self.assertArrayEqual(pulse_21.n_coeffs, [[*z_coeff_2, *z_coeff_1]]) # Make sure zero coefficients are handled correctly self.assertFalse(np.any(np.isnan(pulse_45.c_coeffs))) self.assertFalse(np.any(np.isnan(pulse_45.n_coeffs))) self.assertArrayEqual(pulse_45.c_coeffs, [[*pulse_4.c_coeffs[0], *np.zeros(5)], [*pulse_4.c_coeffs[1], *np.zeros(5)]]) self.assertArrayEqual( pulse_45.n_coeffs, [[*pulse_4.n_coeffs[0], *[pulse_4.n_coeffs[0, 0]] * 5], [*[pulse_5.n_coeffs[0, 0]] * 2, *pulse_5.n_coeffs[0]]]) omega = np.linspace(-100, 100, 101) pulses = (pulse_1, pulse_2, pulse_12, pulse_21) for pulse in pulses: self.assertIsNone(pulse._total_phases) self.assertIsNone(pulse._total_propagator) self.assertIsNone(pulse._total_propagator_liouville) total_phases = pulse.get_total_phases(omega) total_propagator = pulse.total_propagator total_propagator_liouville = pulse.total_propagator_liouville self.assertArrayEqual(total_phases, pulse._total_phases) self.assertArrayEqual(total_propagator, pulse._total_propagator) self.assertArrayEqual(total_propagator_liouville, pulse._total_propagator_liouville) # Test custom identifiers letters = rng.choice(list(string.ascii_letters), size=(6, 5), replace=False) ids = [''.join(c) for c in letters[:3]] labels = [''.join(c) for c in letters[3:]] pulse = ff.PulseSequence( list(zip([X, Y, Z], rng.standard_normal((3, 2)), ids, labels)), list(zip([X, Y, Z], rng.standard_normal((3, 2)), ids, labels)), [1, 1]) self.assertArrayEqual(pulse.c_oper_identifiers, sorted(ids)) self.assertArrayEqual(pulse.n_oper_identifiers, sorted(ids)) pulse = testutil.rand_pulse_sequence(2, 7, 1, 2) periodic_pulse = ff.concatenate_periodic(pulse, 7) self.assertIs(periodic_pulse._t, None) self.assertEqual(periodic_pulse._tau, pulse.tau * 7) self.assertArrayAlmostEqual(periodic_pulse.t, [0, *periodic_pulse.dt.cumsum()])