Esempio n. 1
0
    def test_control_matrix(self):
        """Test control matrix for traceless and non-traceless bases"""

        n_opers = testutil.rand_herm(3, 4)
        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 = copy(base_pulse)
                pulse.n_opers = n_ops
                pulse.basis = base

                R = pulse.get_control_matrix(omega)

                if i == 0 and j == 0:
                    # base not traceless, nopers not traceless
                    self.assertTrue((R[:, 0] != 0).all())
                elif i == 0 and j == 1:
                    # base not traceless, nopers traceless
                    self.assertTrue((R[:, 0] != 0).all())
                elif i == 1 and j == 0:
                    # base traceless, nopers not traceless
                    self.assertTrue((R[:, 0] != 0).all())
                elif i == 1 and j == 1:
                    # base traceless, nopers traceless
                    self.assertTrue(np.allclose(R[:, 0], 0))
Esempio n. 2
0
    def test_basis_generation_from_partial_pauli(self):
        """"Generate complete basis from partial elements of a Pauli basis"""
        # Do 100 test runs with random elements from a Pauli basis in (2 ... 8)
        # dimensions
        for _ in range(50):
            n = rng.randint(1, 4)
            d = 2**n
            b = ff.Basis.pauli(n)
            inds = [i for i in range(d**2)]
            tup = tuple(
                inds.pop(rng.randint(0, len(inds)))
                for _ in range(rng.randint(1, d**2)))
            elems = b[tup, ...]
            basis = ff.Basis(elems)
            self.assertTrue(basis.isorthonorm)
            self.assertTrue(basis.isherm)
            self.assertTrue(basis.istraceless)
            self.assertTrue(basis.iscomplete)
            self.assertTrue(all(elem in basis for elem in elems))

            with self.assertWarns(UserWarning):
                b = [basis[0], 1j * basis[1]]
                ff.Basis(b)

            with self.assertRaises(ValueError):
                b = [basis[0], basis[0] + basis[1]]
                ff.Basis(b)
Esempio n. 3
0
    def test_constructor(self):
        """Test if can create basis from qutip objects."""

        elems_qutip = [qutip.sigmay(), qutip.qeye(2).data]
        elems_np = [qutip.sigmay().full(), qutip.qeye(2).full()]

        basis_qutip = ff.Basis(elems_qutip)
        basis_np = ff.Basis(elems_np)

        self.assertArrayEqual(basis_qutip, basis_np)
Esempio n. 4
0
    def test_basis_generation_from_partial_random(self):
        """"Generate complete basis from partial elements of a random basis"""
        # Do 25 test runs with random elements from a random basis in
        # (2 ... 8) dimensions
        for _ in range(25):
            d = rng.randint(2, 7)
            # Get a random traceless hermitian operator
            oper = testutil.rand_herm_traceless(d)
            # ... and build a basis from it
            b = ff.Basis(oper)
            self.assertTrue(b.isorthonorm)
            self.assertTrue(b.isherm)
            self.assertTrue(b.istraceless)
            self.assertTrue(b.iscomplete)
            # 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(rng.randint(0, len(inds)))
                for _ in range(rng.randint(1, d**2)))
            elems = b[tup, ...]
            basis = ff.Basis(elems)
            self.assertTrue(basis.isorthonorm)
            self.assertTrue(basis.isherm)
            self.assertTrue(basis.istraceless)
            self.assertTrue(basis.iscomplete)
            self.assertTrue(all(elem in basis for elem in elems))

        # Test runs with non-traceless opers
        for _ in range(25):
            d = rng.randint(2, 7)
            # Get a random hermitian operator
            oper = testutil.rand_herm(d)
            # ... and build a basis from it
            b = ff.Basis(oper)
            self.assertTrue(b.isorthonorm)
            self.assertTrue(b.isherm)
            self.assertFalse(b.istraceless)
            self.assertTrue(b.iscomplete)
            # 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(rng.randint(0, len(inds)))
                for _ in range(rng.randint(1, d**2)))
            elems = b[tup, ...]
            basis = ff.Basis(elems)
            self.assertTrue(basis.isorthonorm)
            self.assertTrue(basis.isherm)
            self.assertFalse(basis.istraceless)
            self.assertTrue(basis.iscomplete)
            self.assertTrue(all(elem in basis for elem in elems))
