def linear_inv_state_estimate(results: List[ExperimentResult], qubits: List[int]) -> np.ndarray: """ Estimate a quantum state using linear inversion. This is the simplest state tomography post processing. To use this function, collect state tomography data with :py:func:`generate_state_tomography_experiment` and :py:func:`~pyquil.operator_estimation.measure_observables`. For more details on this post-processing technique, see https://en.wikipedia.org/wiki/Quantum_tomography#Linear_inversion or see section 3.4 of [WOOD] Initialization and characterization of open quantum systems C. Wood, PhD thesis from University of Waterloo, (2015). http://hdl.handle.net/10012/9557 :param results: A tomographically complete list of results. :param qubits: All qubits that were tomographized. This specifies the order in which qubits will be kron'ed together. :return: A point estimate of the quantum state rho. """ measurement_matrix = np.vstack([ vec(pauli2matrix(result.setting.out_operator, qubits=qubits)).T.conj() for result in results ]) expectations = np.array([result.expectation for result in results]) rho = pinv(measurement_matrix) @ expectations return unvec(rho)
def _grad_cost(A, n, estimate, eps=1e-6): """ Computes the gradient of the cost, leveraging the vectorized equation 6 of [PGD] given in the appendix. :param A: a matrix constructed from the input states and POVM elements (eq. A1) that aids in calculating the model probabilities p. :param n: vectorized form of the observed counts n_ij :param estimate: the current model Choi representation of an estimated process for which we compute the gradient. :return: Gradient of the cost of the estimate given the data, n """ p = A @ vec(estimate) # see appendix on "stalling" p = np.clip(p, a_min=eps, a_max=None) eta = n / p return unvec(-A.conj().T @ eta)