Esempio n. 1
0
    def test_exceptions(self):
        X = util.paulis[1]
        n_dt = 10
        omega = np.linspace(0, 1, 50)

        pulse_1 = testutil.rand_pulse_sequence(2, n_dt, btype='Pauli')
        pulse_2 = testutil.rand_pulse_sequence(2, n_dt, btype='GGM')

        pulse_1.cache_filter_function(omega)
        pulse_11 = ff.extend([[pulse_1, 0], [pulse_1, 1]])
        pulse_11.cache_filter_function(omega+1)

        with self.assertRaises(ValueError):
            # qubit indices don't match on pulse that is remapped
            ff.extend([(pulse_11, (2, 1, 0))])

        with self.assertRaises(ValueError):
            # wrong dimensions
            ff.extend([(pulse_1, (0, 1))])

        with self.assertRaises(ValueError):
            # wrong dimensions
            ff.extend([(pulse_1, (0,))], d_per_qubit=3)

        with self.assertRaises(ValueError):
            # wrong dimensions
            ff.extend([(pulse_11, (0,))])

        with self.assertRaises(ValueError):
            # different dt
            ff.extend([(pulse_1, 0), [pulse_2, 1]])

        with self.assertRaises(ValueError):
            # Multiple pulses mapped to same qubit
            ff.extend([(pulse_1, 0), [pulse_1, 0]])

        with self.assertRaises(ValueError):
            # N < max(qubits)
            ff.extend([(pulse_1, 2)], N=2)

        with self.assertRaises(ValueError):
            # cache_filter_function == True and unequal omega
            ff.extend([(pulse_1, 0), (pulse_11, (1, 2))],
                      cache_filter_function=True, omega=None)

        with self.assertRaises(ValueError):
            # cache_diagonalization == False and additional_noise_Hamiltonian
            # is not None
            additional_noise_Hamiltonian = [[util.tensor(X, X), np.ones(n_dt)]]
            ff.extend(
                [(pulse_1, 0), (pulse_1, 1)], cache_diagonalization=False,
                additional_noise_Hamiltonian=additional_noise_Hamiltonian
            )

        with self.assertRaises(ValueError):
            # additional noise Hamiltonian defines existing identifier
            additional_noise_Hamiltonian = [
                [util.tensor(X, X), np.ones(n_dt), 'foo'],
                [util.tensor(X, X), np.ones(n_dt), 'foo'],
            ]
            ff.extend(
                [(pulse_1, 0), (pulse_1, 1)],
                additional_noise_Hamiltonian=additional_noise_Hamiltonian
            )

        with self.assertRaises(ValueError):
            # additional_noise_Hamiltonian has wrong dimensions
            additional_noise_Hamiltonian = [[util.tensor(X, X, X),
                                             np.ones(n_dt)]]
            ff.extend(
                [(pulse_1, 0), (pulse_1, 1)],
                additional_noise_Hamiltonian=additional_noise_Hamiltonian
            )

        with self.assertWarns(UserWarning):
            # Non-pauli basis
            ff.extend([(pulse_2, 0)])