Esempio n. 5
0
    def test_basis_constructor(self):
        """Test the constructor for several failure modes"""

        # Constructing from given elements should check for __getitem__
        with self.assertRaises(TypeError):
            _ = ff.Basis(1)

        # All elements should be either sparse, Qobj, or ndarray
        elems = [
            ff.util.paulis[1],
            COO.from_numpy(ff.util.paulis[3]), [[0, 1], [1, 0]]
        ]
        with self.assertRaises(TypeError):
            _ = ff.Basis(elems)

        # Too many elements
        with self.assertRaises(ValueError):
            _ = ff.Basis(rng.standard_normal((5, 2, 2)))

        # Properly normalized
        self.assertEqual(ff.Basis.pauli(1), ff.Basis(ff.util.paulis))

        # Non traceless elems but traceless basis requested
        with self.assertRaises(ValueError):
            _ = ff.Basis(np.ones((2, 2)), traceless=True)

        # Calling with only the identity should work with traceless true or
        # false
        self.assertEqual(ff.Basis(np.eye(2), traceless=False),
                         ff.Basis(np.eye(2), traceless=True))

        # Constructing a basis from a basis should work
        _ = ff.Basis(ff.Basis.ggm(2)[1:])
Esempio n. 6
0
    def test_infidelity_cnot(self):
        """Compare infidelity to monte carlo results"""
        c_opers = testutil.subspace_opers
        n_opers = c_opers
        c_coeffs, n_coeffs = testutil.c_coeffs, testutil.n_coeffs
        dt = testutil.dt
        infid_MC = testutil.cnot_infid_fast
        A = testutil.A

        # Basis for qubit subspace
        qubit_subspace_basis = ff.Basis(
            [np.pad(b, 1, 'constant') for b in ff.Basis.pauli(2)],
            skip_check=True,
            btype='Pauli')
        complete_basis = ff.Basis(qubit_subspace_basis,
                                  traceless=False,
                                  btype='Pauli')

        identifiers = ['eps_12', 'eps_23', 'eps_34', 'b_12', 'b_23', 'b_34']
        H_c = list(zip(c_opers, c_coeffs, identifiers))
        H_n = list(zip(n_opers, n_coeffs, identifiers))
        cnot = ff.PulseSequence(H_c, H_n, dt, basis=qubit_subspace_basis)
        cnot_full = ff.PulseSequence(H_c, H_n, dt, basis=complete_basis)

        # Manually set dimension of pulse as the dimension of the computational
        # subspace
        cnot.d = 4
        T = dt.sum()

        for f_min, A, alpha, MC, rtol in zip((1 / T, 1e-2 / T), A, (0.0, 0.7),
                                             infid_MC, (0.04, 0.02)):

            omega = np.geomspace(f_min, 1e2, 250) * 2 * np.pi
            S_t, omega_t = ff.util.symmetrize_spectrum(A / omega**alpha, omega)

            infid, xi = ff.infidelity(cnot,
                                      S_t,
                                      omega_t,
                                      identifiers[:3],
                                      return_smallness=True)

            U = ff.error_transfer_matrix(cnot_full, S_t, omega_t,
                                         identifiers[:3])
            infid_P = np.trace(U[:, :16, :16], axis1=1, axis2=2).real / 4**2

            print(np.abs(1 - (infid.sum() / MC)))
            print(np.abs(1 - (infid_P.sum() / MC)))
            self.assertLessEqual(np.abs(1 - (infid.sum() / MC)), rtol)
            self.assertLessEqual(np.abs(1 - (infid_P.sum() / MC)), rtol)
            self.assertLessEqual(infid.sum(), xi**2 / 4)
