Exemple #1
0
    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)
Exemple #2
0
    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))
Exemple #3
0
    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')
Exemple #4
0
    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()])