mirror of
https://github.com/quantumjim/Quantum-Computation-course-Basel.git
synced 2026-10-07 07:19:40 +02:00
scaffolding-2026
This commit is contained in:
Vendored
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user