Esempio n. 7
0
    def test_infidelity_cnot(self):
        """Compare infidelity to monte carlo results"""
        c_opers = testutil.subspace_opers
        n_opers = c_opers
        c_coeffs, n_coeffs = testutil.c_coeffs, testutil.n_coeffs
        dt = testutil.dt
        infid_MC = testutil.cnot_infid_fast
        A = testutil.A

        # Basis for qubit subspace
        qubit_subspace_basis = ff.Basis(
            [np.pad(b, 1, 'constant') for b in ff.Basis.pauli(2)[1:]],
            skip_check=True,
            btype='Pauli')
        complete_basis = ff.Basis(qubit_subspace_basis,
                                  traceless=False,
                                  btype='Pauli')

        identifiers = ['eps_12', 'eps_23', 'eps_34', 'b_12', 'b_23', 'b_34']
        H_c = list(zip(c_opers, c_coeffs, identifiers))
        H_n = list(zip(n_opers, n_coeffs, identifiers))
        cnot = ff.PulseSequence(H_c, H_n, dt, basis=qubit_subspace_basis)
        cnot_full = ff.PulseSequence(H_c, H_n, dt, basis=complete_basis)

        # Manually set dimension of pulse as the dimension of the computational
        # subspace
        cnot.d = 4
        f_min = 1 / cnot.tau
        omega = np.geomspace(f_min, 1e2, 250)

        for A, alpha, MC in zip(A, (0.0, 0.7), infid_MC):
            S = A / omega**alpha

            infid, xi = ff.infidelity(cnot,
                                      S,
                                      omega,
                                      identifiers[:3],
                                      return_smallness=True)

            K = numeric.calculate_cumulant_function(cnot_full, S, omega,
                                                    identifiers[:3])
            infid_P = -np.trace(K[:, :16, :16], axis1=1, axis2=2).real / 4**2

            self.assertLessEqual(np.abs(1 - (infid.sum() / MC)), 0.10)
            self.assertLessEqual(np.abs(1 - (infid_P.sum() / MC)), 0.10)
            self.assertLessEqual(infid.sum(), xi**2 / 4)
Esempio n. 8
0
    def test_basis_properties(self):
        """Basis orthonormal and of correct dimensions"""
        d = rng.randint(2, 17)
        n = rng.randint(1, 5)

        ggm_basis = ff.Basis.ggm(d)
        pauli_basis = ff.Basis.pauli(n)
        custom_basis = ff.Basis(testutil.rand_herm(d), traceless=False)

        btypes = ('Pauli', 'GGM', 'Custom')
        bases = (pauli_basis, ggm_basis, custom_basis)
        for btype, base in zip(btypes, bases):
            base.tidyup(eps_scale=0)
            self.assertTrue(base == base)
            self.assertFalse(base == ff.Basis.ggm(d + 1))
            self.assertEqual(btype, base.btype)
            if not btype == 'Pauli':
                self.assertEqual(d, base.d)
                # Check if __contains__ works as expected
                self.assertTrue(base[rng.randint(0, d**2)] in base)
            else:
                self.assertEqual(2**n, base.d)
                # Check if __contains__ works as expected
                self.assertTrue(base[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))
            self.assertTrue(base.isorthonorm)
            self.assertTrue(base.isherm)
            # Check if basis spans the whole space and all elems are traceless
            if not btype == 'Custom':
                self.assertTrue(base.istraceless)
            else:
                self.assertFalse(base.istraceless)

            self.assertTrue(base.iscomplete)
            # Check sparse representation
            self.assertArrayEqual(base.sparse.todense(), base)
            # Test sparse cache
            self.assertArrayEqual(base.sparse.todense(), base)

            if base.d < 8:
                # Test very resource intense
                ref = np.einsum('iab,jbc,kcd,lda', *(base, ) * 4)
                self.assertArrayAlmostEqual(base.four_element_traces.todense(),
                                            ref,
                                            atol=1e-16)

                # Test setter
                base._four_element_traces = None
                base.four_element_traces = ref
                self.assertArrayEqual(base.four_element_traces, ref)

            base._print_checks()

        basis = ff.util.paulis[1].view(ff.Basis)
        self.assertTrue(basis.isorthonorm)
        self.assertArrayEqual(basis.T, basis.view(np.ndarray).T)
