Source code for mpnum.povm.localpovm

# encoding: utf-8
"""An informationally complete d-level POVM.

The POVM simplifies to measuring Paulis matrices in the case of
qubits.

"""

from __future__ import absolute_import, division, print_function

import numpy as np
from numpy.testing import assert_almost_equal

from six.moves import range, zip


[docs]class POVM(object): """Represent a Positive Operator-Valued Measure (POVM). """ def __init__(self, elements, info_complete=False, pinv=np.linalg.pinv): """Create a POVM. The caller must supply whether the POVM elements are informationally complete. :param elements: Sequence of POVM elements as :class:`numpy.ndarray`\ s of square shape. :param info_complete: Is the POVM informationally complete (IC) (default False) :param pinv: Pseudo-inverse function to be used (default numpy.linalg.pinv) """ self._elements = np.asarray(elements) self._info_complete = info_complete self._pinv = pinv def __len__(self): return len(self._elements) def __iter__(self): return iter(self._elements) def __getitem__(self, index): return self._elements[index]
[docs] @classmethod def from_vectors(cls, vecs, info_complete=False): """Generates a POVM consisting of rank 1 projectors based on the corresponding vectors. :param vecs: Iterable of np.ndarray with ndim=1 representing the vectors for the POVM :param info_complete: Is the POVM informationally complete (default False) :returns: """ povm_elems = np.array([np.outer(vec, vec.conj()) for vec in vecs]) return cls(povm_elems, info_complete=info_complete)
@property def probability_map(self): """Map that takes a raveled density matrix to the POVM probabilities The following two return the same:: probab = np.array([ np.trace(np.dot(elem, rho)) for elem in a_povm ]) probab = np.dot(a_povm.probability_map, rho.ravel()) """ # tr(M rho) = \sum_ij M_ji rho_ij = \sum_ij (M^T)_ij rho_ij return self._elements.transpose((0, 2, 1)).reshape(len(self), -1) @property def linear_inversion_map(self): """Map that reconstructs a density matrix with linear inversion. Linear inversion is performed by taking the Moore--Penrose pseudoinverse of self.probability_map. """ return self._pinv(self.probability_map) @property def informationally_complete(self): return self._info_complete
[docs]def x_povm(dim): """The X POVM simplifies to measuring Pauli X eigenvectors for dim=2. :param dim: Dimension of the system :returns: POVM with generalized X measurments """ vectors = np.zeros([dim * (dim - 1), dim]) k = 0 for i in range(dim - 1): for j in range(i + 1, dim): vectors[k, i], vectors[k, j] = 1.0, 1.0 k += 1 vectors[k, i], vectors[k, j] = 1.0, -1.0 k += 1 vectors /= np.sqrt(2 * (dim - 1)) return POVM.from_vectors(vectors, info_complete=False)
[docs]def y_povm(dim): """The Y POVM simplifies to measuring Pauli Y eigenvectors for dim=2. :param dim: Dimension of the system :returns: POVM with generalized Y measurments """ vectors = np.zeros([dim * (dim - 1), dim], dtype=complex) k = 0 for i in range(dim - 1): for j in range(i + 1, dim): vectors[k, i], vectors[k, j] = 1.0, 1.0j k += 1 vectors[k, i], vectors[k, j] = 1.0, -1.0j k += 1 vectors /= np.sqrt(2 * (dim - 1)) return POVM.from_vectors(vectors, info_complete=False)
[docs]def z_povm(dim): """The Z POVM simplifies to measuring Pauli Z eigenvectors for dim=2. :param dim: Dimension of the system :returns: POVM with generalized Z measurments """ return POVM.from_vectors(np.eye(dim, dim), info_complete=False)
[docs]def pauli_parts(dim): """The POVMs used by :func:`pauli_povm` as a list For `dim > 3`, :func:`x_povm` and :func:`y_povm` are returned. For `dim = 2`, :func:`z_povm` is included as well. :param dim: Dimension of the system :returns: Tuple of :class:`POVMs <POVM>` """ assert dim > 1, "What do you mean by 1-dim. Pauli measurements?" if dim == 2: return (x_povm(dim), y_povm(dim), z_povm(dim)) else: return (x_povm(dim), y_povm(dim))
[docs]def pauli_povm(dim): """An informationally complete d-level POVM that simplifies to measuring Pauli matrices in the case d=2. :param dim: Dimension of the system :returns: :class:`POVM` with (generalized) Pauli measurments """ parts = pauli_parts(dim) return concat(parts, (1/len(parts),) * len(parts), info_complete=True)
[docs]def concat(povms, weights, info_complete=False): """Combines the POVMs given in `povms` according the weights given to a new POVM. :param povms: Iterable of POVM :param weights: Iterable of real numbers, should sum up to one :param info_complete: Is the resulting POVM informationally complete :returns: POVM """ assert_almost_equal(sum(weights), 1.0) elements = sum(([weight * elem for elem in povm] for povm, weight in zip(povms, weights)), []) return POVM(elements, info_complete=info_complete)