From 932a558cf13d76819bdab3cead1d5209122fa223 Mon Sep 17 00:00:00 2001 From: PFmix <52443738+PFmix@users.noreply.github.com> Date: Thu, 23 Oct 2025 10:16:56 +0200 Subject: [PATCH] Added entanglement lecture applications notebooks --- .../10_Entanglement_structure.ipynb | 249 ++++++++++++++++++ .../Entanglement_extra/11_GHZ_W.ipynb | 105 ++++++++ .../Entanglement_extra/12_Purification.ipynb | 224 ++++++++++++++++ .../Entanglement_extra/1_Schmidt_decomp.ipynb | 102 +++++++ .../Entanglement_extra/2_locc.ipynb | 73 +++++ .../Entanglement_extra/3_Renyi_entropy.ipynb | 109 ++++++++ .../4_Concurrence_negativity.ipynb | 104 ++++++++ .../Entanglement_extra/5_Bell_test.ipynb | 100 +++++++ .../6_Entanglement_witnesses.ipynb | 93 +++++++ .../Entanglement_extra/7_Separability.ipynb | 93 +++++++ .../Entanglement_extra/8_Area_law.ipynb | 146 ++++++++++ 11 files changed, 1398 insertions(+) create mode 100644 extra_resources/Entanglement_extra/10_Entanglement_structure.ipynb create mode 100644 extra_resources/Entanglement_extra/11_GHZ_W.ipynb create mode 100644 extra_resources/Entanglement_extra/12_Purification.ipynb create mode 100644 extra_resources/Entanglement_extra/1_Schmidt_decomp.ipynb create mode 100644 extra_resources/Entanglement_extra/2_locc.ipynb create mode 100644 extra_resources/Entanglement_extra/3_Renyi_entropy.ipynb create mode 100644 extra_resources/Entanglement_extra/4_Concurrence_negativity.ipynb create mode 100644 extra_resources/Entanglement_extra/5_Bell_test.ipynb create mode 100644 extra_resources/Entanglement_extra/6_Entanglement_witnesses.ipynb create mode 100644 extra_resources/Entanglement_extra/7_Separability.ipynb create mode 100644 extra_resources/Entanglement_extra/8_Area_law.ipynb diff --git a/extra_resources/Entanglement_extra/10_Entanglement_structure.ipynb b/extra_resources/Entanglement_extra/10_Entanglement_structure.ipynb new file mode 100644 index 0000000..3c6541e --- /dev/null +++ b/extra_resources/Entanglement_extra/10_Entanglement_structure.ipynb @@ -0,0 +1,249 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nDifferent ansätze generate different entanglement patterns, affecting trainability and noise sensitivity.\\n\\nExercises:\\n- Visualize both curves and discuss trainability vs. noise.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Different ansätze generate different entanglement patterns, affecting trainability and noise sensitivity.\n", + "\n", + "Exercises:\n", + "- Visualize both curves and discuss trainability vs. noise.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import Statevector, DensityMatrix, partial_trace\n", + "\n", + "def hea_layer(n, theta):\n", + " qc = QuantumCircuit(n)\n", + " for q in range(n): qc.rx(0.8,q); qc.ry(0.5,q); qc.rz(0.3,q)\n", + " for i in range(n-1): qc.rxx(theta,i,i+1)\n", + " return qc\n", + "\n", + "def pair_layer(n, theta):\n", + " qc = QuantumCircuit(n)\n", + " for q in range(n): qc.rx(0.8,q); qc.ry(0.5,q); qc.rz(0.3,q)\n", + " for i in range(0,n-1,2): qc.rxx(theta,i,i+1)\n", + " for i in range(1,n-1,2): qc.rxx(theta,i,i+1)\n", + " return qc\n", + "\n", + "def mid_entropy(psi, n):\n", + " rhoA = partial_trace(DensityMatrix(psi), list(range(n//2))).data # Trace out qubit 1\n", + " evals = np.linalg.eigvalsh(rhoA)\n", + " evals = evals[evals>1e-12]\n", + " return sum(-evals*np.log2(evals))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "hea_layer for 8 qubits:\n", + " ┌─────────┐┌─────────┐┌─────────┐┌───────────┐ »\n", + "q_0: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤0 ├──────────────────────────»\n", + " ├─────────┤├─────────┤├─────────┤│ Rxx(0.2) │┌───────────┐ »\n", + "q_1: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤1 ├┤0 ├─────────────»\n", + " ├─────────┤├─────────┤├─────────┤└───────────┘│ Rxx(0.2) │┌───────────┐»\n", + "q_2: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├─────────────┤1 ├┤0 ├»\n", + " ├─────────┤├─────────┤├─────────┤ └───────────┘│ Rxx(0.2) │»\n", + "q_3: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├──────────────────────────┤1 ├»\n", + " ├─────────┤├─────────┤├─────────┤ └───────────┘»\n", + "q_4: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├───────────────────────────────────────»\n", + " ├─────────┤├─────────┤├─────────┤ »\n", + "q_5: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├───────────────────────────────────────»\n", + " ├─────────┤├─────────┤├─────────┤ »\n", + "q_6: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├───────────────────────────────────────»\n", + " ├─────────┤├─────────┤├─────────┤ »\n", + "q_7: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├───────────────────────────────────────»\n", + " └─────────┘└─────────┘└─────────┘ »\n", + "« \n", + "«q_0: ────────────────────────────────────────────────────\n", + "« \n", + "«q_1: ────────────────────────────────────────────────────\n", + "« \n", + "«q_2: ────────────────────────────────────────────────────\n", + "« ┌───────────┐ \n", + "«q_3: ┤0 ├───────────────────────────────────────\n", + "« │ Rxx(0.2) │┌───────────┐ \n", + "«q_4: ┤1 ├┤0 ├──────────────────────────\n", + "« └───────────┘│ Rxx(0.2) │┌───────────┐ \n", + "«q_5: ─────────────┤1 ├┤0 ├─────────────\n", + "« └───────────┘│ Rxx(0.2) │┌───────────┐\n", + "«q_6: ──────────────────────────┤1 ├┤0 ├\n", + "« └───────────┘│ Rxx(0.2) │\n", + "«q_7: ───────────────────────────────────────┤1 ├\n", + "« └───────────┘\n", + "pair_layer for 8 qubits:\n", + " ┌─────────┐┌─────────┐┌─────────┐┌───────────┐ \n", + "q_0: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤0 ├─────────────\n", + " ├─────────┤├─────────┤├─────────┤│ Rxx(0.2) │┌───────────┐\n", + "q_1: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤1 ├┤0 ├\n", + " ├─────────┤├─────────┤├─────────┤├───────────┤│ Rxx(0.2) │\n", + "q_2: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤0 ├┤1 ├\n", + " ├─────────┤├─────────┤├─────────┤│ Rxx(0.2) │├───────────┤\n", + "q_3: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤1 ├┤0 ├\n", + " ├─────────┤├─────────┤├─────────┤├───────────┤│ Rxx(0.2) │\n", + "q_4: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤0 ├┤1 ├\n", + " ├─────────┤├─────────┤├─────────┤│ Rxx(0.2) │├───────────┤\n", + "q_5: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤1 ├┤0 ├\n", + " ├─────────┤├─────────┤├─────────┤├───────────┤│ Rxx(0.2) │\n", + "q_6: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤0 ├┤1 ├\n", + " ├─────────┤├─────────┤├─────────┤│ Rxx(0.2) │└───────────┘\n", + "q_7: ┤ Rx(0.8) ├┤ Ry(0.5) ├┤ Rz(0.3) ├┤1 ├─────────────\n", + " └─────────┘└─────────┘└─────────┘└───────────┘ \n" + ] + } + ], + "source": [ + "print(\"hea_layer for 8 qubits:\",)\n", + "qc = hea_layer(8,0.2)\n", + "print(qc)\n", + "print(\"pair_layer for 8 qubits:\")\n", + "qc = pair_layer(8,0.2)\n", + "print(qc)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HEA: [(0, np.float64(0.0)), (1, np.float64(0.14109578748254875)), (2, np.float64(0.2368415930101412)), (3, np.float64(0.5144193774363365)), (4, np.float64(0.7858958956013805)), (5, np.float64(0.9265154729319807)), (6, np.float64(1.0996001206224981))]\n", + "Pair: [(0, np.float64(0.0)), (1, np.float64(0.14109578748254875)), (2, np.float64(0.23684159301014218)), (3, np.float64(0.5144193774363377)), (4, np.float64(0.7858958956013814)), (5, np.float64(0.9265154729319804)), (6, np.float64(1.0996001206224975))]\n", + "Overlap: [(0, np.float64(1.0)), (1, np.float64(0.9999999999999978)), (2, np.float64(0.9999999999999956)), (3, np.float64(0.9999999999999947)), (4, np.float64(0.9999999999999927)), (5, np.float64(0.9999999999999909)), (6, np.float64(0.9999999999999889))]\n" + ] + } + ], + "source": [ + "n=8; L=6; theta=0.4\n", + "psi_he = Statevector.from_label(\"0\"*n)\n", + "psi_pair = Statevector.from_label(\"0\"*n)\n", + "hea, pair, overlap = [], [], []\n", + "for d in range(L+1):\n", + " hea.append((d, mid_entropy(psi_he,n)))\n", + " pair.append((d, mid_entropy(psi_pair,n)))\n", + " overlap.append((d, (np.abs(psi_he.data.conj().T @ psi_pair.data))**2))\n", + " if d + |111>)/sqrt(2)\n", + "rho_g = DensityMatrix(Statevector.from_instruction(qc_g))\n", + "\n", + "w = Statevector([0,1,1,0,1,0,0,0])/np.sqrt(3)\n", + "rho_w = DensityMatrix(w)\n", + "\n", + "def red(dm, keep):\n", + " drop = [i for i in range(3) if i not in keep]\n", + " return partial_trace(dm, drop).data\n", + "\n", + "print(\"Single qubit reductions:\")\n", + "for name, dm in [(\"GHZ\", rho_g), (\"W\", rho_w)]:\n", + " print(name, concurrence(red(dm,[0])), concurrence(red(dm,[1])), concurrence(red(dm,[2])))\n", + "\n", + "print(\"\\nTwo qubit reductions:\")\n", + "for name, dm in [(\"GHZ\", rho_g), (\"W\", rho_w)]:\n", + " print(name, concurrence(red(dm,[0,1])), concurrence(red(dm,[0,2])), concurrence(red(dm,[1,2])))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/12_Purification.ipynb b/extra_resources/Entanglement_extra/12_Purification.ipynb new file mode 100644 index 0000000..1437ca5 --- /dev/null +++ b/extra_resources/Entanglement_extra/12_Purification.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\n### Overview\\nSimulate a simple entanglement purification step (BBPSSW-like) on isotropic states and track fidelity gains.\\n\\nExercises:\\n- Chain multiple rounds and observe convergence threshold behavior.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "### Overview\n", + "Simulate a simple entanglement purification step (BBPSSW-like) on isotropic states and track fidelity gains.\n", + "\n", + "Exercises:\n", + "- Chain multiple rounds and observe convergence threshold behavior.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "F_in=0.50 F_out≈0.500 p_succ≈0.556\n", + "F_in=0.60 F_out≈0.620 p_succ≈0.609\n", + "F_in=0.70 F_out≈0.735 p_succ≈0.680\n", + "F_in=0.80 F_out≈0.838 p_succ≈0.769\n", + "F_in=0.90 F_out≈0.926 p_succ≈0.876\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "def bbpssw_round(F):\n", + " # Toy mapping for isotropic states under BBPSSW (not exact; illustrative)\n", + " # Successful output fidelity (heuristic):\n", + " F_out = (F**2 + ((1-F)/3)**2) / (F**2 + 2*F*(1-F)/3 + 5*((1-F)/3)**2)\n", + " p_succ = F**2 + 2*F*(1-F)/3 + 5*((1-F)/3)**2\n", + " return F_out, p_succ\n", + "for F in [0.5,0.6,0.7,0.8,0.9]:\n", + " Fo, ps = bbpssw_round(F)\n", + " print(f\"F_in={F:.2f} F_out≈{Fo:.3f} p_succ≈{ps:.3f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bell States Density Matrices:\n", + "Phi+:\n", + " DensityMatrix([[0.5+0.j, 0. +0.j, 0. +0.j, 0.5+0.j],\n", + " [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n", + " [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n", + " [0.5+0.j, 0. +0.j, 0. +0.j, 0.5+0.j]],\n", + " dims=(2, 2))\n", + "Phi-:\n", + " DensityMatrix([[ 0.5+0.j, 0. +0.j, 0. +0.j, -0.5+0.j],\n", + " [ 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n", + " [ 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n", + " [-0.5+0.j, 0. +0.j, 0. +0.j, 0.5+0.j]],\n", + " dims=(2, 2))\n", + "Psi+:\n", + " DensityMatrix([[0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n", + " [0. +0.j, 0.5+0.j, 0.5+0.j, 0. +0.j],\n", + " [0. +0.j, 0.5+0.j, 0.5+0.j, 0. +0.j],\n", + " [0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j]],\n", + " dims=(2, 2))\n", + "Psi-:\n", + " DensityMatrix([[ 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j],\n", + " [ 0. +0.j, 0.5+0.j, -0.5+0.j, 0. +0.j],\n", + " [ 0. +0.j, -0.5+0.j, 0.5+0.j, 0. +0.j],\n", + " [ 0. +0.j, 0. +0.j, 0. +0.j, 0. +0.j]],\n", + " dims=(2, 2))\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import Statevector, DensityMatrix, partial_trace\n", + "\n", + "qc_phip = QuantumCircuit(2)\n", + "qc_phip.h(0)\n", + "qc_phip.cx(0, 1)\n", + "rho_phip = DensityMatrix.from_instruction(qc_phip)\n", + "\n", + "qc_phim = QuantumCircuit(2)\n", + "qc_phim.x(0)\n", + "qc_phim.h(0)\n", + "qc_phim.cx(0, 1)\n", + "rho_phim = DensityMatrix.from_instruction(qc_phim)\n", + "\n", + "\n", + "qc_psip = QuantumCircuit(2)\n", + "qc_psip.x(1)\n", + "qc_psip.h(0)\n", + "qc_psip.cx(0, 1)\n", + "rho_psip = DensityMatrix.from_instruction(qc_psip)\n", + "\n", + "\n", + "qc_psim = QuantumCircuit(2)\n", + "qc_psim.x(0)\n", + "qc_psim.x(1)\n", + "qc_psim.h(0)\n", + "qc_psim.cx(0, 1)\n", + "rho_psim = DensityMatrix.from_instruction(qc_psim)\n", + "\n", + "print(\"Bell States Density Matrices:\")\n", + "print(\"Phi+:\\n\", rho_phip)\n", + "print(\"Phi-:\\n\", rho_phim)\n", + "print(\"Psi+:\\n\", rho_psip)\n", + "print(\"Psi-:\\n\", rho_psim)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "F_in=0.50 F_out=0.900\n", + "F_in=0.60 F_out=0.953\n", + "F_in=0.70 F_out=0.980\n", + "F_in=0.80 F_out=0.993\n", + "F_in=0.90 F_out=0.999\n" + ] + } + ], + "source": [ + "rho_id = DensityMatrix(np.eye(4) / 4)\n", + "\n", + "def isotropic_state(F):\n", + "\t\"\"\"Create an isotropic state with fidelity F to |Φ+>.\"\"\"\n", + "\treturn F * rho_phip + (1 - F) / 3 * (rho_phim + rho_psip + rho_psim)\n", + "\n", + "def bbpssw_circuit():\n", + "\t\"\"\"Construct the BBPSSW purification circuit.\"\"\"\n", + "\tcirc = QuantumCircuit(4, 2)\n", + "\t# CNOTs\n", + "\tcirc.cx(0, 2)\n", + "\tcirc.cx(1, 3)\n", + "\treturn circ\n", + "\n", + "def simulate_bbpssw(F):\n", + "\t\"\"\"Simulate one round of BBPSSW purification on isotropic states.\"\"\"\n", + "\t# Prepare initial state\n", + "\trho1 = isotropic_state(F)\n", + "\trho2 = isotropic_state(F)\n", + "\trho_in = rho1.tensor(rho2)\n", + "\tproj = rho_id.tensor(rho_phip+rho_phim)\n", + "\n", + "\t# Create BBPSSW circuit\n", + "\tcirc = bbpssw_circuit()\n", + "\n", + "\t# Apply circuit to the state\n", + "\trho_out = DensityMatrix(circ).evolve(rho_in)\n", + "\n", + "\t# Trace out measured qubits (2 and 3) over only successful outcomes and renormalize\n", + "\trho_reduced = partial_trace(DensityMatrix(proj.data @ rho_out.data), [2, 3])\n", + "\tnorm = np.trace(rho_reduced.data)\n", + "\trho_reduced = DensityMatrix(rho_reduced.data / norm)\n", + "\n", + "\t# Calculate fidelity with |Φ+>\n", + "\tfid = np.real(np.trace(rho_reduced.data @ rho_phip.data))\n", + "\n", + "\treturn fid, rho_reduced\n", + "\n", + "for F in [0.5, 0.6, 0.7, 0.8, 0.9]:\n", + "\tFo, rho_final = simulate_bbpssw(F)\n", + "\tprint(f\"F_in={F:.2f} F_out={Fo:.3f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/1_Schmidt_decomp.ipynb b/extra_resources/Entanglement_extra/1_Schmidt_decomp.ipynb new file mode 100644 index 0000000..cba2c17 --- /dev/null +++ b/extra_resources/Entanglement_extra/1_Schmidt_decomp.ipynb @@ -0,0 +1,102 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nThe Schmidt decomposition factorizes a bipartite pure state into local bases revealing its entanglement spectrum.\\nComputing the Schmidt coefficients is a quick diagnostic of bipartite entanglement.\\n\\n\\nExecises:\\n- Modify the circuit to produce a partially entangled state by inserting a Ry(θ) on qubit 1 controlled by qubit 0.\\n- Plot entropy vs θ to visualize entanglement tuning.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "The Schmidt decomposition factorizes a bipartite pure state into local bases revealing its entanglement spectrum.\n", + "Computing the Schmidt coefficients is a quick diagnostic of bipartite entanglement.\n", + "\n", + "\n", + "Execises:\n", + "- Modify the circuit to produce a partially entangled state by inserting a Ry(θ) on qubit 1 controlled by qubit 0.\n", + "- Plot entropy vs θ to visualize entanglement tuning.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Schmidt coeffs: [0.707107 0.707107]\n", + "Schmidt entropy (von Neumann of reduced state):\n", + "S(ρ_A) = 1.0\n", + "Von Neumann entropy S(ρ_A) = 1.0\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Bad pipe message: %s [b'he\\r\\nCache-Control: no-cache\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 15_6_1) AppleWeb', b't/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36\\r\\nUpgrade: w', b'socket\\r\\nOrigin: file://\\r\\nSec-WebSocket-Version: 13\\r\\nAccept-Encoding: gzip, deflate, br\\r\\nAccept-Langu']\n", + "Bad pipe message: %s [b'he\\r\\nCache-Control: no-cache\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 15_6_1) AppleWeb', b't/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36\\r\\nUpgrade: w', b'socket\\r\\nOrigin: file://\\r\\nSec-WebSocket-Version: 13\\r\\nAccept-Encoding: gzip, deflate, br\\r\\nAccept-Langu']\n" + ] + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import Statevector, partial_trace, DensityMatrix\n", + "import numpy as np\n", + "\n", + "# Two-qubit entangled state: (|00> + |11>)/sqrt(2)\n", + "qc = QuantumCircuit(2)\n", + "qc.h(0); qc.cx(0,1) # |Φ+>\n", + "\n", + "psi = Statevector.from_instruction(qc) # complex vector of length 4\n", + "vec = psi.data.reshape(2,2) # Reshape into 2x2 matrix for bipartition A|B (qubit 0 as A, qubit 1 as B)\n", + "s = np.linalg.svd(vec, compute_uv=False) # Schmidt coefficients\n", + "print(\"Schmidt coeffs:\", np.round(s,6))\n", + "print(\"Schmidt entropy (von Neumann of reduced state):\")\n", + "p = s**2\n", + "entropy = -np.sum(p * np.log2(p))\n", + "print(\"S(ρ_A) =\", entropy)\n", + "\n", + "# Cross-check via reduced density matrix\n", + "rhoA = partial_trace(DensityMatrix(psi), [1]).data # Trace out qubit 1\n", + "evals = np.linalg.eigvalsh(rhoA)\n", + "S = -np.sum(evals* np.log2(evals))\n", + "print(\"Von Neumann entropy S(ρ_A) =\", S)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/2_locc.ipynb b/extra_resources/Entanglement_extra/2_locc.ipynb new file mode 100644 index 0000000..9ca9226 --- /dev/null +++ b/extra_resources/Entanglement_extra/2_locc.ipynb @@ -0,0 +1,73 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "LOCC cannot create entanglement. Simulate LOCC-like maps (local unitaries + classical randomness) on product states.\n", + "\n", + "Exercises:\n", + "- Add classical mixing over different local unitaries and show separability persists for mixed states.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Entangled after local? False\n", + "Entangled after RXX? True\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import Statevector\n", + "\n", + "def entangled(psi):\n", + " s = np.linalg.svd(psi.data.reshape(2,2), compute_uv=False)\n", + " return abs(s[0]*s[1])>1e-12 # Basically 0 if separable, i.e. not entangled.\n", + "\n", + "psi = Statevector.from_label(\"00\")\n", + "local = QuantumCircuit(2) # A separable state.\n", + "for q in range(2): local.rx(0.7,q); local.ry(0.3,q); local.rz(0.2,q) # Example local unitaries. Change as desired.\n", + "psi_local = psi.evolve(local)\n", + "print(\"Entangled after local?\", entangled(psi_local)) #Whateve separable state, whatever local unitaries, should be False.\n", + "\n", + "ent = QuantumCircuit(2); ent.rxx(0.6,0,1) # An entangling operation.\n", + "psi_ent = psi_local.evolve(ent)\n", + "print(\"Entangled after RXX?\", entangled(psi_ent)) #Whatever entagnled state, whatever locc, should be True." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/3_Renyi_entropy.ipynb b/extra_resources/Entanglement_extra/3_Renyi_entropy.ipynb new file mode 100644 index 0000000..31eb302 --- /dev/null +++ b/extra_resources/Entanglement_extra/3_Renyi_entropy.ipynb @@ -0,0 +1,109 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nRandomized measurements can estimate Rényi-2 entropy using random local Clifford rotations and repeated shots.\\n\\nExercises:\\n- Replace the analytic probabilities with sampled bitstrings (multinomial) to mimic finite shots.\\n- Compare a product state vs. Bell state.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Randomized measurements can estimate Rényi-2 entropy using random local Clifford rotations and repeated shots.\n", + "\n", + "Exercises:\n", + "- Replace the analytic probabilities with sampled bitstrings (multinomial) to mimic finite shots.\n", + "- Compare a product state vs. Bell state.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True ⟨S2⟩ (toy): 1.0000000000000007\n", + "Estimated ⟨S2⟩ (toy): 1.0\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import Statevector, DensityMatrix, partial_trace\n", + "rng = np.random.default_rng(7)\n", + "\n", + "def random_unitary_for_1q():\n", + " # A random unitary on 1 qubit via Euler angles\n", + " a,b,c = rng.random(3)*2*np.pi\n", + " qc = QuantumCircuit(1)\n", + " qc.rx(a,0); qc.ry(b,0); qc.rz(c,0)\n", + " return qc\n", + "\n", + "def renyi2_from_probs(p):\n", + " return -np.log2(np.sum(p**2))\n", + "\n", + "prep = QuantumCircuit(2)\n", + "prep.h(0); prep.cx(0,1)\n", + "\n", + "M = 200\n", + "true_entropy = []\n", + "vals = []\n", + "for _ in range(M):\n", + " #Apply random unitaries\n", + " Ua, Ub = random_unitary_for_1q(), random_unitary_for_1q()\n", + " circ = prep.compose(Ua, qubits=[0]).compose(Ub, qubits=[1])\n", + "\n", + " #Compute true entropy\n", + " psi = Statevector.from_instruction(circ)\n", + " rhoA = partial_trace(DensityMatrix(psi), [1]).data # Trace out qubit 1\n", + " evals = np.linalg.eigvalsh(rhoA)\n", + " true_entropy.append(renyi2_from_probs(evals))\n", + "\n", + " #Compute toy model probabilities\n", + " proba = np.abs(psi.data)**2\n", + " proba_A = np.array([np.sum(proba[0::2]), np.sum(proba[1::2])]) # Marginalize over qubit 1\n", + " proba_A /= np.sum(proba_A) # Normalize in case of bad numerical precision\n", + " X = 2*(proba_A[0]**2 - proba_A[0]*proba_A[1] + proba_A[1]**2) # Formula from DOI: 10.1126/science.aau4963 (Brydges–Elben–Roos–Zoller)\n", + " vals.append(X)\n", + "\n", + "print(\"True ⟨S2⟩ (toy):\", np.mean(true_entropy))\n", + "print(\"Estimated ⟨S2⟩ (toy):\", -np.log2(np.mean(vals)))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/4_Concurrence_negativity.ipynb b/extra_resources/Entanglement_extra/4_Concurrence_negativity.ipynb new file mode 100644 index 0000000..6ff25d5 --- /dev/null +++ b/extra_resources/Entanglement_extra/4_Concurrence_negativity.ipynb @@ -0,0 +1,104 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nConcurrence and (log-)negativity are inexpensive two-qubit entanglement quantifiers suitable for tests and CI.\\n\\nExercises:\\n- Plot C and N vs noise parameter p and compare robustness.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Concurrence and (log-)negativity are inexpensive two-qubit entanglement quantifiers suitable for tests and CI.\n", + "\n", + "Exercises:\n", + "- Plot C and N vs noise parameter p and compare robustness.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "p=1.0 C=1.000 N=0.500\n", + "p=0.9 C=0.850 N=0.425\n", + "p=0.8 C=0.700 N=0.350\n", + "p=0.6 C=0.400 N=0.200\n", + "p=0.4 C=0.100 N=0.050\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from qiskit.quantum_info import Statevector, DensityMatrix\n", + "\n", + "Y = np.array([[0,-1j],[1j,0]])\n", + "Y2 = np.kron(Y,Y)\n", + "\n", + "phi = Statevector([1,0,0,1])/np.sqrt(2)\n", + "rho_phi = DensityMatrix(phi).data\n", + "I4 = np.eye(4)/4\n", + "\n", + "def isotropic(p):\n", + " return p*rho_phi + (1-p)*I4 #p is the depolarization parameter\n", + "\n", + "def concurrence(rho):\n", + " # Wootters formula\n", + " R = rho @ Y2 @ rho.conj() @ Y2\n", + " evals = np.sort(np.real(np.sqrt(np.maximum(0, np.linalg.eigvals(R)))))\n", + " return max(0, evals[-1] - np.sum(evals[:-1]))\n", + "\n", + "def negativity(rho):\n", + " rho_pt = DensityMatrix.partial_transpose(DensityMatrix(rho), [1]).data\n", + " eig = np.linalg.eigvalsh(rho_pt)\n", + " return np.sum(np.abs(eig[eig<0]))\n", + "\n", + "for p in [1.0,0.9,0.8,0.6,0.4]:\n", + " rho = isotropic(p)\n", + " print(f\"p={p} C={concurrence(rho):.3f} N={negativity(rho):.3f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/5_Bell_test.ipynb b/extra_resources/Entanglement_extra/5_Bell_test.ipynb new file mode 100644 index 0000000..477aa46 --- /dev/null +++ b/extra_resources/Entanglement_extra/5_Bell_test.ipynb @@ -0,0 +1,100 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + "Compute the CHSH S-parameter for a Bell state under various noise models.\n", + "\n", + "Exercises:\n", + "- Replace the analytic scaling with simulated Kraus noise channels.\n", + "- Try amplitude damping and compare.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "S = 2.8284271247461903 (Tsirelson bound!)\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import SparsePauliOp\n", + "from qiskit_aer import AerSimulator\n", + "from qiskit_aer.primitives import EstimatorV2 as AerEstimator \n", + "from qiskit.transpiler import generate_preset_pass_manager \n", + "\n", + "backend = AerSimulator(method=\"statevector\")\n", + "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n", + "est = AerEstimator.from_backend(backend) \n", + "\n", + "\n", + "def E(theta_a, theta_b):\n", + " #correlator (= p_00 + p_11 - p_10 - p_01) with rotations by where |psi> = U(theta_a) \\otimes U(theta_b)|Φ+>, that would be \"the device preparation state\"\n", + " qc = QuantumCircuit(2)\n", + " qc.h(0); qc.cx(0,1) #Bell state\n", + " qc.ry(theta_a,0); qc.ry(theta_b,1) # modelize crudely the internal state of the device\n", + " isa_qc = pm.run(qc)\n", + " ob = SparsePauliOp(\"ZZ\")\n", + " isa_ZZ = ob.apply_layout(isa_qc.layout)\n", + " pub = [(isa_qc,isa_ZZ)]\n", + " return AerEstimator().run(pub).result()[0].data.evs\n", + "\n", + "a0, a1 = 0, np.pi/2\n", + "b0, b1 = np.pi/4, -np.pi/4\n", + "S = E(a0,b0)+E(a0,b1)+E(a1,b0)-E(a1,b1)\n", + "if S >= 2:\n", + " if abs(S - 2*np.sqrt(2)) < 1e-3:\n", + " print(\"S =\", S, \" (Tsirelson bound!)\")\n", + " elif S < 2*np.sqrt(2):\n", + " print(\"S =\", S, \" (CHSH violation!)\")\n", + " else:\n", + " print(\"S =\", S, \" (error!)\")\n", + "elif S < 2:\n", + " print(\"S =\", S, \" (no CHSH violation)\")\n", + "else:\n", + " print(\"S =\", S, \" (error!)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/6_Entanglement_witnesses.ipynb b/extra_resources/Entanglement_extra/6_Entanglement_witnesses.ipynb new file mode 100644 index 0000000..895cfdb --- /dev/null +++ b/extra_resources/Entanglement_extra/6_Entanglement_witnesses.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nLinear witnesses provide simple measurement schedules to flag entanglement without full tomography.\\n\\nExercises:\\n- Decompose W into Pauli strings and count measurement groups.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Linear witnesses provide simple measurement schedules to flag entanglement without full tomography.\n", + "\n", + "Exercises:\n", + "- Decompose W into Pauli strings and count measurement groups.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " = -0.5\n" + ] + } + ], + "source": [ + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import SparsePauliOp\n", + "from qiskit_aer import AerSimulator\n", + "from qiskit_aer.primitives import EstimatorV2 as AerEstimator \n", + "from qiskit.transpiler import generate_preset_pass_manager \n", + "\n", + "backend = AerSimulator(method=\"statevector\")\n", + "pm = generate_preset_pass_manager(backend=backend, optimization_level=1)\n", + "est = AerEstimator.from_backend(backend) \n", + "\n", + "proj = 0.25*SparsePauliOp.from_list([(\"II\",1),(\"XX\",1),(\"YY\",-1),(\"ZZ\",1)]) # = |Φ+><Φ+|\n", + "prep = QuantumCircuit(2); prep.h(0); prep.cx(0,1) # prepares |Φ+> change to whatever\n", + "\n", + "isa_qc = pm.run(prep)\n", + "isa_obs = proj.apply_layout(isa_qc.layout)\n", + "pub = [(isa_qc,isa_obs)]\n", + "exp_proj = AerEstimator().run(pub).result()[0].data.evs\n", + "\n", + "W = 0.5 - exp_proj # W = 0.5*I - |Φ+><Φ+| is a 2 qubits entanglement witness\n", + "print(\" =\", W)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/7_Separability.ipynb b/extra_resources/Entanglement_extra/7_Separability.ipynb new file mode 100644 index 0000000..1f63723 --- /dev/null +++ b/extra_resources/Entanglement_extra/7_Separability.ipynb @@ -0,0 +1,93 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nFor 2×2 and 2×3 systems, the Positive Partial Transpose (PPT) criterion is necessary and sufficient for separability.\\n\\nExercises:\\n- Extend to a 2×3 example by padding qubits or adding a qutrit toy model with dims=(2,3).\\n- Wrap into a helper function `is_entangled_ppt(rho, dims)`.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "For 2×2 and 2×3 systems, the Positive Partial Transpose (PPT) criterion is necessary and sufficient for separability.\n", + "\n", + "Exercises:\n", + "- Extend to a 2×3 example by padding qubits or adding a qutrit toy model with dims=(2,3).\n", + "- Wrap into a helper function `is_entangled_ppt(rho, dims)`.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "p=1.0 min eig(ρ^T_B)=-5.000000e-01 ENTANGLED\n", + "p=0.8 min eig(ρ^T_B)=-3.500000e-01 ENTANGLED\n", + "p=0.6 min eig(ρ^T_B)=-2.000000e-01 ENTANGLED\n", + "p=0.4 min eig(ρ^T_B)=-5.000000e-02 ENTANGLED\n" + ] + } + ], + "source": [ + "import numpy as np\n", + "from qiskit.quantum_info import Statevector, DensityMatrix\n", + "\n", + "phi = Statevector([1,0,0,1])/np.sqrt(2)\n", + "rho_pure = DensityMatrix(phi).data\n", + "I4 = np.eye(4)/4\n", + "\n", + "def isotropic(p):\n", + " # |Φ+> density matrix with simple depolarizing noise when p<1\n", + " return p*rho_pure + (1-p)*I4\n", + "\n", + "for p in [1.0, 0.8, 0.6, 0.4]:\n", + " rho = isotropic(p)\n", + " rho_pt = DensityMatrix.partial_transpose(DensityMatrix(rho), [1]).data\n", + " eig = np.linalg.eigvalsh(rho_pt)\n", + " print(f\"p={p} min eig(ρ^T_B)={eig.min(): .6e} {'ENTANGLED' if eig.min()< -1e-10 else 'PPT'}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/extra_resources/Entanglement_extra/8_Area_law.ipynb b/extra_resources/Entanglement_extra/8_Area_law.ipynb new file mode 100644 index 0000000..da3e257 --- /dev/null +++ b/extra_resources/Entanglement_extra/8_Area_law.ipynb @@ -0,0 +1,146 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nEntanglement growth in local circuits typically obeys light-cone/area-law constraints, informing depth and layout decisions.\\n\\nExercises:\\n- Sweep θ and plot the entropy curves; observe linear growth then saturation.\\n'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Entanglement growth in local circuits typically obeys light-cone/area-law constraints, informing depth and layout decisions.\n", + "\n", + "Exercises:\n", + "- Sweep θ and plot the entropy curves; observe linear growth then saturation.\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "from qiskit import QuantumCircuit\n", + "from qiskit.quantum_info import Statevector, DensityMatrix, partial_trace\n", + "\n", + "def layer(qc, n, theta):\n", + " for q in range(n): qc.ry(np.pi/4,q)\n", + " for i in range(0,n-1,2): qc.rxx(theta,i,i+1)\n", + " for i in range(1,n-1,2): qc.rxx(theta,i,i+1)\n", + " return qc\n", + "\n", + "def mid_entropy(qc, n):\n", + " psi = Statevector.from_instruction(qc)\n", + " rhoA = partial_trace(DensityMatrix(psi), list(range(n//2))).data # Trace out qubit 1\n", + " evals = np.linalg.eigvalsh(rhoA)\n", + " evals = evals[evals>1e-12]\n", + " return sum(-evals*np.log2(evals))\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A layer for 8 qubits:\n", + " ┌─────────┐┌───────────┐ \n", + "q_0: ┤ Ry(π/4) ├┤0 ├─────────────\n", + " ├─────────┤│ Rxx(π/8) │┌───────────┐\n", + "q_1: ┤ Ry(π/4) ├┤1 ├┤0 ├\n", + " ├─────────┤├───────────┤│ Rxx(π/8) │\n", + "q_2: ┤ Ry(π/4) ├┤0 ├┤1 ├\n", + " ├─────────┤│ Rxx(π/8) │├───────────┤\n", + "q_3: ┤ Ry(π/4) ├┤1 ├┤0 ├\n", + " ├─────────┤├───────────┤│ Rxx(π/8) │\n", + "q_4: ┤ Ry(π/4) ├┤0 ├┤1 ├\n", + " ├─────────┤│ Rxx(π/8) │├───────────┤\n", + "q_5: ┤ Ry(π/4) ├┤1 ├┤0 ├\n", + " ├─────────┤├───────────┤│ Rxx(π/8) │\n", + "q_6: ┤ Ry(π/4) ├┤0 ├┤1 ├\n", + " ├─────────┤│ Rxx(π/8) │└───────────┘\n", + "q_7: ┤ Ry(π/4) ├┤1 ├─────────────\n", + " └─────────┘└───────────┘ \n" + ] + } + ], + "source": [ + "print(\"A layer for 8 qubits:\")\n", + "layer_8 = layer(QuantumCircuit(8),8, np.pi/8)\n", + "print(layer_8)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Depth vs mid-cut entropy:\n", + "0 0.0\n", + "1 0.024978016784828812\n", + "2 0.021772544197811727\n", + "3 0.0751972971934856\n", + "4 0.22373092024896266\n", + "5 0.29348380892044534\n", + "6 0.297321075807504\n", + "7 0.39862734239903624\n", + "8 0.5430823309221445\n" + ] + } + ], + "source": [ + "n=8; L=8; theta=0.2\n", + "qc = QuantumCircuit(n)\n", + "curve = []\n", + "for d in range(L+1):\n", + " curve.append((d, mid_entropy(qc,n)))\n", + " if d