Esempio n. 9
0
    def test_filter_functions(self):

        # Basis for qubit subspace
        qubit_subspace_basis = ff.Basis(
            [np.pad(b, 1, 'constant') for b in ff.Basis.pauli(2)],
            skip_check=True,
            btype='Pauli')

        c_opers = ff_testutil.subspace_opers
        n_opers = c_opers
        c_coeffs, n_coeffs = ff_testutil.c_coeffs, ff_testutil.n_coeffs
        dt = ff_testutil.dt
        infid_MC = ff_testutil.cnot_infid_fast
        A = ff_testutil.A

        identifiers = ['eps_12', 'eps_23', 'eps_34', 'b_12', 'b_23', 'b_34']
        H_c = list(
            zip(c_opers[:3] + [c_opers[3] + 7 * c_opers[4] - c_opers[5]],
                c_coeffs[:3] + [c_coeffs[3]], identifiers[:4]))
        H_n = list(zip(n_opers[:3], n_coeffs[:3], identifiers[:3]))
        cnot = ff.PulseSequence(H_c, H_n, dt, basis=qubit_subspace_basis)

        T = dt.sum()
        omega = np.logspace(np.log10(1 / T), 2, 125)
        S_t, omega_t = ff.util.symmetrize_spectrum(A[0] / omega**0.0, omega)
        infid, xi = ff.infidelity(cnot,
                                  S_t,
                                  omega_t,
                                  identifiers[:3],
                                  return_smallness=True)
        # infid scaled with d = 6, but we actually have d = 4
        infid *= 1.5
        self.assertLessEqual(np.abs(1 - (infid.sum() / infid_MC[0])), .4)
        self.assertLessEqual(infid.sum(), xi**2 / 4)

        time_slot_comp_closed = SchroedingerSolver(
            h_drift=[OPERATORS['h_drift']] * len(dt),
            h_ctrl=OPERATORS['h_ctrl'],
            initial_state=OPERATORS['initial_state'],
            tau=list(dt),
            calculate_propagator_derivatives=True,
            exponential_method='spectral',
            is_skew_hermitian=True,
            transfer_function=id_tf,
            amplitude_function=exp_amp_func,
            filter_function_h_n=H_n,
            filter_function_basis=qubit_subspace_basis)
        time_slot_comp_closed.set_optimization_parameters(eps.T)

        ff_infid = OperatorFilterFunctionInfidelity(
            solver=time_slot_comp_closed,
            noise_power_spec_density=S_t,
            omega=omega_t)
        print(ff_infid.grad())
        np.testing.assert_array_almost_equal(infid, ff_infid.costs() * 1.5)
