diff --git a/dev/GeneralStabilizerState.ipynb b/dev/GeneralStabilizerState.ipynb index 857340c..b600d97 100644 --- a/dev/GeneralStabilizerState.ipynb +++ b/dev/GeneralStabilizerState.ipynb @@ -179,7 +179,7 @@ "metadata": {}, "source": [ "From the result, we see pauli string $XY$ can be decomposed as\n", - "$$XY = i^1 d_0^0 d_1^1 g_0^1 g_1^1=i(XI)(-ZZ)(XX)$$" + "$$XY = i^1 d_0^0 d_1^1 g_0^1 g_1^1=i(ZI)(-ZZ)(XX)$$" ] }, { diff --git a/dev/Untitled.ipynb b/dev/Untitled.ipynb deleted file mode 100644 index 582e3b8..0000000 --- a/dev/Untitled.ipynb +++ /dev/null @@ -1,33 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "8334d599-4421-4ee6-81f6-58b3a2767b46", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.12" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/dev/dev_generalized_stabilizer.ipynb b/dev/dev_generalized_stabilizer.ipynb new file mode 100644 index 0000000..deaa518 --- /dev/null +++ b/dev/dev_generalized_stabilizer.ipynb @@ -0,0 +1,480 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "8334d599-4421-4ee6-81f6-58b3a2767b46", + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.insert(0, '..')\n", + "import numpy\n", + "import matplotlib.pyplot as plt\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "%matplotlib inline\n", + "# will autoupdate any of the packages imported:\n", + "import pyclifford as pc" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "9033b484", + "metadata": {}, + "outputs": [], + "source": [ + "from pyclifford.utils import pauli_decompose, calculate_chi, pauli_combine\n", + "from pyclifford.paulialg import PauliList, Pauli, PauliPolynomial" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "e7395e1b", + "metadata": {}, + "outputs": [], + "source": [ + "class PauliChannel(object):\n", + " '''Pauli channel.\n", + " C[rho] = sum_{m,n} phi_{mn} P_m rho P_n^H,\n", + " where P_m is the m-th element of paulis.\n", + " - The CPTP condition requires phi^H = phi, Tr phi = 1, and phi >=0,\n", + " as if phi is a density matrix.\n", + " \n", + " Parameters:\n", + " paulis: PauliList - a list of Pauli operators {P_m} serving as operator basis.\n", + " phi: complex (L, L) - channel density matrix phi_{mn} in the Pauli basis.'''\n", + " def __init__(self, paulis, phi):\n", + " self.paulis = paulis\n", + " self.phi = phi\n", + " self.N = self.paulis.N" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "1d96ab45", + "metadata": {}, + "outputs": [], + "source": [ + "class GeneralizedStabilizerState(object):\n", + " '''Generalized stabilizer state.\n", + " rho = sum_{b,b'} chi_{b,b'} |b> is a basis state of destabilizer excitations,\n", + " |b> = prod_{i} D_i^{b_i} |0>,\n", + " with |0> being the state stabilzed by all stabilizers, i.e.\n", + " S_i |0> = |0>.\n", + " - The stabilizers and destabilizers are given by a StabilizerState \n", + " instance as the stabilizer frame.\n", + " - The basis of destabilizer excitations are represented as\n", + " binary array (tuple), e.g. (0,1,0,1) means the 2nd and 4th \n", + " destabilizers are excited.\n", + " - The basis dictionary keeps track of the mapping from unique\n", + " binary tuple to integer index of the basis.\n", + " - The density matrix is given by a complex array chi of size L x L,\n", + " where L is the number of excitation basis states.\n", + "\n", + " Parameters:\n", + " frame: StabilizerState - a stabilizer state serving as the frame.\n", + " basis: int (L, N-r) - a binary array encoding the basis of destabilizer excitations.\n", + " chi: complex (L, L) - density matrix in the excitation basis.'''\n", + " def __init__(self, frame, basis, chi):\n", + " self.frame = frame\n", + " self.basis = basis\n", + " self.chi = chi\n", + "\n", + " @property\n", + " def N(self):\n", + " return self.frame.N\n", + " \n", + " @property\n", + " def r(self):\n", + " return self.frame.r\n", + "\n", + " def __repr__(self):\n", + " return f\"GeneralizedStabilizerState(\\nframe=\\n{self.frame},\\nbasis=\\n{self.basis},\\nchi=\\n{self.chi})\"\n", + " \n", + " def copy(self):\n", + " return GeneralizedStabilizerState(self.frame.copy(), self.basis.copy(), self.chi.copy())\n", + " \n", + " def rotate_by(self, generator, mask=None):\n", + " self.frame.rotate_by(generator, mask)\n", + " return self\n", + " \n", + " def transform_by(self, clifford_map, mask=None):\n", + " self.frame.transform_by(clifford_map, mask)\n", + " return self\n", + " \n", + " def evolve_by(self, pauli_channel):\n", + " # Evolve the state by a Pauli channel.\n", + " bs, cs, ps = pauli_decompose(pauli_channel.paulis.gs, pauli_channel.paulis.ps, \n", + " self.frame.gs, self.frame.ps, self.r)\n", + " # construct new basis, compute fusion map and fusion phase indicator\n", + " L_old = self.basis.shape[0]\n", + " L_add = bs.shape[0]\n", + " L_new = 0\n", + " basis_new = {}\n", + " fusion_map = numpy.zeros((L_old,L_add), dtype=numpy.int_)\n", + " fusion_p = numpy.zeros((L_old,L_add), dtype=numpy.int_)\n", + " for i in range(L_old):\n", + " for j in range(L_add):\n", + " b_new = tuple((self.basis[i] + bs[j])%2)\n", + " if b_new not in basis_new:\n", + " basis_new[b_new] = L_new\n", + " L_new += 1\n", + " k = basis_new[b_new]\n", + " fusion_map[i,j] = k\n", + " fusion_p[i,j] = ps[j] + 2*self.basis[i].dot(cs[j])\n", + " # perform fusion of state and channel density matrices\n", + " chi_new = calculate_chi(self.chi, pauli_channel.phi, fusion_map, fusion_p, L_new)\n", + " # in-place update basis and chi\n", + " self.basis = numpy.array(list(basis_new.keys()))\n", + " self.chi = chi_new\n", + " return self\n", + " \n", + " def represent(self, ops):\n", + " '''Represent a list of operators in the destabilizer excitation basis.\n", + " \n", + " Parameters:\n", + " ops: operator(s), can be Pauli, PauliList, PauliPolynomial'''\n", + " if isinstance(ops, Pauli):\n", + " # cast Pauli to PauliPolynomial\n", + " return self.represent(ops.as_polynomial())\n", + " if isinstance(ops, PauliPolynomial):\n", + " # cast PauliPolynomial to PauliList\n", + " mats = self.represent(PauliList(ops.gs,ops.ps))\n", + " return numpy.tensordot(ops.cs, mats, axes=(0,0))\n", + " if isinstance(ops, PauliList):\n", + " bs, cs, ps = pauli_decompose(ops.gs, ops.ps, self.frame.gs, self.frame.ps, self.r)\n", + " L = self.basis.shape[0]\n", + " K = ps.shape[0]\n", + " mats = numpy.zeros((K,L,L), dtype=numpy.complex128)\n", + " idx = {tuple(b): i for i, b in enumerate(self.basis)}\n", + " for k in range(K):\n", + " for i0 in range(L):\n", + " b0 = self.basis[i0]\n", + " b1 = tuple((b0 + bs[k])%2)\n", + " if b1 in idx:\n", + " i1 = idx[b1]\n", + " mats[k,i1,i0] = 1j**(ps[k] + 2*b0.dot(cs[k]))\n", + " return mats\n", + " \n", + " def expect(self, obs):\n", + " '''Evaluate expctationvalues of Pauli observables on the generalized\n", + " stabilizer state.\n", + " \n", + " Parameters:\n", + " obs: observable, can be Pauli, PauliList, PauliPolynomial\n", + "\n", + " Returns:\n", + " out: output (depending on the type of obs)\n", + " * Pauli: promote to PauliPolynomial\n", + " * PauliPolynomial O: Tr(rho O)\n", + " * PauliList [O_i]: [Tr(rho O_i)]''' \n", + " mats = self.represent(obs)\n", + " if mats.ndim == 2: # single matrix case\n", + " return numpy.trace(self.chi @ mats)\n", + " else: # batch case\n", + " return numpy.tensordot(self.chi, mats, axes=([1,0], [1,2]))\n", + " \n", + " def to_numpy(self):\n", + " '''Convert generalized stabilizer state to numpy density matrix representation.'''\n", + " destabilizers = self.frame[self.N+self.r:2*self.N]\n", + " gs, ps =pauli_combine(self.basis, destabilizers.gs, destabilizers.ps)\n", + " Ds = PauliList(gs,ps).to_numpy()\n", + " rho0 = self.frame.to_numpy()\n", + " L = Ds.shape[0]\n", + " rho = numpy.zeros_like(rho0)\n", + " for j1 in range(L):\n", + " for j2 in range(L):\n", + " rho += self.chi[j1, j2]* Ds[j1] @ rho0 @ Ds[j2]\n", + " return rho\n", + " " + ] + }, + { + "cell_type": "markdown", + "id": "161714ca", + "metadata": {}, + "source": [ + "Test: create a generalized stabilizer state over three qubits, where the first two qubits is in a mixture of Bell state, and the third qubit is maximally mixed." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "3e63172d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "GeneralizedStabilizerState(\n", + "frame=\n", + "StabilizerState(\n", + " +XXI\n", + " +ZZI),\n", + "basis=\n", + "[[0 0]\n", + " [1 0]],\n", + "chi=\n", + "[[0.8+0.j 0.1+0.j]\n", + " [0.1+0.j 0.2+0.j]])" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "state=GeneralizedStabilizerState(\n", + " pc.stabilizer_state(\"XXI\",\"ZZI\"), \n", + " numpy.array([[0,0],[1,0]]), \n", + " numpy.array([[0.8,0.1],[0.1,0.2]],dtype=numpy.complex128))\n", + "state" + ] + }, + { + "cell_type": "markdown", + "id": "7ecc9b19", + "metadata": {}, + "source": [ + "Density matrix of the state." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "be822ce2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.4 , 0. , 0. , 0. , 0.05, 0. , 0. , 0. ],\n", + " [0. , 0.4 , 0. , 0. , 0. , 0.05, 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0.05, 0. , 0. , 0. , 0.1 , 0. , 0. , 0. ],\n", + " [0. , 0.05, 0. , 0. , 0. , 0.1 , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]])" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "state.to_numpy().real" + ] + }, + { + "cell_type": "markdown", + "id": "39e9fb12", + "metadata": {}, + "source": [ + "Represent a list of Pauli operators on the stabilizer frame basis." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3744ddcb", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 1.+0.j, 0.+0.j],\n", + " [ 0.+0.j, -1.+0.j]],\n", + "\n", + " [[ 0.+0.j, 0.+1.j],\n", + " [-0.-1.j, 0.+0.j]],\n", + "\n", + " [[ 0.+0.j, 0.+1.j],\n", + " [-0.-1.j, 0.+0.j]],\n", + "\n", + " [[-1.+0.j, 0.+0.j],\n", + " [ 0.+0.j, 1.+0.j]]])" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "state.represent(pc.paulis(\"XXI\",\"XYI\",\"YXI\",\"YYI\"))" + ] + }, + { + "cell_type": "markdown", + "id": "4f06773a", + "metadata": {}, + "source": [ + "Compute the expectation value of a Pauli polynomial on the state." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "9fb4ecae", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.complex128(0.3+0j)" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "obs = (pc.pauli(\"XXI\")+1j*pc.pauli(\"XYI\")+1j*pc.pauli(\"YXI\")-pc.pauli(\"YYI\"))/4\n", + "state.expect(obs)" + ] + }, + { + "cell_type": "markdown", + "id": "493a4c4f", + "metadata": {}, + "source": [ + "Verify that the result is correct by explicit calculation using matrix representations of state and operator." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "7155800c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "np.complex128(0.30000000000000004+0j)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numpy.trace(state.to_numpy() @ obs.to_numpy())" + ] + }, + { + "cell_type": "markdown", + "id": "b7231ecf", + "metadata": {}, + "source": [ + "Define a Pauli channel which maximally decohere the first qubit in the Z basis, then apply the channel to the state." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "9dcaff6b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "GeneralizedStabilizerState(\n", + "frame=\n", + "StabilizerState(\n", + " +XXI\n", + " +ZZI),\n", + "basis=\n", + "[[0 0]\n", + " [1 0]],\n", + "chi=\n", + "[[0.5+0.j 0.1+0.j]\n", + " [0.1+0.j 0.5+0.j]])" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "channel = PauliChannel(pc.paulis(\"III\",\"ZII\"), numpy.array([[0.5,0.0],[0.0,0.5]],dtype=numpy.complex128))\n", + "state.evolve_by(channel)" + ] + }, + { + "cell_type": "markdown", + "id": "3b71c863", + "metadata": {}, + "source": [ + "The density matrix shows that the decoherence indeed removes off-diagonal matrix elements." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "3a6649ac", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0.3, 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0.3, 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0.2, 0. ],\n", + " [0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.2]])" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "state.to_numpy().real" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c16191ca", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.2" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/dev/test_agent_benchmark.ipynb b/dev/test_agent_benchmark.ipynb new file mode 100644 index 0000000..09c4e02 --- /dev/null +++ b/dev/test_agent_benchmark.ipynb @@ -0,0 +1,815 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# add the parent directory to the path, so that we can import the package\n", + "import sys\n", + "sys.path.insert(0, '..')" + ] + }, + { + "cell_type": "code", + "execution_count": 261, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + } + ], + "source": [ + "import numpy\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "# will autoupdate any of the packages imported:\n", + "import pyclifford as pc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Helper Functions" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "def to_latex(obj):\n", + " if isinstance(obj, pc.PauliMonomial):\n", + " z = obj.c * (1j ** obj.p)\n", + " if z == 0.:\n", + " return \"0\"\n", + " elif z.real == 0.:\n", + " s = \"\"\n", + " elif z == 1.:\n", + " s = \"\"\n", + " elif z == -1.:\n", + " s = \"-\"\n", + " else:\n", + " s = str(z.real)\n", + " if z.imag > 0:\n", + " s += \"+\"\n", + " if z.imag != 1.:\n", + " s += str(z.imag)\n", + " s += \"i\"\n", + " elif z.imag < 0:\n", + " if z.imag != -1.:\n", + " s += str(z.imag)\n", + " else:\n", + " s += \"-\"\n", + " s += \"i\"\n", + " if len(s) > 0:\n", + " s += \" \"\n", + " for i in range(obj.N):\n", + " if numpy.array_equal(obj.g[2*i:2*i+2], [1,0]):\n", + " s += \"X\" + \"_{\" + str(i+1) + \"}\"\n", + " elif numpy.array_equal(obj.g[2*i:2*i+2], [1,1]):\n", + " s += \"Y\" + \"_{\" + str(i+1) + \"}\"\n", + " elif numpy.array_equal(obj.g[2*i:2*i+2], [0,1]):\n", + " s += \"Z\" + \"_{\" + str(i+1) + \"}\"\n", + " if s[-1] == \" \":\n", + " s += \"I\"\n", + " return s\n", + " elif isinstance(obj, pc.PauliPolynomial):\n", + " s = \"\"\n", + " for k, term in enumerate(obj):\n", + " s_term = to_latex(term)\n", + " if k != 0:\n", + " if s_term[0] == '-':\n", + " s_term = ' ' + s_term\n", + " else:\n", + " s_term = ' +' + s_term\n", + " s = s + s_term\n", + " return s\n", + " elif isinstance(obj, pc.Pauli):\n", + " return to_latex(obj.as_monomial())\n", + " elif isinstance(obj, pc.PauliList):\n", + " return [to_latex(op) for op in obj]\n", + " else:\n", + " return str(obj)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Benchmark Problems for Agents" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## I. Pauli Algebra" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### I.1. Product of Pauli Strings" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(+i Z_{1}) (-i X_{1}) = +i Y_{1}\n", + "(- Z_{1}) (-i I) = +i Z_{1}\n", + "(- Y_{1}Y_{2}) (+i X_{1}X_{2}) = +i Z_{1}Z_{2}\n", + "(+i Z_{1}Y_{2}) (Z_{1}X_{2}) = Z_{2}\n", + "(Z_{1}X_{2}Y_{3}) (-i Z_{1}Z_{2}X_{3}) = +i Y_{2}Z_{3}\n", + "(+i Z_{1}Y_{2}X_{3}) (-i X_{2}Y_{3}Y_{4}) = Z_{1}Z_{2}Z_{3}Y_{4}\n", + "(- X_{2}X_{4}) (- X_{1}Y_{3}X_{4}Z_{5}) = X_{1}X_{2}Y_{3}Z_{5}\n", + "(+i Y_{2}Z_{3}X_{4}X_{5}Z_{6}) (-i X_{1}X_{2}X_{3}Y_{4}Y_{5}Z_{6}) = - X_{1}Z_{2}Y_{3}Z_{4}Z_{5}\n", + "(-i X_{1}Y_{2}Z_{5}X_{6}Y_{7}Z_{8}) (-i Y_{1}Y_{2}Z_{3}X_{4}X_{5}X_{7}) = -i Z_{1}Z_{3}X_{4}Y_{5}X_{6}Z_{7}Z_{8}\n", + "(- X_{2}X_{3}X_{4}Z_{5}Z_{6}Y_{7}Y_{8}Z_{10}) (- Y_{3}X_{4}X_{5}Y_{6}X_{7}Z_{8}) = +i X_{2}Z_{3}Y_{5}X_{6}Z_{7}X_{8}Z_{10}\n", + "(-i X_{1}X_{2}Z_{4}Z_{5}Z_{6}Y_{8}Z_{9}Z_{10}X_{11}X_{12}Z_{14}) (X_{2}X_{3}Y_{4}X_{5}Z_{6}Z_{7}Z_{8}X_{9}Z_{10}Z_{11}Z_{12}X_{13}X_{14}) = X_{1}X_{3}X_{4}Y_{5}Z_{7}X_{8}Y_{9}Y_{11}Y_{12}X_{13}Y_{14}\n", + "(- X_{3}X_{4}Z_{5}X_{6}Z_{7}Y_{8}Y_{10}Z_{12}Z_{14}X_{17}Z_{18}) (-i Z_{1}X_{2}X_{3}X_{4}Y_{5}X_{6}Z_{8}Z_{9}X_{10}Z_{11}Y_{13}Z_{15}Y_{16}Y_{17}) = +i Z_{1}X_{2}X_{5}Z_{7}X_{8}Z_{9}Z_{10}Z_{11}Z_{12}Y_{13}Z_{14}Z_{15}Y_{16}Z_{17}Z_{18}\n", + "\n" + ] + } + ], + "source": [ + "def prod_pauli(Nmin, samples, seed=42):\n", + " rng = numpy.random.default_rng(seed)\n", + " txt = \"\"\n", + " for k in range(samples):\n", + " N = round(Nmin + 1.3**k - 1)\n", + " gs = rng.integers(0, 2, (2, 2*N))\n", + " ps = rng.integers(0, 4, (2,))\n", + " op0, op1 = pc.PauliList(gs, ps)\n", + " op = op0 @ op1\n", + " txt += \"({}) ({}) = {}\\n\".format(to_latex(op0), to_latex(op1), to_latex(op))\n", + " return txt\n", + "print(prod_pauli(1, 12))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### I.2. Krylov Space Construction" + ] + }, + { + "cell_type": "code", + "execution_count": 178, + "metadata": {}, + "outputs": [], + "source": [ + "def krylov_space(H, tol=1e-10):\n", + " basis = [pc.pauli_identity(H.N)]\n", + " def inner(A, B):\n", + " return (A @ B).trace()/2**H.N\n", + " while True:\n", + " # Generate next potential basis vector H^n\n", + " Knew = H @ basis[-1]\n", + " # Gram-Schmidt orthogonalization against existing basis\n", + " for K in basis:\n", + " proj = inner(K, Knew).item()\n", + " Knew = Knew - proj * K\n", + " # Check if new vector is linearly independent\n", + " norm = inner(Knew, Knew).real.item()\n", + " if norm < tol:\n", + " break\n", + " # Add normalized vector to basis\n", + " basis.append(Knew/numpy.sqrt(norm).item())\n", + " dim = len(basis)\n", + " for i, A in enumerate(basis):\n", + " for j, B in enumerate(basis):\n", + " for k, C in enumerate(basis):\n", + " ope = inner(C, A @ B).real.round(decimals=15)\n", + " if ope != 0.:\n", + " print(\"({},{},{}): {}\".format(i, j, k, ope))\n", + " return basis" + ] + }, + { + "cell_type": "code", + "execution_count": 179, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0,0,0): 1.0\n", + "(0,1,1): 1.0\n", + "(0,2,2): 1.0\n", + "(1,0,1): 1.0\n", + "(1,1,0): 1.0\n", + "(1,1,2): -1.0\n", + "(1,2,1): -1.0\n", + "(2,0,2): 1.0\n", + "(2,1,1): -1.0\n", + "(2,2,0): 1.0\n" + ] + }, + { + "data": { + "text/plain": [ + "[1 II, -0.71 ZZ -0.71 XX, -1 YY]" + ] + }, + "execution_count": 179, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "H = - pc.pauli('XX') - pc.pauli('ZZ')\n", + "krylov_space(H)" + ] + }, + { + "cell_type": "code", + "execution_count": 180, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(0,0,0): 1.0\n", + "(0,1,1): 1.0\n", + "(0,2,2): 1.0\n", + "(0,3,3): 1.0\n", + "(0,4,4): 1.0\n", + "(1,0,1): 1.0\n", + "(1,1,0): 1.0\n", + "(1,2,3): 0.408248290463863\n", + "(1,3,2): 0.408248290463863\n", + "(2,0,2): 1.0\n", + "(2,1,3): 0.408248290463863\n", + "(2,2,0): 1.0\n", + "(2,2,2): 1.632993161855453\n", + "(2,2,4): 1.0\n", + "(2,3,1): 0.408248290463863\n", + "(2,4,2): 1.0\n", + "(3,0,3): 1.0\n", + "(3,1,2): 0.408248290463863\n", + "(3,2,1): 0.408248290463863\n", + "(3,3,0): 1.0\n", + "(4,0,4): 1.0\n", + "(4,2,2): 1.0\n", + "(4,4,0): 1.0\n" + ] + }, + { + "data": { + "text/plain": [ + "[1 IIII,\n", + " -0.50 IIZZ -0.50 IZZI -0.50 ZZII -0.50 XXXX,\n", + " 0.41 IZIZ +0.41 ZIZI +0.41 ZZZZ -0.41 XXYY -0.41 XYYX -0.41 YYXX,\n", + " -0.50 ZIIZ +0.50 XYXY +0.50 YXYX -0.50 YYYY,\n", + " -1 YXXY]" + ] + }, + "execution_count": 180, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "H = - pc.pauli('ZZII') - pc.pauli('IZZI') - pc.pauli('IIZZ') - pc.pauli('XXXX')\n", + "krylov_space(H)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## II. Random Clifford Circuit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### II.1. Random Clifford Unitary Forward" + ] + }, + { + "cell_type": "code", + "execution_count": 266, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X_{1} &\\mapsto - X_{1}Z_{2}Y_{3}Y_{4}X_{5}Z_{6}Y_{7}Y_{8}Y_{9}Y_{10} \\\\\n", + "Z_{1} &\\mapsto X_{1}Z_{3}Y_{4}Z_{5}Y_{6}Y_{7}Y_{8} \\\\\n", + "X_{2} &\\mapsto - X_{1}X_{2}Y_{3}Z_{5}X_{7}X_{9} \\\\\n", + "Z_{2} &\\mapsto - Y_{2}Z_{3}Y_{6}X_{7}X_{8}Z_{9}Y_{10} \\\\\n", + "X_{3} &\\mapsto - Z_{1}Y_{2}Z_{4}Z_{5}Z_{6}Y_{7}X_{8}Z_{9}Y_{10} \\\\\n", + "Z_{3} &\\mapsto Y_{1}X_{2}Z_{4}Z_{5}Z_{6}Y_{7}X_{8}Z_{10} \\\\\n", + "X_{4} &\\mapsto X_{1}Y_{2}Z_{3}Z_{4}X_{5}Y_{9}X_{10} \\\\\n", + "Z_{4} &\\mapsto X_{1}X_{3}Y_{6}Y_{7}Z_{8}X_{10} \\\\\n", + "X_{5} &\\mapsto Y_{1}Y_{3}Y_{5}X_{6}X_{7}Z_{8}X_{9} \\\\\n", + "Z_{5} &\\mapsto Z_{1}Z_{2}Z_{3}X_{4}Z_{5}X_{6}X_{7}Y_{8}Z_{9}Z_{10} \\\\\n", + "X_{6} &\\mapsto X_{1}X_{2}Y_{5}Z_{8}Y_{9}X_{10} \\\\\n", + "Z_{6} &\\mapsto X_{1}X_{2}Z_{4}Z_{5}X_{6}Y_{7}Z_{9}Z_{10} \\\\\n", + "X_{7} &\\mapsto X_{1}Z_{3}Y_{6}Z_{7}Z_{8} \\\\\n", + "Z_{7} &\\mapsto X_{1}Z_{2}X_{3}Y_{6}X_{7}Y_{8}X_{10} \\\\\n", + "X_{8} &\\mapsto - X_{1}Y_{2}Y_{3}X_{4}Y_{5}Y_{6}X_{7}X_{9} \\\\\n", + "Z_{8} &\\mapsto X_{1}X_{2}X_{7}X_{8}X_{9} \\\\\n", + "X_{9} &\\mapsto - X_{2}X_{3}X_{5}Z_{6}Y_{7}X_{8}Y_{9}X_{10} \\\\\n", + "Z_{9} &\\mapsto - Z_{3}Z_{4}X_{5}Z_{6}X_{8}X_{9}Y_{10} \\\\\n", + "X_{10} &\\mapsto - Y_{1}Y_{2}Y_{3}Y_{4}X_{5}Z_{8}Z_{9} \\\\\n", + "Z_{10} &\\mapsto X_{1}X_{3}X_{4}X_{5}X_{8}X_{9}Y_{10} \\\\\n" + ] + }, + { + "data": { + "text/plain": [ + "(['-i Z_{1}Z_{3}Z_{5}X_{8}Y_{9}X_{10}',\n", + " 'X_{1}Y_{2}Y_{3}Y_{4}Y_{5}Y_{7}X_{8}X_{9}',\n", + " '+i Y_{2}Y_{3}X_{4}Y_{5}Z_{6}Z_{7}Z_{8}X_{9}',\n", + " '- Z_{3}X_{4}Y_{5}Y_{6}Z_{7}Z_{8}Y_{9}Z_{10}',\n", + " 'Z_{1}Z_{2}X_{4}Y_{5}Y_{6}Y_{7}Y_{8}Y_{9}X_{10}',\n", + " '-i Z_{1}Y_{2}Y_{3}Y_{4}X_{5}X_{6}Y_{7}Z_{8}Z_{9}X_{10}'],\n", + " ['-i Z_{1}Z_{2}Y_{3}Y_{6}Y_{7}Y_{8}Y_{9}Z_{10}',\n", + " '- X_{1}Y_{2}X_{3}X_{4}X_{5}Y_{6}X_{7}X_{8}Y_{10}',\n", + " '+i X_{1}Z_{2}Z_{3}X_{4}X_{5}Y_{6}Y_{8}X_{9}Y_{10}',\n", + " 'Z_{1}Z_{2}Z_{5}Y_{7}X_{8}Y_{9}Z_{10}',\n", + " '- Z_{1}Y_{3}Z_{4}X_{5}Z_{6}X_{7}Y_{8}Y_{9}',\n", + " '-i X_{1}Z_{2}X_{3}X_{5}Y_{7}Y_{8}Z_{9}X_{10}'])" + ] + }, + "execution_count": 266, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def random_clifford_forward(N, nop, seed=42):\n", + " numpy.random.seed(seed)\n", + " gs = numpy.random.randint(0, 2, (nop, 2*N))\n", + " ps = numpy.random.randint(0, 4, (nop,))\n", + " ops = pc.PauliList(gs, ps)\n", + " map = pc.random_clifford_map(N)\n", + " head = sum([[\"X_{\"+str(i+1)+\"} &\\mapsto\", \"Z_{\"+str(i+1)+\"} &\\mapsto\"] for i in range(N)],[])\n", + " for h, t in zip(head, to_latex(map)):\n", + " print(h+\" \"+t+\" \\\\\\\\\")\n", + " return to_latex(ops), to_latex(ops.transform_by(map))\n", + "\n", + "random_clifford_forward(10, 6)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### II.2. Random Clifford Unitary Backward" + ] + }, + { + "cell_type": "code", + "execution_count": 309, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X_{1} &\\mapsto - Z_{1}Z_{3}X_{6}Y_{7}X_{8}X_{9}Y_{10} \\\\\n", + "Z_{1} &\\mapsto - Y_{1}Y_{2}Y_{3}Y_{5}X_{6}X_{7}Y_{10} \\\\\n", + "X_{2} &\\mapsto Y_{1}Y_{2}Y_{3}Y_{4}Z_{5}Y_{6}X_{7}X_{9}Y_{10} \\\\\n", + "Z_{2} &\\mapsto - Y_{1}X_{4}Y_{5}Z_{6}X_{7}Y_{8}Z_{9}X_{10} \\\\\n", + "X_{3} &\\mapsto - X_{1}Z_{2}X_{4}X_{5}Z_{6}Z_{8}Y_{9} \\\\\n", + "Z_{3} &\\mapsto - Y_{1}Y_{2}Y_{3}X_{5}X_{6}Z_{7}Y_{9} \\\\\n", + "X_{4} &\\mapsto Z_{1}Y_{2}Y_{3}Y_{5}Y_{7}Z_{9} \\\\\n", + "Z_{4} &\\mapsto Y_{1}Z_{2}Z_{3}X_{4}Z_{5}X_{8}X_{9}Z_{10} \\\\\n", + "X_{5} &\\mapsto - Y_{1}Y_{2}X_{3}X_{4}Z_{5}Z_{7}X_{8}Z_{10} \\\\\n", + "Z_{5} &\\mapsto X_{1}Y_{2}Y_{4}Y_{5}X_{7}Z_{9}X_{10} \\\\\n", + "X_{6} &\\mapsto X_{1}Y_{5}Z_{6}Y_{7}X_{8}Y_{9}X_{10} \\\\\n", + "Z_{6} &\\mapsto - Z_{1}X_{2}X_{3}Z_{4}Y_{5}X_{6}Z_{7}Y_{8}Y_{9}Y_{10} \\\\\n", + "X_{7} &\\mapsto X_{1}Y_{2}Z_{3}Z_{5}Z_{6}X_{7}X_{8}Z_{9}Y_{10} \\\\\n", + "Z_{7} &\\mapsto Z_{2}Y_{3}Y_{5}X_{6}Y_{7}Y_{8}X_{9}Y_{10} \\\\\n", + "X_{8} &\\mapsto X_{1}X_{2}Y_{4}Y_{5}Z_{6}Y_{7}Z_{8}Z_{9} \\\\\n", + "Z_{8} &\\mapsto X_{1}X_{2}Z_{3}Z_{5}Z_{7}Y_{9}X_{10} \\\\\n", + "X_{9} &\\mapsto - Z_{2}Y_{3}X_{4}Z_{7}Y_{8}Z_{9}Y_{10} \\\\\n", + "Z_{9} &\\mapsto Z_{1}Z_{2}Y_{3}Y_{4}Z_{5}X_{6}Y_{7}Z_{8} \\\\\n", + "X_{10} &\\mapsto Y_{1}Z_{2}X_{4}Z_{5}Y_{6}Z_{7}Z_{9}Y_{10} \\\\\n", + "Z_{10} &\\mapsto Y_{1}X_{4}Z_{6}Y_{7}Y_{8}Y_{9} \\\\\n" + ] + }, + { + "data": { + "text/plain": [ + "(['+i Y_{1}X_{2}Z_{4}Z_{5}Z_{6}Y_{7}Z_{8}Z_{9}Y_{10}',\n", + " 'X_{1}X_{2}Z_{6}Y_{7}Z_{8}X_{9}X_{10}',\n", + " 'Z_{1}Z_{2}Z_{3}Z_{4}Z_{7}X_{9}X_{10}',\n", + " '+i Y_{1}Z_{2}Z_{3}Y_{4}Y_{5}Y_{6}Y_{8}X_{9}',\n", + " 'Y_{2}Z_{5}X_{7}X_{8}Y_{9}',\n", + " 'Z_{2}Y_{3}X_{4}Z_{5}X_{6}Y_{7}'],\n", + " ['-i Y_{2}Y_{3}Y_{4}Z_{5}Z_{6}X_{7}Z_{8}X_{10}',\n", + " '- X_{1}Z_{2}X_{3}Z_{4}Y_{5}Z_{7}Z_{8}Y_{9}X_{10}',\n", + " '- X_{1}Z_{3}X_{4}Y_{5}Z_{6}Y_{7}Y_{8}X_{9}',\n", + " '-i Y_{1}Y_{2}X_{3}X_{4}Y_{5}Z_{8}Y_{9}Y_{10}',\n", + " 'X_{1}Y_{2}Z_{3}Z_{4}Z_{5}Y_{7}Z_{8}X_{9}Z_{10}',\n", + " '- Y_{1}X_{2}X_{3}X_{4}Z_{5}X_{6}X_{7}X_{8}Y_{9}X_{10}'])" + ] + }, + "execution_count": 309, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def random_clifford_backward(N, nop, seed=32):\n", + " numpy.random.seed(seed)\n", + " gs = numpy.random.randint(0, 2, (nop, 2*N))\n", + " ps = numpy.random.randint(0, 4, (nop,))\n", + " ops = pc.PauliList(gs, ps)\n", + " map = pc.random_clifford_map(N)\n", + " head = sum([[\"X_{\"+str(i+1)+\"} &\\mapsto\", \"Z_{\"+str(i+1)+\"} &\\mapsto\"] for i in range(N)],[])\n", + " for h, t in zip(head, to_latex(map)):\n", + " print(h+\" \"+t+\" \\\\\\\\\")\n", + " return to_latex(ops), to_latex(ops.transform_by(map.inverse()))\n", + "\n", + "random_clifford_backward(10, 6)" + ] + }, + { + "cell_type": "code", + "execution_count": 291, + "metadata": {}, + "outputs": [], + "source": [ + "from numba import njit" + ] + }, + { + "cell_type": "code", + "execution_count": 312, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 1, 0, 0])" + ] + }, + "execution_count": 312, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@njit\n", + "def f(seed):\n", + " numpy.random.seed(seed)\n", + " return numpy.random.randint(0, 2, 4)\n", + "\n", + "f(42)" + ] + }, + { + "cell_type": "code", + "execution_count": 313, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('MT19937',\n", + " array([ 42, 3107752595, 1895908407, 3900362577, 3030691166,\n", + " 4081230161, 2732361568, 1361238961, 3961642104, 867618704,\n", + " 2837705690, 3281374275, 3928479052, 3691474744, 3088217429,\n", + " 1769265762, 3769508895, 2731227933, 2930436685, 486258750,\n", + " 1452990090, 3321835500, 3520974945, 2343938241, 928051207,\n", + " 2811458012, 3391994544, 3688461242, 1372039449, 3706424981,\n", + " 1717012300, 1728812672, 1688496645, 1203107765, 1648758310,\n", + " 440890502, 1396092674, 626042708, 3853121610, 669844980,\n", + " 2992565612, 310741647, 3820958101, 3474052697, 305511342,\n", + " 2053450195, 705225224, 3836704087, 3293527636, 1140926340,\n", + " 2738734251, 574359520, 1493564308, 269614846, 427919468,\n", + " 2903547603, 2957214125, 181522756, 4137743374, 2557886044,\n", + " 3399018834, 1348953650, 1575066973, 3837612427, 705360616,\n", + " 4138204617, 1604205300, 1605197804, 590851525, 2371419134,\n", + " 2530821810, 4183626679, 2872056396, 3895467791, 1156426758,\n", + " 184917518, 2502875602, 2730245981, 3251099593, 2228829441,\n", + " 2591075711, 3048691618, 3030004338, 1726207619, 993866654,\n", + " 823585707, 936803789, 3180156728, 1191670842, 348221088,\n", + " 988038522, 3281236861, 1153842962, 4152167900, 98291801,\n", + " 816305276, 575746380, 1719541597, 2584648622, 1791391551,\n", + " 3234806234, 413529090, 219961136, 4180088407, 1135264652,\n", + " 3923811338, 2304598263, 762142228, 1980420688, 1225347938,\n", + " 3657621885, 3762382117, 1157119598, 2556627260, 2276905960,\n", + " 3857700293, 1903185298, 4258743924, 2078637161, 4160077183,\n", + " 3569294948, 2138906140, 1346725611, 1473959117, 2798330104,\n", + " 3785346335, 4103334026, 3448442764, 1142532843, 4278036691,\n", + " 3071994514, 3474299731, 1121195796, 1536841934, 2132070705,\n", + " 1064908919, 2840327803, 992870214, 2041326888, 2906112696,\n", + " 4182466030, 1031463950, 703166484, 854266995, 4157971695,\n", + " 4071962029, 2600094776, 2770410869, 3776335751, 2599879593,\n", + " 2451043853, 2223709058, 2098813464, 4008111478, 2959232195,\n", + " 3072496064, 2498909222, 4020139729, 785990520, 958060279,\n", + " 4183949075, 2392404465, 533774465, 4092066952, 3967420027,\n", + " 1726137853, 2907699474, 3158758391, 1460845905, 1323598137,\n", + " 2446717890, 3004885867, 3447263769, 1378488047, 3172418196,\n", + " 652839901, 1695052769, 226007057, 778836071, 1216725078,\n", + " 655651335, 1850195064, 427367795, 800074262, 2241880422,\n", + " 1713434925, 339981078, 1730571881, 672610244, 1952245009,\n", + " 2729177102, 3516932475, 4032720152, 3177283432, 411893652,\n", + " 2440235559, 3587427933, 43170267, 39225133, 3904203400,\n", + " 1935961247, 3843123487, 1625453782, 1337993374, 2095455879,\n", + " 3402219947, 634671126, 70868861, 3072823841, 851862432,\n", + " 1828056818, 2794213810, 1222863684, 2164539406, 4249334162,\n", + " 1380362252, 1512719097, 2773165233, 4063118969, 3041859837,\n", + " 529421431, 563872464, 2478730478, 3168749051, 4132953373,\n", + " 3922807735, 1124217574, 1970058502, 1744120743, 1906315107,\n", + " 1074758800, 1611130652, 2878846041, 886823888, 1175456250,\n", + " 1669874674, 2428820171, 1044308794, 3841962192, 138850094,\n", + " 1239727126, 1753711876, 2194286827, 872797664, 4276240980,\n", + " 690338888, 4087206238, 2279169960, 1117436170, 3344885072,\n", + " 3127829945, 315537090, 3802787206, 4157203318, 1637047079,\n", + " 3774106877, 3230158646, 1855823338, 1931415993, 667252379,\n", + " 4288528171, 1587598285, 1096793218, 1916566454, 101891899,\n", + " 2354644560, 3351208292, 1467125166, 2177732119, 4122299478,\n", + " 3904084887, 2653591155, 4201043109, 2867379343, 2660555187,\n", + " 3641744616, 4126452939, 326579197, 2697259239, 3365236848,\n", + " 3007834487, 4118919490, 3306741951, 2285455175, 1956645973,\n", + " 1879691841, 891565150, 1843460149, 2013381028, 819311674,\n", + " 123282948, 1436558519, 1154343666, 206804484, 1650349242,\n", + " 2142011886, 304163699, 2608574600, 2500624796, 2996744833,\n", + " 2344192475, 3152512202, 165571606, 691170269, 1806226529,\n", + " 568535825, 1243813863, 3068953841, 3843784723, 1540495237,\n", + " 4246006858, 1303595780, 3288680241, 864868851, 819595545,\n", + " 3230857496, 3574119395, 1545404573, 2970139338, 4292786727,\n", + " 1803072884, 1374565738, 1736333177, 1978645403, 3962597126,\n", + " 1068006206, 3458125500, 168085922, 1597587506, 2052497512,\n", + " 1323596727, 2421372441, 1468386547, 3574947527, 3363915938,\n", + " 860279252, 1309097460, 3065417722, 1490716202, 3476091722,\n", + " 1669402145, 895071221, 1432690175, 3353592973, 149850974,\n", + " 2789493615, 826939483, 666980418, 755367270, 3988951195,\n", + " 21783894, 1924727373, 1699517788, 1152431122, 2593798113,\n", + " 3522529522, 2797535609, 4018366956, 2350035889, 3010507270,\n", + " 2832621820, 627979167, 997422629, 365587204, 2302500352,\n", + " 1720920631, 689999548, 3713985947, 3267499624, 1971264680,\n", + " 1981530399, 1662926921, 1833821660, 1422522022, 3141447769,\n", + " 2727954526, 4172728772, 1787436028, 1902276939, 3145551277,\n", + " 4207627911, 2497093521, 4111966589, 3929089589, 2253454030,\n", + " 1069424637, 2165048659, 2848813944, 2435898022, 2546206777,\n", + " 3864777677, 3107311565, 3776562483, 1040285049, 3171631943,\n", + " 2404677828, 2522848682, 2930777301, 2831905121, 1436989598,\n", + " 602730315, 664177960, 3959954010, 3116042160, 2881899726,\n", + " 233404945, 4058465099, 1781994751, 485046222, 2776777695,\n", + " 432082123, 1989128370, 86344507, 2510576356, 2194076764,\n", + " 1742125237, 3715839140, 895100548, 147445686, 705462897,\n", + " 2245325113, 1052295404, 1956014786, 2916055958, 1829369612,\n", + " 2541711050, 1594343058, 3708804266, 150438233, 323857098,\n", + " 294681952, 783931535, 606075163, 2427042904, 121207604,\n", + " 3943199031, 1196785464, 1818211378, 1788241109, 3138862427,\n", + " 2037307093, 2306750301, 1644605749, 165986111, 542190743,\n", + " 486828112, 1757411662, 894543082, 4108143634, 1232805238,\n", + " 3801632949, 3863166865, 713767006, 2091486427, 3174776264,\n", + " 1157004409, 623072544, 1667151721, 3361539538, 696723008,\n", + " 3247069452, 682044344, 1382136166, 1385645682, 4219951151,\n", + " 2747881261, 2489355869, 786564174, 2040230554, 2967874556,\n", + " 1414286092, 2677969656, 1393412218, 2216095072, 935533444,\n", + " 3662643439, 3285199608, 3103672804, 522796956, 3952383595,\n", + " 1928659176, 3397717710, 4278554051, 1984736931, 3559102926,\n", + " 1878353094, 875578217, 2398931796, 2313634006, 1606027661,\n", + " 2790634022, 2334166559, 1857067101, 666458681, 1626872683,\n", + " 2155121857, 715449823, 1865157100, 2938814835, 4084911240,\n", + " 45488075, 3474982924, 1750873825, 2246019159, 125388929,\n", + " 1110287838, 652200437, 4212247716, 2702974687, 2963764270,\n", + " 208692058, 3170393729, 1378248367, 752591527, 591629541,\n", + " 2253399388, 2402291226, 3089656189, 3202324513, 3818308310,\n", + " 2828131601, 2690672008, 3676629884, 1007739430, 4072247562,\n", + " 3574795162, 518485611, 1889402182, 3687902739, 3410263649,\n", + " 2790674620, 779455241, 3573984673, 3053204735, 4089925351,\n", + " 789980683, 476440431, 3843536868, 2400661309, 3139919094,\n", + " 1643266656, 113318754, 428163528, 2386492935, 3807242009,\n", + " 574560611, 3174039857, 3774465602, 1164640969, 455942925,\n", + " 1374407495, 2562304709, 1024844203, 521375136, 417432138,\n", + " 1203241821, 2900988280, 2841030991, 2301700751, 369508560,\n", + " 2396447808, 1891459643, 4225682708, 3930667846, 1518293357,\n", + " 2697063889, 3113075061, 2411136298, 2836361984, 4105335811,\n", + " 914081338, 2675982621, 1816939127, 1596754123, 1464603632,\n", + " 1598478676, 1318403529, 4016663081, 2106416852, 2757323084,\n", + " 2042842122, 1175184796, 2212339255, 1334626864, 3994484893,\n", + " 3938045599, 2166620630, 3036360431, 397499085, 975931950,\n", + " 1868702836, 3530424696, 3532548823, 2770836469, 3537418693,\n", + " 3344319345, 3208552526, 1771170897, 4097379814, 3761572528,\n", + " 2794194423, 706836738, 2953105956, 3446096217, 220984542,\n", + " 309619699, 223913021, 3985142640, 1757616575, 2582763607,\n", + " 4018329835, 1393278443, 4121569718, 2087146446, 4282833425,\n", + " 807775617, 1396604749, 3571181413, 90301352, 2618014643,\n", + " 2783561793, 1329389532, 836540831, 26719530], dtype=uint32),\n", + " 624,\n", + " 0,\n", + " 0.0)" + ] + }, + "execution_count": 313, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numpy.random.seed(42)\n", + "numpy.random.get_state()" + ] + }, + { + "cell_type": "code", + "execution_count": 320, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('MT19937',\n", + " array([ 42, 3107752595, 1895908407, 3900362577, 3030691166,\n", + " 4081230161, 2732361568, 1361238961, 3961642104, 867618704,\n", + " 2837705690, 3281374275, 3928479052, 3691474744, 3088217429,\n", + " 1769265762, 3769508895, 2731227933, 2930436685, 486258750,\n", + " 1452990090, 3321835500, 3520974945, 2343938241, 928051207,\n", + " 2811458012, 3391994544, 3688461242, 1372039449, 3706424981,\n", + " 1717012300, 1728812672, 1688496645, 1203107765, 1648758310,\n", + " 440890502, 1396092674, 626042708, 3853121610, 669844980,\n", + " 2992565612, 310741647, 3820958101, 3474052697, 305511342,\n", + " 2053450195, 705225224, 3836704087, 3293527636, 1140926340,\n", + " 2738734251, 574359520, 1493564308, 269614846, 427919468,\n", + " 2903547603, 2957214125, 181522756, 4137743374, 2557886044,\n", + " 3399018834, 1348953650, 1575066973, 3837612427, 705360616,\n", + " 4138204617, 1604205300, 1605197804, 590851525, 2371419134,\n", + " 2530821810, 4183626679, 2872056396, 3895467791, 1156426758,\n", + " 184917518, 2502875602, 2730245981, 3251099593, 2228829441,\n", + " 2591075711, 3048691618, 3030004338, 1726207619, 993866654,\n", + " 823585707, 936803789, 3180156728, 1191670842, 348221088,\n", + " 988038522, 3281236861, 1153842962, 4152167900, 98291801,\n", + " 816305276, 575746380, 1719541597, 2584648622, 1791391551,\n", + " 3234806234, 413529090, 219961136, 4180088407, 1135264652,\n", + " 3923811338, 2304598263, 762142228, 1980420688, 1225347938,\n", + " 3657621885, 3762382117, 1157119598, 2556627260, 2276905960,\n", + " 3857700293, 1903185298, 4258743924, 2078637161, 4160077183,\n", + " 3569294948, 2138906140, 1346725611, 1473959117, 2798330104,\n", + " 3785346335, 4103334026, 3448442764, 1142532843, 4278036691,\n", + " 3071994514, 3474299731, 1121195796, 1536841934, 2132070705,\n", + " 1064908919, 2840327803, 992870214, 2041326888, 2906112696,\n", + " 4182466030, 1031463950, 703166484, 854266995, 4157971695,\n", + " 4071962029, 2600094776, 2770410869, 3776335751, 2599879593,\n", + " 2451043853, 2223709058, 2098813464, 4008111478, 2959232195,\n", + " 3072496064, 2498909222, 4020139729, 785990520, 958060279,\n", + " 4183949075, 2392404465, 533774465, 4092066952, 3967420027,\n", + " 1726137853, 2907699474, 3158758391, 1460845905, 1323598137,\n", + " 2446717890, 3004885867, 3447263769, 1378488047, 3172418196,\n", + " 652839901, 1695052769, 226007057, 778836071, 1216725078,\n", + " 655651335, 1850195064, 427367795, 800074262, 2241880422,\n", + " 1713434925, 339981078, 1730571881, 672610244, 1952245009,\n", + " 2729177102, 3516932475, 4032720152, 3177283432, 411893652,\n", + " 2440235559, 3587427933, 43170267, 39225133, 3904203400,\n", + " 1935961247, 3843123487, 1625453782, 1337993374, 2095455879,\n", + " 3402219947, 634671126, 70868861, 3072823841, 851862432,\n", + " 1828056818, 2794213810, 1222863684, 2164539406, 4249334162,\n", + " 1380362252, 1512719097, 2773165233, 4063118969, 3041859837,\n", + " 529421431, 563872464, 2478730478, 3168749051, 4132953373,\n", + " 3922807735, 1124217574, 1970058502, 1744120743, 1906315107,\n", + " 1074758800, 1611130652, 2878846041, 886823888, 1175456250,\n", + " 1669874674, 2428820171, 1044308794, 3841962192, 138850094,\n", + " 1239727126, 1753711876, 2194286827, 872797664, 4276240980,\n", + " 690338888, 4087206238, 2279169960, 1117436170, 3344885072,\n", + " 3127829945, 315537090, 3802787206, 4157203318, 1637047079,\n", + " 3774106877, 3230158646, 1855823338, 1931415993, 667252379,\n", + " 4288528171, 1587598285, 1096793218, 1916566454, 101891899,\n", + " 2354644560, 3351208292, 1467125166, 2177732119, 4122299478,\n", + " 3904084887, 2653591155, 4201043109, 2867379343, 2660555187,\n", + " 3641744616, 4126452939, 326579197, 2697259239, 3365236848,\n", + " 3007834487, 4118919490, 3306741951, 2285455175, 1956645973,\n", + " 1879691841, 891565150, 1843460149, 2013381028, 819311674,\n", + " 123282948, 1436558519, 1154343666, 206804484, 1650349242,\n", + " 2142011886, 304163699, 2608574600, 2500624796, 2996744833,\n", + " 2344192475, 3152512202, 165571606, 691170269, 1806226529,\n", + " 568535825, 1243813863, 3068953841, 3843784723, 1540495237,\n", + " 4246006858, 1303595780, 3288680241, 864868851, 819595545,\n", + " 3230857496, 3574119395, 1545404573, 2970139338, 4292786727,\n", + " 1803072884, 1374565738, 1736333177, 1978645403, 3962597126,\n", + " 1068006206, 3458125500, 168085922, 1597587506, 2052497512,\n", + " 1323596727, 2421372441, 1468386547, 3574947527, 3363915938,\n", + " 860279252, 1309097460, 3065417722, 1490716202, 3476091722,\n", + " 1669402145, 895071221, 1432690175, 3353592973, 149850974,\n", + " 2789493615, 826939483, 666980418, 755367270, 3988951195,\n", + " 21783894, 1924727373, 1699517788, 1152431122, 2593798113,\n", + " 3522529522, 2797535609, 4018366956, 2350035889, 3010507270,\n", + " 2832621820, 627979167, 997422629, 365587204, 2302500352,\n", + " 1720920631, 689999548, 3713985947, 3267499624, 1971264680,\n", + " 1981530399, 1662926921, 1833821660, 1422522022, 3141447769,\n", + " 2727954526, 4172728772, 1787436028, 1902276939, 3145551277,\n", + " 4207627911, 2497093521, 4111966589, 3929089589, 2253454030,\n", + " 1069424637, 2165048659, 2848813944, 2435898022, 2546206777,\n", + " 3864777677, 3107311565, 3776562483, 1040285049, 3171631943,\n", + " 2404677828, 2522848682, 2930777301, 2831905121, 1436989598,\n", + " 602730315, 664177960, 3959954010, 3116042160, 2881899726,\n", + " 233404945, 4058465099, 1781994751, 485046222, 2776777695,\n", + " 432082123, 1989128370, 86344507, 2510576356, 2194076764,\n", + " 1742125237, 3715839140, 895100548, 147445686, 705462897,\n", + " 2245325113, 1052295404, 1956014786, 2916055958, 1829369612,\n", + " 2541711050, 1594343058, 3708804266, 150438233, 323857098,\n", + " 294681952, 783931535, 606075163, 2427042904, 121207604,\n", + " 3943199031, 1196785464, 1818211378, 1788241109, 3138862427,\n", + " 2037307093, 2306750301, 1644605749, 165986111, 542190743,\n", + " 486828112, 1757411662, 894543082, 4108143634, 1232805238,\n", + " 3801632949, 3863166865, 713767006, 2091486427, 3174776264,\n", + " 1157004409, 623072544, 1667151721, 3361539538, 696723008,\n", + " 3247069452, 682044344, 1382136166, 1385645682, 4219951151,\n", + " 2747881261, 2489355869, 786564174, 2040230554, 2967874556,\n", + " 1414286092, 2677969656, 1393412218, 2216095072, 935533444,\n", + " 3662643439, 3285199608, 3103672804, 522796956, 3952383595,\n", + " 1928659176, 3397717710, 4278554051, 1984736931, 3559102926,\n", + " 1878353094, 875578217, 2398931796, 2313634006, 1606027661,\n", + " 2790634022, 2334166559, 1857067101, 666458681, 1626872683,\n", + " 2155121857, 715449823, 1865157100, 2938814835, 4084911240,\n", + " 45488075, 3474982924, 1750873825, 2246019159, 125388929,\n", + " 1110287838, 652200437, 4212247716, 2702974687, 2963764270,\n", + " 208692058, 3170393729, 1378248367, 752591527, 591629541,\n", + " 2253399388, 2402291226, 3089656189, 3202324513, 3818308310,\n", + " 2828131601, 2690672008, 3676629884, 1007739430, 4072247562,\n", + " 3574795162, 518485611, 1889402182, 3687902739, 3410263649,\n", + " 2790674620, 779455241, 3573984673, 3053204735, 4089925351,\n", + " 789980683, 476440431, 3843536868, 2400661309, 3139919094,\n", + " 1643266656, 113318754, 428163528, 2386492935, 3807242009,\n", + " 574560611, 3174039857, 3774465602, 1164640969, 455942925,\n", + " 1374407495, 2562304709, 1024844203, 521375136, 417432138,\n", + " 1203241821, 2900988280, 2841030991, 2301700751, 369508560,\n", + " 2396447808, 1891459643, 4225682708, 3930667846, 1518293357,\n", + " 2697063889, 3113075061, 2411136298, 2836361984, 4105335811,\n", + " 914081338, 2675982621, 1816939127, 1596754123, 1464603632,\n", + " 1598478676, 1318403529, 4016663081, 2106416852, 2757323084,\n", + " 2042842122, 1175184796, 2212339255, 1334626864, 3994484893,\n", + " 3938045599, 2166620630, 3036360431, 397499085, 975931950,\n", + " 1868702836, 3530424696, 3532548823, 2770836469, 3537418693,\n", + " 3344319345, 3208552526, 1771170897, 4097379814, 3761572528,\n", + " 2794194423, 706836738, 2953105956, 3446096217, 220984542,\n", + " 309619699, 223913021, 3985142640, 1757616575, 2582763607,\n", + " 4018329835, 1393278443, 4121569718, 2087146446, 4282833425,\n", + " 807775617, 1396604749, 3571181413, 90301352, 2618014643,\n", + " 2783561793, 1329389532, 836540831, 26719530], dtype=uint32),\n", + " 624,\n", + " 0,\n", + " 0.0)" + ] + }, + "execution_count": 320, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "numpy.random.seed(42)\n", + "numpy.random.randint(0, 1, 6)\n", + "numpy.random.get_state()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pyclifford/circuit.py b/pyclifford/circuit.py index 226b15a..252b12a 100644 --- a/pyclifford/circuit.py +++ b/pyclifford/circuit.py @@ -69,8 +69,8 @@ def independent_from(self, other): return len(set(self.qubits) & set(other.qubits))==0 def forward(self, obj): - '''Apply the gate forward in time. (inplace update) - Forward transformation: O -> U O U^\dagger + '''Apply the gate forward in time. (inplace update) + Forward transformation: O -> U O U^H Input: obj: Pauli, PauliList, StabilizerState - the object to be transformed @@ -103,7 +103,7 @@ def forward(self, obj): def backward(self, obj): '''Apply the gate backward in time. (inplace update) - Backward transformation: O -> U^\dagger O U + Backward transformation: O -> U^H O U Input: obj: Pauli, PauliList, StabilizerState - the object to be transformed @@ -195,12 +195,12 @@ def independent_from(self, other): def forward(self, obj): '''Implements the measurement (non-deterministic sampling outcome). (inplace update) - Forward transformation: rho -> M rho M^\dagger / Tr(M rho M^\dagger), - where M is sampled with probability Tr(M rho M^\dagger). + Forward transformation: rho -> M rho M^H / Tr(M rho M^H), + where M is sampled with probability Tr(M rho M^H). Input: obj: StabilizerState - the state to be measured - + Output: obj: StabilizerState - the state after measurement log2prob: real - log2 probability of the outcome''' @@ -215,12 +215,12 @@ def forward(self, obj): def backward(self, obj): '''Postselect the measurement outcome (deterministic projection). (inplace update) - Backward transformation: rho -> M^\dagger rho M / Tr(M^\dagger rho M) + Backward transformation: rho -> M^H rho M / Tr(M^H rho M) where M is fixed by the measurement outcome generated in the forward pass. Input: obj: StabilizerState - the state to be postselected - + Output: obj: StabilizerState - the state after postselection log2prob: real - log2 probability of successful postselection''' diff --git a/pyclifford/paulialg.py b/pyclifford/paulialg.py index 1e7e3b1..9d4187b 100644 --- a/pyclifford/paulialg.py +++ b/pyclifford/paulialg.py @@ -48,6 +48,11 @@ def __repr__(self): def N(self): # number of qubits return self.g.shape[0]//2 + def expand(self, N): + if N is not None and N > self.N: + self.g = numpy.concatenate([self.g, numpy.zeros(2*(N-self.N), dtype=self.g.dtype)]) + return self + def __neg__(self): return type(self)(self.g, (self.p + 2) % 4) @@ -77,6 +82,10 @@ def __sub__(self, other): def __matmul__(self, other): if isinstance(other, Pauli): + if self.N != other.N: + N = max(self.N, other.N) + self.expand(N) + other.expand(N) p = (self.p + other.p + ipow(self.g, other.g)) % 4 g = (self.g + other.g) % 2 return Pauli(g, p) @@ -186,6 +195,11 @@ def L(self): @property def N(self): return self.gs.shape[1]//2 + + def expand(self, N): + if N is not None and N > self.N: + self.gs = numpy.concatenate([self.gs, numpy.zeros((self.L, 2*(N-self.N)), dtype=self.gs.dtype)], axis=1) + return self def __getitem__(self, item): if isinstance(item, (int, numpy.integer)): @@ -367,7 +381,7 @@ def as_polynomial(self): '''cast the Pauli monomial to a single-term Pauli polynomial''' gs = numpy.expand_dims(self.g, 0) ps = numpy.array([self.p], dtype=numpy.int_) - cs = numpy.array([self.c], dtype=numpy.complex_) + cs = numpy.array([self.c], dtype=numpy.complex128) return PauliPolynomial(gs, ps).set_cs(cs) def inverse(self): @@ -386,7 +400,7 @@ class PauliPolynomial(PauliList): cs: comlex (L) - coefficients.''' def __init__(self, *args, **kwargs): super(PauliPolynomial, self).__init__(*args, **kwargs) - self.cs = numpy.ones(self.ps.shape, dtype=numpy.complex_) # default coefficient + self.cs = numpy.ones(self.ps.shape, dtype=numpy.complex128) # default coefficient def __repr__(self): txt = '' @@ -420,6 +434,10 @@ def __add__(self, other): other = other.as_polynomial() else: # otherwise assuming other is a number other = other * pauli_identity(self.N) + if self.N != other.N: + N = max(self.N, other.N) + self.expand(N) + other.expand(N) gs = numpy.concatenate([self.gs, other.gs]) ps = numpy.concatenate([self.ps, other.ps]) cs = numpy.concatenate([self.cs, other.cs]) @@ -436,6 +454,10 @@ def __matmul__(self, other): other = other.as_polynomial() else: raise NotImplementedError('matmul is not implemented for between {} and {}'.format(type(self).__name__, type(other).__name__)) + if self.N != other.N: + N = max(self.N, other.N) + self.expand(N) + other.expand(N) gs, ps, cs = batch_dot(self.gs, self.ps, self.cs, other.gs, other.ps, other.cs) return PauliPolynomial(gs, ps).set_cs(cs) @@ -474,13 +496,13 @@ def to_numpy(self): # ---- constructors ---- def pauli(obj, N = None): if isinstance(obj, Pauli): - return obj + return obj.expand(N) elif isinstance(obj, (tuple, list, numpy.ndarray)): N = len(obj) inds = enumerate(obj) elif isinstance(obj, dict): if N is None: - raise ValueError('pauli(inds, N) must specify qubit number N when inds is dict.') + N = max(obj.keys()) + 1 if obj else 0 inds = obj.items() elif isinstance(obj, str): return pauli(list(obj)) @@ -490,6 +512,7 @@ def pauli(obj, N = None): h = 0 p = 0 for i, mu in inds: + i = int(i) assert i-h < N, 'qubit {} is out of bounds for system size {}.'.format(i, N) if mu == 0 or mu == 'I': continue @@ -532,6 +555,9 @@ def paulis(*objs, N = None): objs = objs[0] # otherwise construct data for Pauli operators objs = [pauli(obj, N = N) for obj in objs] + N = max(obj.N for obj in objs) + for obj in objs: + obj.expand(N) gs = numpy.stack([obj.g for obj in objs]) ps = numpy.array([obj.p for obj in objs]) return PauliList(gs, ps) diff --git a/pyclifford/pyclifford.egg-info/PKG-INFO b/pyclifford/pyclifford.egg-info/PKG-INFO new file mode 100644 index 0000000..2800d9d --- /dev/null +++ b/pyclifford/pyclifford.egg-info/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 2.4 +Name: pyclifford +Version: 0.1.0 +Summary: A Python package for Clifford algebra and quantum computing +Author: PyClifford Team +Requires-Python: >=3.6 +Requires-Dist: numpy +Requires-Dist: matplotlib +Dynamic: author +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary diff --git a/pyclifford/pyclifford.egg-info/SOURCES.txt b/pyclifford/pyclifford.egg-info/SOURCES.txt new file mode 100644 index 0000000..94df70c --- /dev/null +++ b/pyclifford/pyclifford.egg-info/SOURCES.txt @@ -0,0 +1,9 @@ +setup.py +pyclifford.egg-info/PKG-INFO +pyclifford.egg-info/SOURCES.txt +pyclifford.egg-info/dependency_links.txt +pyclifford.egg-info/requires.txt +pyclifford.egg-info/top_level.txt +tests/__init__.py +tests/test_paulialg.py +tests/test_stabilizer.py \ No newline at end of file diff --git a/pyclifford/pyclifford.egg-info/dependency_links.txt b/pyclifford/pyclifford.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pyclifford/pyclifford.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/pyclifford/pyclifford.egg-info/requires.txt b/pyclifford/pyclifford.egg-info/requires.txt new file mode 100644 index 0000000..aa094d9 --- /dev/null +++ b/pyclifford/pyclifford.egg-info/requires.txt @@ -0,0 +1,2 @@ +numpy +matplotlib diff --git a/pyclifford/pyclifford.egg-info/top_level.txt b/pyclifford/pyclifford.egg-info/top_level.txt new file mode 100644 index 0000000..2b29f27 --- /dev/null +++ b/pyclifford/pyclifford.egg-info/top_level.txt @@ -0,0 +1 @@ +tests diff --git a/pyclifford/stabilizer.py b/pyclifford/stabilizer.py index b070e58..148679f 100644 --- a/pyclifford/stabilizer.py +++ b/pyclifford/stabilizer.py @@ -38,6 +38,12 @@ def __repr__(self): lns2 = [dis.format(xz[i%2], i//2, pauli) for i, pauli in zip(range(self.L-10, self.L), self[-10:])] return 'CliffordMap(\n{}\n ...\n{})'.format('\n'.join(lns1),'\n'.join(lns2)).replace('\n','\n ') + def expand(self, N): + if N is not None and N > self.N: + return identity_map(N).embed(self, mask(range(self.N), N)) + else: + return self + def copy(self): return CliffordMap(self.gs.copy(), self.ps.copy()) @@ -65,7 +71,7 @@ def inverse(self): '''Returns the inverse of this Clifford map, (such that it composes with its inverse results in identity map).''' gs_inv = z2inv(self.gs) - gs_iden, ps_mis = pauli_combine(gs_inv, self.gs, self.ps) + _, ps_mis = pauli_combine(gs_inv, self.gs, self.ps) ps_inv = (- ps_mis - ps0(gs_inv))%4 return CliffordMap(gs_inv, ps_inv) @@ -106,6 +112,12 @@ def __repr__(self): @property def stabilizers(self): return self[self.r:self.N] + + def expand(self, N): + if N is not None and N > self.N: + return stabilizer_state(self.stabilizers.expand(N)) + else: + return self def copy(self): return StabilizerState(self.gs.copy(), self.ps.copy(), r=self.r) diff --git a/pyclifford/utils.py b/pyclifford/utils.py index 012cc9c..ab86659 100644 --- a/pyclifford/utils.py +++ b/pyclifford/utils.py @@ -169,7 +169,7 @@ def batch_dot(gs1, ps1, cs1, gs2, ps2, cs2): (L2, N2) = gs2.shape gs = numpy.empty((L1,L2,N2), dtype=numpy.int_) ps = numpy.empty((L1,L2), dtype=numpy.int_) - cs = numpy.empty((L1,L2), dtype=numpy.complex_) + cs = numpy.empty((L1,L2), dtype=numpy.complex128) for j1 in range(L1): for j2 in range(L2): ps[j1,j2] = (ps1[j1] + ps2[j2] + ipow(gs1[j1], gs2[j2]))%4 @@ -202,7 +202,7 @@ def pauli_tokenize(gs, ps): ts[j,N] = 4 + x * (11 - 9 * x + 2 * x**2) // 2 return ts -# ---- combination and trasnformation ---- +# ---- combination, trasnformation, decomposition ---- @njit def pauli_combine(C, gs_in, ps_in): '''Combine Pauli operators by operator product. @@ -246,6 +246,41 @@ def pauli_transform(gs_in, ps_in, gs_map, ps_map): ps_out = (ps_in + ps0(gs_in) + ps_out)%4 return gs_out, ps_out +@njit +def pauli_decompose(gs_in, ps_in, gs_stb, ps_stb, r): + '''Decompose Pauli operators into stabilizer and destabilizers. + + Parameters: + gs_in: int (L, 2*N) - Pauli strings in binary representation. + ps_in: int (L) - phase indicators of Pauli operators. + gs_stb: int (2*N, 2*N) - stabilizer tableaux in binary representation. + ps_stb: int (2*N) - phase indicators of (de)stabilizer. + r: int - number of standby stabilizer pairs (0:r to be excluded). + + Returns: + bs_out: int (L, N-r) - binary encoding of destabilizer decomposition. + cs_out: int (L, N-r) - binary encoding of stabilizer decomposition. + ps_out: int (L) - phase indicators of decomposed operators.''' + (L, N2) = gs_in.shape + N = N2//2 + bs_out = numpy.zeros((L, N-r), dtype=numpy.int_) + cs_out = numpy.zeros((L, N-r), dtype=numpy.int_) + ps_out = ps_in.copy() + g_tmp = numpy.zeros(N2, dtype=numpy.int_) + for k in range(L): + g_tmp.fill(0) + for j in range(r, N): + if acq(gs_in[k], gs_stb[j]): + bs_out[k,j-r] = 1 + ps_out[k] = ps_out[k] - ps_stb[j+N] - ipow(g_tmp, gs_stb[j+N]) + g_tmp = (g_tmp + gs_stb[j+N])%2 + for j in range(r, N): + if acq(gs_in[k], gs_stb[j+N]): + cs_out[k,j-r] = 1 + ps_out[k] = ps_out[k] - ps_stb[j] - ipow(g_tmp, gs_stb[j]) + g_tmp = (g_tmp + gs_stb[j])%2 + return bs_out, cs_out, ps_out%4 + # ---- clifford rotation ---- @njit def clifford_rotate(g, p, gs, ps): @@ -969,3 +1004,17 @@ def aggregate(data_in, inds, l): for i in range(data_in.shape[0]): data_out[inds[i]] += data_in[i] return data_out + +# ---- generalized stabilizer utilities ---- +@njit +def calculate_chi(chi_old, phi, fusion_map, fusion_p, L_new): + L_old, L_add = fusion_map.shape + chi_new = numpy.zeros((L_new,L_new), dtype=numpy.complex128) + for i1 in range(L_old): + for j1 in range(L_add): + k1 = fusion_map[i1,j1] + for i2 in range(L_old): + for j2 in range(L_add): + k2 = fusion_map[i2,j2] + chi_new[k1,k2] += chi_old[i1,i2] * phi[j1,j2] * 1j**(fusion_p[i1,j1] + fusion_p[i2,j2]) + return chi_new