Esempio n. 2
0
    def test_caching(self):
        """Test caching"""
        pulse_1 = testutil.rand_pulse_sequence(2, 10, btype='Pauli')
        pulse_2 = testutil.rand_pulse_sequence(2, 10, btype='Pauli')
        pulse_2.dt = pulse_1.dt
        pulse_2.t = pulse_1.t
        omega = util.get_sample_frequencies(pulse_1, 50)

        # diagonalize one pulse
        pulse_1.diagonalize()
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)])
        self.assertIsNone(extended_pulse._eigvals)
        self.assertIsNone(extended_pulse._eigvecs)
        self.assertIsNone(extended_pulse._propagators)
        self.assertIsNone(extended_pulse._total_propagator)
        self.assertIsNone(extended_pulse._total_propagator_liouville)
        self.assertIsNone(extended_pulse._total_phases)
        self.assertIsNone(extended_pulse._control_matrix)
        self.assertIsNone(extended_pulse._filter_function)

        # override
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)],
                                   cache_diagonalization=True)
        self.assertIsNotNone(extended_pulse._eigvals)
        self.assertIsNotNone(extended_pulse._eigvecs)
        self.assertIsNotNone(extended_pulse._propagators)
        self.assertIsNotNone(extended_pulse._total_propagator)
        self.assertIsNone(extended_pulse._total_propagator_liouville)
        self.assertIsNone(extended_pulse._total_phases)
        self.assertIsNone(extended_pulse._control_matrix)
        self.assertIsNone(extended_pulse._filter_function)

        # diagonalize both
        pulse_2.diagonalize()
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)])
        self.assertIsNotNone(extended_pulse._eigvals)
        self.assertIsNotNone(extended_pulse._eigvecs)
        self.assertIsNotNone(extended_pulse._propagators)
        self.assertIsNotNone(extended_pulse._total_propagator)
        self.assertIsNone(extended_pulse._total_propagator_liouville)
        self.assertIsNone(extended_pulse._total_phases)
        self.assertIsNone(extended_pulse._control_matrix)
        self.assertIsNone(extended_pulse._filter_function)

        # override
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)],
                                   cache_diagonalization=False)
        self.assertIsNone(extended_pulse._eigvals)
        self.assertIsNone(extended_pulse._eigvecs)
        self.assertIsNone(extended_pulse._propagators)
        # Total_propagators is still cached
        self.assertIsNotNone(extended_pulse._total_propagator)
        self.assertIsNone(extended_pulse._total_propagator_liouville)
        self.assertIsNone(extended_pulse._total_phases)
        self.assertIsNone(extended_pulse._control_matrix)
        self.assertIsNone(extended_pulse._filter_function)

        # Get filter function for one pulse
        pulse_1.cache_filter_function(omega)
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)])
        self.assertIsNone(extended_pulse._total_propagator_liouville)
        self.assertIsNone(extended_pulse._total_phases)
        self.assertIsNone(extended_pulse._control_matrix)
        self.assertIsNone(extended_pulse._filter_function)

        # override
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)],
                                   cache_filter_function=True,
                                   omega=omega)
        self.assertIsNotNone(extended_pulse._total_propagator_liouville)
        self.assertIsNotNone(extended_pulse._total_phases)
        self.assertIsNotNone(extended_pulse._control_matrix)
        self.assertIsNotNone(extended_pulse._filter_function)

        # Get filter function for both
        pulse_2.cache_filter_function(omega)
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)])
        self.assertIsNotNone(extended_pulse._total_propagator_liouville)
        self.assertIsNotNone(extended_pulse._total_phases)
        self.assertIsNotNone(extended_pulse._control_matrix)
        self.assertIsNotNone(extended_pulse._filter_function)

        # override
        extended_pulse = ff.extend([(pulse_1, 0), (pulse_2, 1)],
                                   cache_filter_function=False)
        self.assertIsNone(extended_pulse._total_propagator_liouville)
        self.assertIsNone(extended_pulse._total_phases)
        self.assertIsNone(extended_pulse._control_matrix)
        self.assertIsNone(extended_pulse._filter_function)