Esempio n. 10
0
    def test_basis_expansion_and_normalization(self):
        """Correct expansion of operators and normalization of bases"""
        for _ in range(10):
            d = rng.randint(2, 16)
            ggm_basis = ff.Basis.ggm(d)
            basis = ff.Basis(np.einsum('i,ijk->ijk', rng.standard_normal(d**2),
                                       ggm_basis),
                             skip_check=True)
            M = rng.standard_normal((d, d)) + 1j * rng.standard_normal((d, d))
            M -= np.trace(M) / d
            coeffs = ff.basis.expand(M, basis, normalized=False)
            self.assertArrayAlmostEqual(M, np.einsum('i,ijk', coeffs, basis))
            self.assertArrayAlmostEqual(ff.basis.expand(M, ggm_basis),
                                        ff.basis.ggm_expand(M),
                                        atol=1e-14)
            self.assertArrayAlmostEqual(ff.basis.ggm_expand(M),
                                        ff.basis.ggm_expand(M, traceless=True),
                                        atol=1e-14)

            n = rng.randint(1, 50)
            M = (rng.standard_normal((n, d, d)) + 1j * rng.standard_normal(
                (n, d, d)))
            coeffs = ff.basis.expand(M, basis, normalized=False)
            self.assertArrayAlmostEqual(
                M, np.einsum('li,ijk->ljk', coeffs, basis))
            self.assertArrayAlmostEqual(ff.basis.expand(M, ggm_basis),
                                        ff.basis.ggm_expand(M),
                                        atol=1e-14)

            # Argument to ggm_expand not square in last two dimensions
            with self.assertRaises(ValueError):
                ff.basis.ggm_expand(basis[..., 0])

            self.assertTrue(ff.basis.normalize(basis).isorthonorm)

            # Basis method and function should give the same
            normalized = ff.basis.normalize(basis)
            basis.normalize()
            self.assertEqual(normalized, basis)

            # normalize single element
            elem = basis[1]
            normalized = ff.basis.normalize(elem)
            elem.normalize()
            self.assertEqual(normalized, elem)

            # Not matrix or sequence of matrices
            with self.assertRaises(ValueError):
                ff.basis.normalize(basis[0, 0])
Esempio n. 11
0
 def test_basis_generation_from_partial_ggm(self):
     """"Generate complete basis from partial elements of a GGM basis"""
     # Do 100 test runs with random elements from a GGM basis in (2 ... 8)
     # dimensions
     for _ in range(50):
         d = rng.randint(2, 9)
         b = ff.Basis.ggm(d)
         inds = [i for i in range(d**2)]
         tup = tuple(
             inds.pop(rng.randint(0, len(inds)))
             for _ in range(rng.randint(1, d**2)))
         elems = b[tup, ...]
         basis = ff.Basis(elems)
         self.assertTrue(basis.isorthonorm)
         self.assertTrue(basis.isherm)
         self.assertTrue(basis.istraceless)
         self.assertTrue(basis.iscomplete)
         self.assertTrue(all(elem in basis for elem in elems))
Esempio n. 12
0
    def test_filter_functions(self):
        """Filter functions equal for different bases"""
        # Set up random Hamiltonian
        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(base_pulse.n_opers)
        bases = (pauli_basis, ggm_basis, from_random_basis)

        # 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)
