mirror of
https://github.com/quantumjim/Quantum-Computation-course-Basel.git
synced 2025-11-24 01:14:30 +01:00
Added entanglement lecture applications notebooks
This commit is contained in:
@@ -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<L:\n",
|
||||
" psi_he = psi_he.evolve(hea_layer(n,theta))\n",
|
||||
" psi_pair = psi_pair.evolve(pair_layer(n,theta))\n",
|
||||
"\n",
|
||||
"print(\"HEA:\", hea)\n",
|
||||
"print(\"Pair:\", pair)\n",
|
||||
"print(\"Overlap:\", overlap)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hea_layer_alt(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): \n",
|
||||
" if i % 2 == 0:\n",
|
||||
" qc.rxx(theta,i,i+1)\n",
|
||||
" else:\n",
|
||||
" qc.ryy(theta,i,i+1)\n",
|
||||
" return qc\n",
|
||||
"\n",
|
||||
"def pair_layer_alt(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.ryy(theta,i,i+1)\n",
|
||||
" return qc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"HEA: [(0, np.float64(0.0)), (1, np.float64(0.11585759836549395)), (2, np.float64(0.13666544165112313)), (3, np.float64(0.31175719823869114)), (4, np.float64(0.5268886662772366)), (5, np.float64(0.7065218696053106)), (6, np.float64(0.8443450713092262))]\n",
|
||||
"Pair: [(0, np.float64(0.0)), (1, np.float64(0.09273514883335729)), (2, np.float64(0.1651926342187447)), (3, np.float64(0.414436373899551)), (4, np.float64(0.6577144016537176)), (5, np.float64(0.8624055109775808)), (6, np.float64(0.937592949714684))]\n",
|
||||
"Overlap: [(0, np.float64(1.0)), (1, np.float64(0.982439264963681)), (2, np.float64(0.9542857216675236)), (3, np.float64(0.9274834863273084)), (4, np.float64(0.9189695626001178)), (5, np.float64(0.9166720426781583)), (6, np.float64(0.9168803426989058))]\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<L:\n",
|
||||
" psi_he = psi_he.evolve(hea_layer_alt(n,theta))\n",
|
||||
" psi_pair = psi_pair.evolve(pair_layer_alt(n,theta))\n",
|
||||
"\n",
|
||||
"print(\"HEA:\", hea)\n",
|
||||
"print(\"Pair:\", pair)\n",
|
||||
"print(\"Overlap:\", overlap)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"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
|
||||
}
|
||||
105
extra_resources/Entanglement_extra/11_GHZ_W.ipynb
Normal file
105
extra_resources/Entanglement_extra/11_GHZ_W.ipynb
Normal file
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'\\n### Overview\\nContrast GHZ and W states: robustness to loss and pairwise correlations differ.\\n\\nExercises:\\n- Trace out one qubit and compare the remaining 2-qubit entanglement.\\n'"
|
||||
]
|
||||
},
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"\"\"\"\n",
|
||||
"### Overview\n",
|
||||
"Contrast GHZ and W states: robustness to loss and pairwise correlations differ.\n",
|
||||
"\n",
|
||||
"Exercises:\n",
|
||||
"- Trace out one qubit and compare the remaining 2-qubit entanglement.\n",
|
||||
"\"\"\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Single qubit reductions:\n",
|
||||
"GHZ (1.0000000000000002+0j) (1.0000000000000002+0j) (1.0000000000000002+0j)\n",
|
||||
"W (0.942809041582063+0j) (0.942809041582063+0j) (0.942809041582063+0j)\n",
|
||||
"\n",
|
||||
"Two qubit reductions:\n",
|
||||
"GHZ (1.0000000000000002+0j) (1.0000000000000002+0j) (1.0000000000000002+0j)\n",
|
||||
"W (0.942809041582063+0j) (0.942809041582063+0j) (0.942809041582063+0j)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import numpy as np\n",
|
||||
"from qiskit import QuantumCircuit\n",
|
||||
"from qiskit.quantum_info import Statevector, partial_trace, DensityMatrix\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def concurrence(reduced_rho):\n",
|
||||
" return np.sqrt(2*(1-np.trace(reduced_rho @ reduced_rho)))\n",
|
||||
"\n",
|
||||
"qc_g = QuantumCircuit(3); qc_g.h(0); qc_g.cx(0,1); qc_g.cx(1,2) #GHZ state (3 qubits)= (|000> + |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
|
||||
}
|
||||
224
extra_resources/Entanglement_extra/12_Purification.ipynb
Normal file
224
extra_resources/Entanglement_extra/12_Purification.ipynb
Normal file
@@ -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
|
||||
}
|
||||
102
extra_resources/Entanglement_extra/1_Schmidt_decomp.ipynb
Normal file
102
extra_resources/Entanglement_extra/1_Schmidt_decomp.ipynb
Normal file
@@ -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
|
||||
}
|
||||
73
extra_resources/Entanglement_extra/2_locc.ipynb
Normal file
73
extra_resources/Entanglement_extra/2_locc.ipynb
Normal file
@@ -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
|
||||
}
|
||||
109
extra_resources/Entanglement_extra/3_Renyi_entropy.ipynb
Normal file
109
extra_resources/Entanglement_extra/3_Renyi_entropy.ipynb
Normal file
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
100
extra_resources/Entanglement_extra/5_Bell_test.ipynb
Normal file
100
extra_resources/Entanglement_extra/5_Bell_test.ipynb
Normal file
@@ -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 <psi| ZZ |psi> (= 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
|
||||
}
|
||||
@@ -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": [
|
||||
"<W> = -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> =\", 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
|
||||
}
|
||||
93
extra_resources/Entanglement_extra/7_Separability.ipynb
Normal file
93
extra_resources/Entanglement_extra/7_Separability.ipynb
Normal file
@@ -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
|
||||
}
|
||||
146
extra_resources/Entanglement_extra/8_Area_law.ipynb
Normal file
146
extra_resources/Entanglement_extra/8_Area_law.ipynb
Normal file
@@ -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<L: qc = layer(qc,n,theta)\n",
|
||||
"\n",
|
||||
"print(\"Depth vs mid-cut entropy:\")\n",
|
||||
"for L,S in curve:\n",
|
||||
" print(L,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
|
||||
}
|
||||
Reference in New Issue
Block a user