Esempio n. 3
0
    def test_accuracy(self):
        ID, X, Y, Z = util.paulis
        XI = util.tensor(X, ID)
        IX = util.tensor(ID, X)
        XII = util.tensor(X, ID, ID)
        IXI = util.tensor(ID, X, ID)
        IIX = util.tensor(ID, ID, X)
        XIII = util.tensor(X, ID, ID, ID)
        IXII = util.tensor(ID, X, ID, ID)
        IIXI = util.tensor(ID, ID, X, ID)
        IIIX = util.tensor(ID, ID, ID, X)
        YI = util.tensor(Y, ID)
        IY = util.tensor(ID, Y)
        YII = util.tensor(Y, ID, ID)
        IYI = util.tensor(ID, Y, ID)
        IIY = util.tensor(ID, ID, Y)
        YIII = util.tensor(Y, ID, ID, ID)
        IYII = util.tensor(ID, Y, ID, ID)
        IIYI = util.tensor(ID, ID, Y, ID)
        IIIY = util.tensor(ID, ID, ID, Y)
        ZI = util.tensor(Z, ID)
        IZ = util.tensor(ID, Z)
        ZII = util.tensor(Z, ID, ID)
        IZI = util.tensor(ID, Z, ID)
        ZIII = util.tensor(Z, ID, ID, ID)
        IZII = util.tensor(ID, Z, ID, ID)
        IIZI = util.tensor(ID, ID, Z, ID)
        IIIZ = util.tensor(ID, ID, ID, Z)

        IIZ = util.tensor(ID, ID, Z)
        XXX = util.tensor(X, X, X)

        n_dt = 10
        coeffs = rng.standard_normal((3, n_dt))
        X_pulse = ff.PulseSequence(
            [[X, coeffs[0], 'X']],
            list(zip((X, Y, Z), np.ones((3, n_dt)), ('X', 'Y', 'Z'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(1)
        )
        Y_pulse = ff.PulseSequence(
            [[Y, coeffs[1], 'Y']],
            list(zip((X, Y, Z), np.ones((3, n_dt)), ('X', 'Y', 'Z'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(1)
        )
        Z_pulse = ff.PulseSequence(
            [[Z, coeffs[2], 'Z']],
            list(zip((X, Y, Z), np.ones((3, n_dt)), ('X', 'Y', 'Z'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(1)
        )
        XZ_pulse = ff.PulseSequence(
            [[XI, coeffs[0], 'XI'],
             [IZ, coeffs[2], 'IZ']],
            list(zip((XI, YI, ZI, IX, IY, IZ), np.ones((6, n_dt)),
                     ('XI', 'YI', 'ZI', 'IX', 'IY', 'IZ'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(2)
        )
        XYZ_pulse = ff.PulseSequence(
            [[XII, coeffs[0], 'XII'],
             [IYI, coeffs[1], 'IYI'],
             [IIZ, coeffs[2], 'IIZ']],
            list(zip((XII, YII, ZII, IIX, IIY, IIZ, IXI, IYI, IZI, XXX),
                     np.ones((10, n_dt)),
                     ('XII', 'YII', 'ZII', 'IIX', 'IIY', 'IIZ', 'IXI', 'IYI',
                      'IZI', 'XXX'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(3)
        )
        ZYX_pulse = ff.PulseSequence(
            [[IIX, coeffs[0], 'IIX'],
             [IYI, coeffs[1], 'IYI'],
             [ZII, coeffs[2], 'ZII']],
            list(zip((IIX, IIY, IIZ, XII, YII, ZII, IXI, IYI, IZI),
                     np.ones((9, n_dt)),
                     ('IIX', 'IIY', 'IIZ', 'XII', 'YII', 'ZII', 'IXI', 'IYI',
                      'IZI'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(3)
        )
        XZXZ_pulse = ff.PulseSequence(
            [[XIII, coeffs[0], 'XIII'],
             [IZII, coeffs[2], 'IZII'],
             [IIXI, coeffs[0], 'IIXI'],
             [IIIZ, coeffs[2], 'IIIZ']],
            list(zip((XIII, YIII, ZIII, IXII, IYII, IZII,
                      IIXI, IIYI, IIZI, IIIX, IIIY, IIIZ),
                     np.ones((12, n_dt)),
                     ('XIII', 'YIII', 'ZIII', 'IXII', 'IYII', 'IZII',
                      'IIXI', 'IIYI', 'IIZI', 'IIIX', 'IIIY', 'IIIZ'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(4)
        )
        XXZZ_pulse = ff.PulseSequence(
            [[XIII, coeffs[0], 'XIII'],
             [IIZI, coeffs[2], 'IIZI'],
             [IXII, coeffs[0], 'IXII'],
             [IIIZ, coeffs[2], 'IIIZ']],
            list(zip((XIII, YIII, ZIII, IIXI, IIYI, IIZI,
                      IXII, IYII, IZII, IIIX, IIIY, IIIZ),
                     np.ones((12, n_dt)),
                     ('XIII', 'YIII', 'ZIII', 'IIXI', 'IIYI', 'IIZI',
                      'IXII', 'IYII', 'IZII', 'IIIX', 'IIIY', 'IIIZ'))),
            np.ones(n_dt),
            basis=ff.Basis.pauli(4)
        )

        # Cache
        omega = ff.util.get_sample_frequencies(XYZ_pulse, n_samples=50)
        X_pulse.cache_filter_function(omega)
        Y_pulse.cache_filter_function(omega)
        Z_pulse.cache_filter_function(omega)
        XZ_pulse.cache_filter_function(omega)
        XYZ_pulse.cache_filter_function(omega)
        ZYX_pulse.cache_filter_function(omega)
        XZXZ_pulse.cache_filter_function(omega)
        XXZZ_pulse.cache_filter_function(omega)

        # Test that mapping a pulse to itself returns the pulse itself and
        # issues a warning
        with self.assertWarns(UserWarning):
            pulse = ff.extend([(X_pulse, 0)])
            self.assertIs(pulse, X_pulse)

        with self.assertWarns(UserWarning):
            pulse = ff.extend([(XZ_pulse, (0, 1))])
            self.assertIs(pulse, XZ_pulse)

        # Test mapping two single-qubit pulses to a two-qubit pulse
        XZ_pulse_ext = ff.extend([
            (X_pulse, 0, {'X': 'XI', 'Y': 'YI', 'Z': 'ZI'}),
            (Z_pulse, 1, {'X': 'IX', 'Y': 'IY', 'Z': 'IZ'})
        ])

        self.assertEqual(XZ_pulse, XZ_pulse_ext)
        self.assertCorrectDiagonalization(XZ_pulse_ext, atol=1e-14)
        self.assertArrayAlmostEqual(XZ_pulse._propagators,
                                    XZ_pulse_ext._propagators, atol=1e-10)
        self.assertArrayAlmostEqual(XZ_pulse._control_matrix,
                                    XZ_pulse_ext._control_matrix, atol=1e-9)
        self.assertArrayAlmostEqual(XZ_pulse._filter_function,
                                    XZ_pulse_ext._filter_function, atol=1e-9)

        # Test additional noise Hamiltonian
        add_H_n = list(zip((XXX,), np.ones((1, n_dt)), ['XXX']))
        XYZ_pulse_ext = ff.extend(
            [(XZ_pulse, (0, 2),
              {i: i[0] + 'I' + i[1] for i in XZ_pulse.n_oper_identifiers}),
             (Y_pulse, 1,
              {i: 'I' + i[0] + 'I' for i in Y_pulse.n_oper_identifiers})],
            additional_noise_Hamiltonian=add_H_n
        )

        self.assertEqual(XYZ_pulse, XYZ_pulse_ext)
        self.assertCorrectDiagonalization(XYZ_pulse_ext, atol=1e-14)
        self.assertArrayAlmostEqual(XYZ_pulse._propagators,
                                    XYZ_pulse_ext._propagators, atol=1e-10)
        self.assertArrayAlmostEqual(XYZ_pulse._control_matrix,
                                    XYZ_pulse_ext._control_matrix, atol=1e-9)
        self.assertArrayAlmostEqual(XYZ_pulse._filter_function,
                                    XYZ_pulse_ext._filter_function, atol=1e-9)

        # Test remapping a two-qubit pulse
        ZYX_pulse_ext = ff.extend(
            [(XZ_pulse, (2, 0),
              {i: i[1] + 'I' + i[0] for i in XZ_pulse.n_oper_identifiers}),
             (Y_pulse, 1,
              {i: 'I' + i[0] + 'I' for i in Y_pulse.n_oper_identifiers})],
        )

        self.assertEqual(ZYX_pulse, ZYX_pulse_ext)
        self.assertCorrectDiagonalization(ZYX_pulse_ext, atol=1e-14)
        self.assertArrayAlmostEqual(ZYX_pulse._propagators,
                                    ZYX_pulse_ext._propagators, atol=1e-10)
        self.assertArrayAlmostEqual(ZYX_pulse._control_matrix,
                                    ZYX_pulse_ext._control_matrix, atol=1e-9)
        self.assertArrayAlmostEqual(ZYX_pulse._filter_function,
                                    ZYX_pulse_ext._filter_function, atol=1e-9)

        XZXZ_pulse_ext = ff.extend([
            (XZ_pulse, (0, 1),
             {i: i + 'II' for i in XZ_pulse.n_oper_identifiers}),
            (XZ_pulse, (2, 3),
             {i: 'II' + i for i in XZ_pulse.n_oper_identifiers})
        ], cache_diagonalization=True)
        self.assertEqual(XZXZ_pulse, XZXZ_pulse_ext)
        self.assertCorrectDiagonalization(XZXZ_pulse_ext, atol=1e-14)
        self.assertArrayAlmostEqual(XZXZ_pulse._propagators,
                                    XZXZ_pulse_ext._propagators, atol=1e-10)
        self.assertArrayAlmostEqual(XZXZ_pulse._control_matrix,
                                    XZXZ_pulse_ext._control_matrix, atol=1e-9)
        self.assertArrayAlmostEqual(XZXZ_pulse._filter_function,
                                    XZXZ_pulse_ext._filter_function, atol=1e-8)

        XZXZ_pulse_ext = ff.extend([
            (XZ_pulse, (0, 1),
             {i: i + 'II' for i in XZ_pulse.n_oper_identifiers}),
            (XZ_pulse, (2, 3),
             {i: 'II' + i for i in XZ_pulse.n_oper_identifiers})
        ], cache_diagonalization=False)
        self.assertEqual(XZXZ_pulse, XZXZ_pulse_ext)
        self.assertArrayAlmostEqual(XZXZ_pulse._total_propagator,
                                    XZXZ_pulse_ext._total_propagator,
                                    atol=1e-10)

        # Test merging with overlapping qubit ranges
        XXZZ_pulse_ext = ff.extend([
            (XZ_pulse, (0, 2),
             {i: i[0] + 'I' + i[1] + 'I'
              for i in XZ_pulse.n_oper_identifiers}),
            (XZ_pulse, (1, 3),
             {i: 'I' + i[0] + 'I' + i[1]
              for i in XZ_pulse.n_oper_identifiers}),
        ])
        self.assertEqual(XXZZ_pulse, XXZZ_pulse_ext)
        self.assertCorrectDiagonalization(XXZZ_pulse_ext, atol=1e-14)
        self.assertArrayAlmostEqual(XXZZ_pulse._propagators,
                                    XXZZ_pulse_ext._propagators, atol=1e-10)
        self.assertArrayAlmostEqual(XXZZ_pulse._control_matrix,
                                    XXZZ_pulse_ext._control_matrix, atol=1e-10)
        self.assertArrayAlmostEqual(XXZZ_pulse._filter_function,
                                    XXZZ_pulse_ext._filter_function, atol=1e-8)
Esempio n. 4
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')