Esempio n. 13
0
    def test_pulse_sequence_attributes(self):
        """Test attributes of single instance"""
        X, Y, Z = util.paulis[1:]
        n_dt = rng.randint(1, 10)

        # trivial case
        A = ff.PulseSequence([[X, rng.standard_normal(n_dt), 'X']],
                             [[Z, rng.standard_normal(n_dt), 'Z']],
                             np.abs(rng.standard_normal(n_dt)))
        self.assertFalse(A == 1)
        self.assertTrue(A != 1)

        # different number of time steps
        B = ff.PulseSequence([[X, rng.standard_normal(n_dt+1), 'X']],
                             [[Z, rng.standard_normal(n_dt+1), 'Z']],
                             np.abs(rng.standard_normal(n_dt+1)))
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different time steps
        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(rng.standard_normal(n_dt))
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different control opers
        B = ff.PulseSequence(
            list(zip([Y], A.c_coeffs, A.c_oper_identifiers)),
            list(zip(A.n_opers, A.n_coeffs, A.n_oper_identifiers)),
            A.dt
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different control coeffs
        B = ff.PulseSequence(
            list(zip(A.c_opers, [rng.standard_normal(n_dt)],
                     A.c_oper_identifiers)),
            list(zip(A.n_opers, A.n_coeffs, A.n_oper_identifiers)),
            A.dt
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different noise opers
        B = ff.PulseSequence(
            list(zip(A.c_opers, A.c_coeffs, A.c_oper_identifiers)),
            list(zip([Y], A.n_coeffs, A.n_oper_identifiers)),
            A.dt
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different noise coeffs
        B = ff.PulseSequence(
            list(zip(A.c_opers, A.c_coeffs, A.c_oper_identifiers)),
            list(zip(A.n_opers, [rng.standard_normal(n_dt)],
                     A.n_oper_identifiers)),
            A.dt
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different control oper identifiers
        B = ff.PulseSequence(
            list(zip(A.c_opers, A.c_coeffs, ['foobar'])),
            list(zip(A.n_opers, A.n_coeffs, A.n_oper_identifiers)),
            A.dt
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different noise oper identifiers
        B = ff.PulseSequence(
            list(zip(A.c_opers, A.c_coeffs, A.c_oper_identifiers)),
            list(zip(A.n_opers, A.n_coeffs, ['foobar'])),
            A.dt
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # different bases
        elem = testutil.rand_herm_traceless(2)
        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)),
            A.dt,
            ff.Basis(elem)
        )
        self.assertFalse(A == B)
        self.assertTrue(A != B)

        # Test sparse operators for whatever reason
        A = ff.PulseSequence([[util.paulis[1], [1]]],
                             [[sparse.COO.from_numpy(util.paulis[2]), [2]]],
                             [3])
        B = ff.PulseSequence([[sparse.COO.from_numpy(util.paulis[1]), [1]]],
                             [[util.paulis[2], [2]]],
                             [3])
        self.assertEqual(A, B)

        # Test for attributes
        for attr in A.__dict__.keys():
            if not (attr.startswith('_') or '_' + attr in A.__dict__.keys()):
                # not a cached attribute
                with self.assertRaises(AttributeError):
                    _ = A.is_cached(attr)
            else:
                # set mock attribute at random
                if rng.randint(0, 2):
                    setattr(A, attr, 'foo')
                    assertion = self.assertTrue
                else:
                    setattr(A, attr, None)
                    assertion = self.assertFalse

                assertion(A.is_cached(attr))

        # Diagonalization attributes
        A.diagonalize()
        self.assertIsNotNone(A.eigvals)
        self.assertIsNotNone(A.eigvecs)
        self.assertIsNotNone(A.propagators)

        A.cleanup('conservative')
        self.assertIsNotNone(A.eigvals)
        A.cleanup('conservative')
        self.assertIsNotNone(A.eigvecs)
        A.cleanup('conservative')
        self.assertIsNotNone(A.propagators)

        aliases = {'eigenvalues': '_eigvals',
                   'eigenvectors': '_eigvecs',
                   'total propagator': '_total_propagator',
                   'total propagator liouville': '_total_propagator_liouville',
                   'frequencies': '_omega',
                   'total phases': '_total_phases',
                   'filter function': '_filter_function',
                   'fidelity filter function': '_filter_function',
                   'generalized filter function': '_filter_function_gen',
                   'pulse correlation filter function': '_filter_function_pc',
                   'fidelity pulse correlation filter function': '_filter_function_pc',
                   'generalized pulse correlation filter function': '_filter_function_pc_gen',
                   'control matrix': '_control_matrix',
                   'pulse correlation control matrix': '_control_matrix_pc'}

        for alias, attr in aliases.items():
            # set mock attribute at random
            if rng.randint(0, 2):
                setattr(A, attr, 'foo')
                assertion = self.assertTrue
            else:
                setattr(A, attr, None)
                assertion = self.assertFalse

            assertion(A.is_cached(alias))
            assertion(A.is_cached(alias.upper()))
            assertion(A.is_cached(alias.replace(' ', '_')))

        A.cleanup('all')

        # Test cleanup
        C = ff.concatenate((A, A), calc_pulse_correlation_FF=True,
                           which='generalized',
                           omega=util.get_sample_frequencies(A))
        C.diagonalize()
        attrs = ['_eigvals', '_eigvecs', '_propagators']
        for attr in attrs:
            self.assertIsNotNone(getattr(C, attr))

        C.cleanup()
        for attr in attrs:
            self.assertIsNone(getattr(C, attr))

        C.diagonalize()
        C.cache_control_matrix(A.omega)
        attrs.extend(['_control_matrix', '_total_phases', '_total_propagator',
                      '_total_propagator_liouville'])
        for attr in attrs:
            self.assertIsNotNone(getattr(C, attr))

        C.cleanup('greedy')
        for attr in attrs:
            self.assertIsNone(getattr(C, attr))

        C.cache_filter_function(A.omega, which='generalized')
        for attr in attrs + ['omega', '_filter_function_gen',
                             '_filter_function_pc_gen']:
            self.assertIsNotNone(getattr(C, attr))

        C = ff.concatenate((A, A), calc_pulse_correlation_FF=True,
                           which='fidelity', omega=A.omega)
        C.diagonalize()
        C.cache_filter_function(A.omega, which='fidelity')
        attrs.extend(['omega', '_filter_function', '_filter_function_pc'])
        for attr in attrs:
            self.assertIsNotNone(getattr(C, attr))

        C.cleanup('all')
        for attr in attrs + ['_filter_function_gen',
                             '_filter_function_pc_gen']:
            self.assertIsNone(getattr(C, attr))

        C.cache_filter_function(A.omega, which='fidelity')
        C.cleanup('frequency dependent')
        freq_attrs = {'omega', '_control_matrix', '_filter_function',
                      '_filter_function_gen', '_filter_function_pc',
                      '_filter_function_pc_gen', '_total_phases'}
        for attr in freq_attrs:
            self.assertIsNone(getattr(C, attr))

        for attr in set(attrs).difference(freq_attrs):
            self.assertIsNotNone(getattr(C, attr))
Esempio n. 14
0
    def test_basis_constructor(self):
        """Test the constructor for several failure modes"""
        # Constructing from given elements should check for __getitem__
        with self.assertRaises(TypeError):
            _ = ff.Basis(1)

        # All elements should be either sparse, Qobj, or ndarray
        elems = [
            util.paulis[1],
            COO.from_numpy(util.paulis[3]), [[0, 1], [1, 0]]
        ]
        with self.assertRaises(TypeError):
            _ = ff.Basis(elems)

        # Too many elements
        with self.assertRaises(ValueError):
            _ = ff.Basis(rng.standard_normal((5, 2, 2)))

        # Non traceless elems but traceless basis requested
        with self.assertRaises(ValueError):
            _ = ff.Basis.from_partial(np.ones((2, 2)), traceless=True)

        # Incorrect number of labels for default constructor
        with self.assertRaises(ValueError):
            _ = ff.Basis(util.paulis, labels=['a', 'b', 'c'])

        # Incorrect number of labels for from_partial constructor
        with self.assertRaises(ValueError):
            _ = ff.Basis.from_partial(util.paulis[:2], labels=['a', 'b', 'c'])

        # from_partial constructor should move identity label to the front
        basis = ff.Basis.from_partial([util.paulis[1], util.paulis[0]],
                                      labels=['x', 'i'])
        self.assertEqual(basis.labels[:2], ['i', 'x'])
        self.assertEqual(basis.labels[2:], ['$C_{2}$', '$C_{3}$'])

        # from_partial constructor should copy labels if it can
        partial_basis = ff.Basis.pauli(1)[[1, 3]]
        partial_basis.labels = [
            partial_basis.labels[1], partial_basis.labels[3]
        ]
        basis = ff.Basis.from_partial(partial_basis)
        self.assertEqual(basis.labels[:2], partial_basis.labels)
        self.assertEqual(basis.labels[2:], ['$C_{2}$', '$C_{3}$'])

        # Default constructor should return 3d array also for single 2d element
        basis = ff.Basis(rng.standard_normal((2, 2)))
        self.assertEqual(basis.shape, (1, 2, 2))

        # from_partial constructor should return same basis for 2d or 3d input
        elems = testutil.rand_herm(3)
        basis1 = ff.Basis.from_partial(elems, labels=['weif'])
        basis2 = ff.Basis.from_partial(elems.squeeze(), labels=['weif'])
        self.assertEqual(basis1, basis2)

        # Calling with only the identity should work with traceless true or false
        self.assertEqual(ff.Basis(np.eye(2), traceless=False),
                         ff.Basis(np.eye(2), traceless=True))

        # Constructing a basis from a basis should work
        _ = ff.Basis(ff.Basis.ggm(2)[1:])

        # Constructing should not change the elements
        elems = rng.standard_normal((6, 3, 3))
        basis = ff.Basis(elems)
        self.assertArrayEqual(elems, basis)
Esempio n. 15
0
    def test_basis_expansion_and_normalization(self):
        """Correct expansion of operators and normalization of bases"""
        # dtype
        b = ff.Basis.ggm(3)
        r = ff.basis.expand(rng.standard_normal((3, 3)), b, hermitian=False)
        self.assertTrue(r.dtype == 'complex128')
        r = ff.basis.expand(testutil.rand_herm(3), b, hermitian=True)
        self.assertTrue(r.dtype == 'float64')
        b._isherm = False
        r = ff.basis.expand(testutil.rand_herm(3), b, hermitian=True)
        self.assertTrue(r.dtype == 'complex128')

        r = ff.basis.ggm_expand(testutil.rand_herm(3), hermitian=True)
        self.assertTrue(r.dtype == 'float64')
        r = ff.basis.ggm_expand(rng.standard_normal((3, 3)), hermitian=False)
        self.assertTrue(r.dtype == 'complex128')

        for _ in range(10):
            d = rng.integers(2, 16)
            ggm_basis = ff.Basis.ggm(d)
            basis = ff.Basis(
                np.einsum('i,ijk->ijk', rng.standard_normal(d**2), ggm_basis))
            M = rng.standard_normal((d, d)) + 1j * rng.standard_normal((d, d))
            M -= np.trace(M) / d
            coeffs = ff.basis.expand(M, basis, normalized=False)
            self.assertArrayAlmostEqual(M, np.einsum('i,ijk', coeffs, basis))
            self.assertArrayAlmostEqual(ff.basis.expand(M, ggm_basis),
                                        ff.basis.ggm_expand(M),
                                        atol=1e-14)
            self.assertArrayAlmostEqual(ff.basis.ggm_expand(M),
                                        ff.basis.ggm_expand(M, traceless=True),
                                        atol=1e-14)

            n = rng.integers(1, 50)
            M = rng.standard_normal((n, d, d)) + 1j * rng.standard_normal(
                (n, d, d))
            coeffs = ff.basis.expand(M, basis, normalized=False)
            self.assertArrayAlmostEqual(
                M, np.einsum('li,ijk->ljk', coeffs, basis))
            self.assertArrayAlmostEqual(ff.basis.expand(M, ggm_basis),
                                        ff.basis.ggm_expand(M),
                                        atol=1e-14)

            # Argument to ggm_expand not square in last two dimensions
            with self.assertRaises(ValueError):
                ff.basis.ggm_expand(basis[..., 0])

            self.assertTrue(ff.basis.normalize(basis).isorthonorm)

            # Basis method and function should give the same
            normalized = ff.basis.normalize(basis)
            basis.normalize()
            self.assertEqual(normalized, basis)

            # normalize single element
            elem = basis[1]
            normalized = ff.basis.normalize(elem)
            elem.normalize()
            self.assertEqual(normalized, elem)

            # Not matrix or sequence of matrices
            with self.assertRaises(ValueError):
                ff.basis.normalize(basis[0, 0])

            # Test copy
            arr = rng.standard_normal((3, 2, 2))
            basis = ff.Basis(arr)
            normalized = basis.normalize(copy=True)
            self.assertIsNot(normalized, basis)
            self.assertFalse(np.array_equal(normalized, basis))
            basis.normalize()
            self.assertArrayEqual(normalized, basis)