Created
May 17, 2016 08:24
-
-
Save cgranade/d20fcf3e9907eb26c7fc2f6a8d855918 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "# Proposed Semantics for Qobj.\\_\\_call\\_\\_ #" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "This Notebook describes proposed semantics for representing the actions of superoperators and operators on operators and states as *functions*. In particular, this will greatly simplify the syntax used to represent evolving a density operator under a quantum channel stored as a ``type=\"super\"`` Qobj." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": { | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "import qutip as qt" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "A operator $X$ acting on a Hilbert space $\\mathcal{H}$ is a representation of a function $f_X(\\left|\\psi\\right\\rangle) = X\\left|\\psi\\right\\rangle$ such that $f_X(\\left|\\psi\\right\\rangle + \\left|\\phi\\right\\rangle) = f_X(\\left|\\psi\\right\\rangle) + f_X(\\left|\\phi\\right\\rangle)$ and such that for any scalar $\\alpha$, $f_X(\\alpha \\left|\\psi\\right\\rangle) = \\alpha f_X(\\left|\\psi\\right\\rangle)$. Similarly, given a function $g_Y(\\rho)$ such that $g_Y(\\rho + \\sigma) = g_Y(\\rho) + g_Y(\\sigma)$ and $g_Y(\\alpha \\rho) = \\alpha g_Y(\\rho)$, we can represent the action of $g_Y$ as a superoperator $Y$.\n", | |
| "\n", | |
| "In QuTiP, superoperators $Y$ are represented by ``type=\"super\"`` Qobj instances with ``superrep in ['super', 'choi', 'chi']``. For example, a map $g(\\rho) = (\\sigma_x \\rho \\sigma_x + \\rho) / 2$ representing dephasing in the $x$-direction corresponds to the following Qobj:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": { | |
| "collapsed": false | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/latex": [ | |
| "Quantum object: dims = [[[2], [2]], [[2], [2]]], shape = [4, 4], type = super, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.500 & 0.0 & 0.0 & 0.500\\\\0.0 & 0.500 & 0.500 & 0.0\\\\0.0 & 0.500 & 0.500 & 0.0\\\\0.500 & 0.0 & 0.0 & 0.500\\\\\\end{array}\\right)\\end{equation*}" | |
| ], | |
| "text/plain": [ | |
| "Quantum object: dims = [[[2], [2]], [[2], [2]]], shape = [4, 4], type = super, isherm = True\n", | |
| "Qobj data =\n", | |
| "[[ 0.5 0. 0. 0.5]\n", | |
| " [ 0. 0.5 0.5 0. ]\n", | |
| " [ 0. 0.5 0.5 0. ]\n", | |
| " [ 0.5 0. 0. 0.5]]" | |
| ] | |
| }, | |
| "execution_count": 2, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "dephasing_superop = (qt.to_super(qt.sigmax()) + qt.to_super(qt.qeye(2))) / 2\n", | |
| "dephasing_superop" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "This Qobj then acts on vectorized operators, $|\\rho\\rangle\\!\\rangle$, as given by the ``operator_to_vector`` function. Thus, to apply this superoperator to a density operator requires calling ``operator_to_vector`` and the corresponding ``vector_to_operator``:" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": { | |
| "collapsed": false | |
| }, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/latex": [ | |
| "Quantum object: dims = [[2], [2]], shape = [2, 2], type = oper, isherm = True\\begin{equation*}\\left(\\begin{array}{*{11}c}0.500 & 0.187\\\\0.187 & 0.500\\\\\\end{array}\\right)\\end{equation*}" | |
| ], | |
| "text/plain": [ | |
| "Quantum object: dims = [[2], [2]], shape = [2, 2], type = oper, isherm = True\n", | |
| "Qobj data =\n", | |
| "[[ 0.5 0.18655508]\n", | |
| " [ 0.18655508 0.5 ]]" | |
| ] | |
| }, | |
| "execution_count": 3, | |
| "metadata": {}, | |
| "output_type": "execute_result" | |
| } | |
| ], | |
| "source": [ | |
| "rho = qt.rand_dm_ginibre(2)\n", | |
| "rho_out = qt.vector_to_operator(dephasing_superop * qt.operator_to_vector(rho))\n", | |
| "rho_out" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "This is confusing to newcomers to the library, and while it accurately models the Liouvillian representation (that is, ``superrep=\"super\"``), does not model the more general view of a channel as an abstract object. For instance, $\\mathcal{U}(\\rho) = U \\rho U^\\dagger$ (as returned by ``qt.to_super(U)``) is already a quantum channel representing conjugation by a unitary $U$, and need not be written as a superoperator. Using ``__call__``, the group action of superoperators and operators on operators can be modeled in a uniform manner." | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "Here, we prototype by introducing a new method and monkey-patching it into ``Qobj``." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": { | |
| "collapsed": false | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "def qobj_call(self, other):\n", | |
| " if not isinstance(other, qt.Qobj):\n", | |
| " raise TypeError(\"Only defined for quantum objects.\")\n", | |
| " \n", | |
| " if self.type == \"super\":\n", | |
| " if other.type == \"ket\":\n", | |
| " other = qt.ket2dm(other)\n", | |
| " elif other.type == \"oper\":\n", | |
| " return qt.vector_to_operator(self * qt.operator_to_vector(other))\n", | |
| " else:\n", | |
| " raise TypeError(\"Can only act super on oper or ket.\")\n", | |
| " \n", | |
| " elif self.type == \"oper\":\n", | |
| " if other.type == \"ket\":\n", | |
| " return self * other\n", | |
| " elif other.type == \"oper\":\n", | |
| " return self * other * self.dag()\n", | |
| " else:\n", | |
| " raise TypeError(\"Can only act oper on oper or ket.\")\n", | |
| "\n", | |
| "qt.Qobj.__call__ = qobj_call" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 5, | |
| "metadata": { | |
| "collapsed": false | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "psi = qt.rand_ket_haar(2)\n", | |
| "rho = qt.rand_dm_ginibre(2)\n", | |
| "X = qt.sigmax()\n", | |
| "I = qt.qeye(2)\n", | |
| "S = (qt.to_super(I) + qt.to_super(X)) / 2" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "metadata": {}, | |
| "source": [ | |
| "We finally assert a few usecases of these new semantics." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 6, | |
| "metadata": { | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "assert X(psi) == X * psi\n", | |
| "assert X(rho) == X * rho * X.dag()\n", | |
| "assert S(rho) == qt.vector_to_operator(S * qt.operator_to_vector(rho))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "metadata": { | |
| "collapsed": true | |
| }, | |
| "outputs": [], | |
| "source": [] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 2", | |
| "language": "python", | |
| "name": "python2" | |
| }, | |
| "language_info": { | |
| "codemirror_mode": { | |
| "name": "ipython", | |
| "version": 2 | |
| }, | |
| "file_extension": ".py", | |
| "mimetype": "text/x-python", | |
| "name": "python", | |
| "nbconvert_exporter": "python", | |
| "pygments_lexer": "ipython2", | |
| "version": "2.7.11" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 0 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment