Exemple #1
0
    def test_density(self):

        rho = DensityOperator(np.eye(6) / 6.0, (2, 3))
        rhosmall = rho.partial_trace([1])

        self.assertEqual(rhosmall.dimension, (2, ))
        self.assertTrue(np.all(np.isclose(rhosmall.matrix, np.eye(2) / 2)))

        with self.assertRaises(ValueError):
            DensityOperator(np.array([[0, 1], [1, 0]]))

        with self.assertRaises(ValueError):
            DensityOperator(np.array([[1, 1], [0, 1]]))

        rho = DensityOperator.from_vectors(0.5, [1, 0, 0])

        self.assertTrue(np.all(rho.matrix == np.ones((2, 2)) * 0.5))

        rho = DensityOperator.from_vectors(0.5, [0, 1, 0], 0.5)

        self.assertTrue(
            np.all(
                np.isclose(rho.matrix, np.array([[0.5, -0.25j], [0.25j,
                                                                 0.5]]))))
Exemple #2
0
    def get_starting_state(self):
        """Return the starting quantum state for the system

        Build the starting quantum state for the system as a coherently 
        polarized muon + a thermal density matrix (using only the Zeeman 
        terms) for every other spin for the current magnetic field,
        temperature, and muon polarization axis.

        Returns:
            DensityOperator -- The starting density matrix
        """

        if self._rho0 is None:
            T = self._T
            muon_axis = self._mupol

            mu_i = self.spin_system.muon_index
            rhos = []

            for i, s in enumerate(self.spin_system.spins):
                I = self.spin_system.I(i)
                if i == mu_i:
                    r = DensityOperator.from_vectors(I, muon_axis, 0)
                else:
                    # Get the Zeeman Hamiltonian for this field
                    Sz = SpinOperator.from_axes(I, 'z')
                    E = np.diag(
                        Sz.matrix) * self.spin_system.gamma(i) * self.B * 1e6
                    if T > 0:
                        Z = np.exp(-cnst.h * E / (cnst.k * T))
                    else:
                        Z = np.where(E == np.amin(E), 1.0, 0.0)
                    if np.sum(Z) > 0:
                        Z /= np.sum(Z)
                    else:
                        Z = np.ones(len(E)) / len(E)
                    r = DensityOperator(np.diag(Z))

                rhos.append(r)

            self._rho0 = rhos[0]
            for r in rhos[1:]:
                self._rho0 = self._rho0.kron(r)

        return self._rho0
Exemple #3
0
    def evolve(self, rho0, times, operators=[]):
        """Time evolution of a state under this Lindbladian

        Perform an evolution of a state described by a DensityOperator under
        this Lindbladian and return either a sequence of DensityOperators or
        a sequence of expectation values for given SpinOperators.

        Arguments:
            rho0 {DensityOperator} -- Initial state
            times {ndarray} -- Times to compute the evolution for, in microseconds

        Keyword Arguments:
            operators {[SpinOperator]} -- List of SpinOperators to compute the
                                          expectation values of at each step.
                                          If omitted, the states' density 
                                          matrices will be returned instead
                                           (default: {[]})

        Returns:
            [DensityOperator | ndarray] -- DensityOperators or expectation values

        Raises:
            TypeError -- Invalid operators
            ValueError -- Invalid values of times or operators
            RuntimeError -- Hamiltonian is not hermitian
        """

        if not isinstance(rho0, DensityOperator):
            raise TypeError('rho0 must be a valid DensityOperator')

        times = np.array(times)

        if len(times.shape) != 1:
            raise ValueError(
                'times must be an array of values in microseconds')

        if isinstance(operators, SpinOperator):
            operators = [operators]
        if not all([isinstance(o, SpinOperator) for o in operators]):
            raise ValueError('operators must be a SpinOperator or a list'
                             ' of SpinOperator objects')

        dim = rho0.dimension
        if self.dimension != dim * 2:
            raise ValueError('Incompatible rho0 dimension')

        if any([self.dimension != o.dimension * 2 for o in operators]):
            raise ValueError('Incompatible measure operator dimension')

        # Start by building the matrix
        L = self.matrix

        # Diagonalize it
        evals, revecs = np.linalg.eig(L)

        # Vec-ing the density matrix
        rho0 = rho0.matrix.reshape((-1, ))
        rho0 = np.linalg.solve(revecs, rho0)
        # And the operators
        operatorsT = np.array(
            [np.dot(o.matrix.T.reshape((-1, )), revecs) for o in operators])

        rho = np.exp(
            2.0 * np.pi * evals[None, :] * times[:, None]) * rho0[None, :]

        if len(operators) > 0:
            # Expectation values
            result = np.sum(operatorsT[None, :, :] * rho[:, None, :], axis=-1)
        else:
            # Density matrices
            result = [DensityOperator(np.dot(revecs, r), dim) for r in rho]

        return result
Exemple #4
0
    def evolve(self, rho0, times, operators=[]):
        """Time evolution of a state under this Hamiltonian

        Perform an evolution of a state described by a DensityOperator under
        this Hamiltonian and return either a sequence of DensityOperators or
        a sequence of expectation values for given SpinOperators.

        Arguments:
            rho0 {DensityOperator} -- Initial state
            times {ndarray} -- Times to compute the evolution for, in microseconds

        Keyword Arguments:
            operators {[SpinOperator]} -- List of SpinOperators to compute the
                                          expectation values of at each step.
                                          If omitted, the states' density 
                                          matrices will be returned instead
                                           (default: {[]})

        Returns:
            [DensityOperator | ndarray] -- DensityOperators or expectation values

        Raises:
            TypeError -- Invalid operators
            ValueError -- Invalid values of times or operators
            RuntimeError -- Hamiltonian is not hermitian
        """

        if not isinstance(rho0, DensityOperator):
            raise TypeError('rho0 must be a valid DensityOperator')

        times = np.array(times)

        if len(times.shape) != 1:
            raise ValueError(
                'times must be an array of values in microseconds')

        if isinstance(operators, SpinOperator):
            operators = [operators]
        if not all([isinstance(o, SpinOperator) for o in operators]):
            raise ValueError('operators must be a SpinOperator or a list'
                             ' of SpinOperator objects')

        # Start by building the matrix
        H = self.matrix

        # Sanity check - should never happen
        if not np.all(H == H.T.conj()):
            raise RuntimeError('Hamiltonian is not hermitian')

        # Diagonalize it
        evals, evecs = np.linalg.eigh(H)

        # Turn the density matrix in the right basis
        dim = rho0.dimension
        rho0 = rho0.basis_change(evecs).matrix

        # Same for operators
        operatorsT = np.array(
            [o.basis_change(evecs).matrix.T for o in operators])

        # Matrix of evolution operators
        ll = -2.0j * np.pi * (evals[:, None] - evals[None, :])
        rho = np.exp(ll[None, :, :] * times[:, None, None]) * rho0[None, :, :]

        # Now, return values
        if len(operators) > 0:
            # Actually compute expectation values
            result = np.sum(rho[:, None, :, :] * operatorsT[None, :, :, :],
                            axis=(2, 3))
        else:
            # Just return density matrices
            sceve = evecs.T.conj()
            result = [DensityOperator(r, dim).basis_change(sceve) for r in rho]

        return result