{
const container = html`<div style="max-width: 720px; margin: 0 auto;">
<h4 style="text-align:center; margin-bottom: 4px;">Logical Basis States</h4>
<p style="text-align:center; color:#666; font-size:0.9em; margin-top:0;">
Each logical basis state is a superposition of physical-qubit computational basis states.
</p>
<table style="width:100%; border-collapse:collapse; font-family: 'CMU Serif', Georgia, serif; font-size: 1.05em;">
<thead>
<tr style="border-bottom: 2px solid #333;">
<th style="padding:10px 12px; text-align:center; width:18%;">Logical State</th>
<th style="padding:10px 12px; text-align:left;">Physical Qubit Decomposition</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid #ddd; background:#f8fbff;">
<td style="padding:10px 12px; text-align:center; font-weight:600;">|00⟩<sub>L</sub></td>
<td style="padding:10px 12px; font-family: monospace;">
<span style="color:#2563eb;">(|0000⟩ + |1111⟩)</span> / √2
</td>
</tr>
<tr style="border-bottom:1px solid #ddd;">
<td style="padding:10px 12px; text-align:center; font-weight:600;">|01⟩<sub>L</sub></td>
<td style="padding:10px 12px; font-family: monospace;">
<span style="color:#2563eb;">(|0011⟩ + |1100⟩)</span> / √2
</td>
</tr>
<tr style="border-bottom:1px solid #ddd; background:#f8fbff;">
<td style="padding:10px 12px; text-align:center; font-weight:600;">|10⟩<sub>L</sub></td>
<td style="padding:10px 12px; font-family: monospace;">
<span style="color:#2563eb;">(|0101⟩ + |1010⟩)</span> / √2
</td>
</tr>
<tr style="border-bottom:1px solid #ddd;">
<td style="padding:10px 12px; text-align:center; font-weight:600;">|11⟩<sub>L</sub></td>
<td style="padding:10px 12px; font-family: monospace;">
<span style="color:#2563eb;">(|0110⟩ + |1001⟩)</span> / √2
</td>
</tr>
</tbody>
</table>
<p style="color:#555; font-size:0.85em; margin-top:8px; text-align:center;">
Notice: every basis state is a <em>cat state</em> — an equal superposition of a bitstring and its complement.
This is precisely what makes both X⊗4 and Z⊗4 stabilize the code space.
</p>
</div>`;
return container;
}The [[4,2,2]] Error Detection Code
1. The [[4,2,2]] Code Space
The [[4,2,2]] code encodes 2 logical qubits into 4 physical qubits. It is the smallest quantum error-detecting code and can detect any single-qubit error.
The code is defined by two stabilizer generators:
\[S_X = X^{\otimes 4} = X_1 X_2 X_3 X_4, \qquad S_Z = Z^{\otimes 4} = Z_1 Z_2 Z_3 Z_4\]
The code space consists of all 4-qubit states that are simultaneous \(+1\) eigenstates of both \(S_X\) and \(S_Z\). Because we have 2 stabilizers acting on 4 qubits, the code space is \(2^{4-2} = 4\)-dimensional, encoding exactly 2 logical qubits.
2. Error Detection Simulator
Apply a single-qubit error to the logical state \(|00\rangle_L\) and observe how the stabilizer measurements detect it.
viewof selectedError = Inputs.radio(
[
"No error",
"X on qubit 1",
"X on qubit 2",
"Z on qubit 1",
"Z on qubit 2",
"Y on qubit 1"
],
{
value: "No error",
label: "Apply error"
}
)errorInfo = {
const errors = {
"No error": {
label: "None",
xParity: +1,
zParity: +1,
stateLabel: "|00⟩_L = (|0000⟩ + |1111⟩) / √2",
inCodeSpace: true,
explanation: "No error applied. The state remains in the code space. Both stabilizers measure +1."
},
"X on qubit 1": {
label: "X₁",
xParity: +1,
zParity: -1,
stateLabel: "X₁|00⟩_L = (|1000⟩ + |0111⟩) / √2",
inCodeSpace: false,
explanation: "A single X error flips one qubit in the Z basis. The Z⊗4 parity flips to −1 (odd number of 1s changed), while X⊗4 remains +1."
},
"X on qubit 2": {
label: "X₂",
xParity: +1,
zParity: -1,
stateLabel: "X₂|00⟩_L = (|0100⟩ + |1011⟩) / √2",
inCodeSpace: false,
explanation: "A single X error on any qubit flips the Z⊗4 parity to −1. The X⊗4 parity is unaffected because X commutes with X."
},
"Z on qubit 1": {
label: "Z₁",
xParity: -1,
zParity: +1,
stateLabel: "Z₁|00⟩_L = (|0000⟩ − |1111⟩) / √2",
inCodeSpace: false,
explanation: "A single Z error introduces a phase flip. The X⊗4 parity flips to −1, while Z⊗4 remains +1 because Z commutes with Z."
},
"Z on qubit 2": {
label: "Z₂",
xParity: -1,
zParity: +1,
stateLabel: "Z₂|00⟩_L = (|0000⟩ − |1111⟩) / √2",
inCodeSpace: false,
explanation: "Same as Z on qubit 1 for this state — a single Z error on any qubit flips X⊗4 parity to −1."
},
"Y on qubit 1": {
label: "Y₁ = iX₁Z₁",
xParity: -1,
zParity: -1,
stateLabel: "Y₁|00⟩_L = i(|1000⟩ − |0111⟩) / √2",
inCodeSpace: false,
explanation: "Y = iXZ combines both types of error. BOTH parities flip to −1. The code detects this as an error, but cannot distinguish it from separate X and Z errors on different qubits."
}
};
return errors[selectedError];
}{
const detected = !errorInfo.inCodeSpace;
const bgColor = detected ? "#fef2f2" : "#f0fdf4";
const borderColor = detected ? "#fca5a5" : "#86efac";
const statusColor = detected ? "#dc2626" : "#16a34a";
const statusText = detected ? "ERROR DETECTED" : "NO ERROR";
const xColor = errorInfo.xParity === +1 ? "#16a34a" : "#dc2626";
const zColor = errorInfo.zParity === +1 ? "#16a34a" : "#dc2626";
const container = html`<div style="max-width: 680px; margin: 0 auto;">
<div style="background:${bgColor}; border:2px solid ${borderColor}; border-radius:12px; padding:24px; margin-bottom:16px;">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:16px;">
<span style="font-size:1.3em; font-weight:700; color:${statusColor};">${statusText}</span>
<span style="font-size:0.95em; color:#555;">Error applied: <strong>${errorInfo.label}</strong></span>
</div>
<div style="font-family:monospace; font-size:1.1em; background:white; padding:12px 16px; border-radius:8px; margin-bottom:16px; border:1px solid #e5e7eb;">
${errorInfo.stateLabel}
</div>
<div style="display:flex; gap:24px; margin-bottom:16px;">
<div style="flex:1; background:white; border-radius:8px; padding:14px; text-align:center; border:2px solid ${xColor}40;">
<div style="font-size:0.85em; color:#666; margin-bottom:4px;">X⊗4 stabilizer</div>
<div style="font-size:1.8em; font-weight:700; color:${xColor};">
${errorInfo.xParity === +1 ? "+1" : "−1"}
</div>
</div>
<div style="flex:1; background:white; border-radius:8px; padding:14px; text-align:center; border:2px solid ${zColor}40;">
<div style="font-size:0.85em; color:#666; margin-bottom:4px;">Z⊗4 stabilizer</div>
<div style="font-size:1.8em; font-weight:700; color:${zColor};">
${errorInfo.zParity === +1 ? "+1" : "−1"}
</div>
</div>
</div>
<p style="color:#444; font-size:0.93em; line-height:1.5; margin:0;">
${errorInfo.explanation}
</p>
</div>
<div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:8px; padding:16px; font-size:0.88em; color:#475569; line-height:1.6;">
<strong>Summary of detection rules:</strong><br>
• A single <strong>X error</strong> anticommutes with Z⊗4 → flips Z⊗4 parity to −1.<br>
• A single <strong>Z error</strong> anticommutes with X⊗4 → flips X⊗4 parity to −1.<br>
• A single <strong>Y error</strong> (= iXZ) anticommutes with both → flips <em>both</em> parities to −1.<br>
• The code <em>detects</em> but does not <em>correct</em>: it flags that an error occurred, and the state is discarded (post-selected away).
</div>
</div>`;
return container;
}3. Logical Bell State Fidelity
The power of error detection via post-selection: even a simple [[4,2,2]] code can produce logical Bell pairs with fidelity far exceeding the raw physical fidelity. Adjust the physical error rates below to see how post-selection boosts fidelity.
viewof gateFidelity = Inputs.range([0.95, 1.0], {
value: 0.993,
step: 0.001,
label: "Physical gate fidelity"
})viewof measFidelity = Inputs.range([0.95, 1.0], {
value: 0.998,
step: 0.001,
label: "Measurement fidelity"
})fidelityResults = {
// Simple depolarizing noise model for a Bell-state circuit on the [[4,2,2]] code.
//
// Physical Bell pair: needs ~2 CNOT gates + single-qubit gates.
// We model the physical Bell pair fidelity as the product of
// two two-qubit gate fidelities and one measurement per qubit.
const nGatesPhysical = 2;
const physBellFidelity = Math.pow(gateFidelity, nGatesPhysical) * Math.pow(measFidelity, 2);
// Logical Bell pair on [[4,2,2]]:
// The encoding + transversal CNOT circuit uses roughly 8 two-qubit gates
// and 4 stabilizer measurements (2 per block). Under depolarizing noise,
// the dominant error contribution is from these gates.
//
// With post-selection on correct stabilizer outcomes, any single fault
// is caught. The logical error rate therefore scales as p^2 (second order),
// where p = 1 - gateFidelity.
const p = 1 - gateFidelity;
const pm = 1 - measFidelity;
// Number of fault locations in the encoded Bell circuit
const nFaultLocations = 8;
const nMeasLocations = 4;
// Post-selection acceptance probability (first order: reject single faults)
const pReject = nFaultLocations * p + nMeasLocations * pm;
const pAccept = Math.max(0.01, 1 - pReject);
// Logical infidelity after post-selection: leading order is O(p^2)
// We use a combinatorial estimate: pairs of faults that go undetected
const nUndetectedPairs = Math.floor(nFaultLocations * (nFaultLocations - 1) / 6);
const logicalInfidelity = nUndetectedPairs * p * p + nMeasLocations * pm * pm;
const logBellFidelity = Math.min(1.0, Math.max(0, 1 - logicalInfidelity));
return {
physical: physBellFidelity,
logical: logBellFidelity,
pAccept: pAccept,
gain: logBellFidelity - physBellFidelity
};
}{
const phys = fidelityResults.physical;
const log = fidelityResults.logical;
const gain = fidelityResults.gain;
const pAccept = fidelityResults.pAccept;
const gainColor = gain > 0 ? "#16a34a" : "#dc2626";
const gainSign = gain > 0 ? "+" : "";
const barWidth = 480;
const barH = 36;
const container = html`<div style="max-width: 680px; margin: 0 auto;">
<div style="display:flex; gap:20px; margin-bottom:20px; flex-wrap:wrap;">
<div style="flex:1; min-width:200px; background:#eff6ff; border:1px solid #bfdbfe; border-radius:10px; padding:18px; text-align:center;">
<div style="font-size:0.82em; color:#64748b; margin-bottom:6px;">Physical Bell Fidelity</div>
<div style="font-size:2em; font-weight:700; color:#2563eb;">${(phys * 100).toFixed(1)}%</div>
</div>
<div style="flex:1; min-width:200px; background:#f0fdf4; border:1px solid #86efac; border-radius:10px; padding:18px; text-align:center;">
<div style="font-size:0.82em; color:#64748b; margin-bottom:6px;">Logical Bell Fidelity (post-selected)</div>
<div style="font-size:2em; font-weight:700; color:#16a34a;">${(log * 100).toFixed(1)}%</div>
</div>
</div>
<div style="text-align:center; margin-bottom:20px;">
<span style="font-size:1.1em; font-weight:600; color:${gainColor};">
Fidelity gain: ${gainSign}${(gain * 100).toFixed(2)} percentage points
</span>
<span style="font-size:0.9em; color:#64748b; margin-left:12px;">
(acceptance rate: ${(pAccept * 100).toFixed(1)}%)
</span>
</div>
<svg width="${barWidth + 120}" height="${2 * barH + 60}" style="display:block; margin:0 auto;">
<!-- Physical bar -->
<text x="0" y="${barH / 2 + 18}" font-size="13" fill="#555" font-weight="600">Physical</text>
<rect x="70" y="${14}" width="${barWidth}" height="${barH}" rx="5" fill="#e2e8f0"/>
<rect x="70" y="${14}" width="${barWidth * phys}" height="${barH}" rx="5" fill="#3b82f6"/>
<text x="${72 + barWidth * phys}" y="${barH / 2 + 18}" font-size="12" fill="#1e40af" font-weight="600">
${(phys * 100).toFixed(1)}%
</text>
<!-- Logical bar -->
<text x="0" y="${barH + 30 + barH / 2 + 4}" font-size="13" fill="#555" font-weight="600">Logical</text>
<rect x="70" y="${barH + 30}" width="${barWidth}" height="${barH}" rx="5" fill="#e2e8f0"/>
<rect x="70" y="${barH + 30}" width="${barWidth * log}" height="${barH}" rx="5" fill="#22c55e"/>
<text x="${72 + barWidth * log}" y="${barH + 30 + barH / 2 + 4}" font-size="12" fill="#15803d" font-weight="600">
${(log * 100).toFixed(1)}%
</text>
</svg>
<div style="background:#fffbeb; border:1px solid #fde68a; border-radius:8px; padding:14px; margin-top:18px; font-size:0.88em; color:#92400e; line-height:1.6;">
<strong>Reference from the paper:</strong> With physical gate fidelities around 99.3% and measurement fidelity ~99.8%,
the experiment achieved <strong>physical Bell fidelity = 88.5%</strong> and
<strong>logical Bell fidelity = 99.0%</strong> after post-selection on correct stabilizer outcomes.
The gain from error detection was over <strong>10 percentage points</strong>.
</div>
</div>`;
return container;
}4. Flying Ancilla Protocol
In the velocity-enabled architecture, a flying ancilla atom physically moves past the data qubits to perform stabilizer measurements. This avoids the need for static long-range connectivity. Below is an animated visualization of the \(Z^{\otimes 4}\) stabilizer measurement protocol.
viewof ancillaControl = {
const div = html`<div style="display:flex; align-items:center; gap:12px; max-width:680px; margin:0 auto 8px auto;">
<button id="btn-reset" style="padding:6px 16px; border-radius:6px; border:1px solid #dc2626; background:#fef2f2; color:#dc2626; cursor:pointer; font-size:0.92em; font-weight:600;">⏮ Reset</button>
<button id="btn-step" style="padding:6px 16px; border-radius:6px; border:1px solid #3b82f6; background:#eff6ff; color:#2563eb; cursor:pointer; font-weight:600; font-size:0.92em;">Step ▶</button>
<button id="btn-auto" style="padding:6px 16px; border-radius:6px; border:1px solid #16a34a; background:#f0fdf4; color:#16a34a; cursor:pointer; font-size:0.92em;">▶▶ Auto-play</button>
<span id="step-label" style="font-size:0.9em; color:#64748b; margin-left:8px;">Step 0 / 7</span>
</div>`;
let step = 0;
const maxStep = 7;
let autoInterval = null;
function update() {
div.querySelector("#step-label").textContent = `Step ${step} / ${maxStep}`;
div.value = step;
div.dispatchEvent(new Event("input", {bubbles: true}));
}
div.querySelector("#btn-step").onclick = () => {
if (autoInterval) { clearInterval(autoInterval); autoInterval = null; }
if (step < maxStep) step++;
update();
};
div.querySelector("#btn-reset").onclick = () => {
if (autoInterval) { clearInterval(autoInterval); autoInterval = null; }
step = 0;
update();
};
div.querySelector("#btn-auto").onclick = () => {
if (autoInterval) { clearInterval(autoInterval); autoInterval = null; return; }
step = 0;
update();
autoInterval = setInterval(() => {
if (step < maxStep) { step++; update(); }
else { clearInterval(autoInterval); autoInterval = null; }
}, 900);
};
div.value = step;
return div;
}{
const step = ancillaControl;
const W = 680, H = 320;
const qY = 160;
const qR = 22;
const aR = 16;
const startX = 80;
const spacing = 130;
const ancStartX = startX - 70;
const qx = [0, 1, 2, 3].map(i => startX + i * spacing);
const ancillaPositions = [
ancStartX, ancStartX, qx[0], qx[1], qx[2], qx[3], qx[3] + 70, qx[3] + 70
];
const ancX = ancillaPositions[step];
const ancY = qY - 70;
const stepDescriptions = [
"Ancilla qubit initialized in |0⟩, at rest to the left.",
"Ancilla is selectively excited to the Rydberg state.",
"Ancilla flies to data qubit 1 — CZ gate applied.",
"Ancilla flies to data qubit 2 — CZ gate applied.",
"Ancilla flies to data qubit 3 — CZ gate applied.",
"Ancilla flies to data qubit 4 — CZ gate applied.",
"Ancilla is selectively measured.",
"Syndrome result: Z⊗4 = +1 (no error detected)."
];
// Build SVG as a single string to avoid namespace issues
let s = `<svg width="${W}" height="${H}" style="display:block; margin:0 auto; background:#fafbfd; border:1px solid #e2e8f0; border-radius:10px;">`;
// Title
s += `<text x="${W/2}" y="28" text-anchor="middle" font-size="14" fill="#334155" font-weight="600">Flying Ancilla — Z⊗4 Stabilizer Measurement</text>`;
// Ancilla rail
s += `<line x1="${ancStartX}" y1="${ancY}" x2="${qx[3] + 80}" y2="${ancY}" stroke="#cbd5e1" stroke-width="1.5" stroke-dasharray="6,4"/>`;
s += `<text x="${ancStartX}" y="${ancY + 14}" font-size="10" fill="#94a3b8">ancilla rail</text>`;
// CZ gate connection lines
for (let i = 0; i < 4; i++) {
const gateStep = i + 2;
if (step >= gateStep) {
const dash = step === gateStep ? "none" : "4,3";
const op = step === gateStep ? 1 : 0.4;
const opText = step === gateStep ? 1 : 0.5;
s += `<line x1="${qx[i]}" y1="${ancY + aR}" x2="${qx[i]}" y2="${qY - qR}" stroke="#f59e0b" stroke-width="2.5" stroke-dasharray="${dash}" opacity="${op}"/>`;
s += `<text x="${qx[i] + 12}" y="${(ancY + qY) / 2 + 4}" font-size="10" fill="#d97706" font-weight="600" opacity="${opText}">CZ</text>`;
}
}
// Data qubits
for (let i = 0; i < 4; i++) {
const gateStep = i + 2;
const isActive = step === gateStep;
const fillColor = isActive ? "#1d4ed8" : "#3b82f6";
const r = isActive ? qR + 3 : qR;
const op = isActive ? 1 : 0.8;
s += `<circle cx="${qx[i]}" cy="${qY}" r="${r}" fill="${fillColor}" opacity="${op}"/>`;
s += `<text x="${qx[i]}" y="${qY + 5}" text-anchor="middle" font-size="14" fill="white" font-weight="700">|0⟩</text>`;
}
// Data qubit labels
for (let i = 0; i < 4; i++) {
s += `<text x="${qx[i]}" y="${qY + qR + 20}" text-anchor="middle" font-size="12" fill="#475569" font-weight="500">Q${i+1}</text>`;
}
// Ancilla qubit
if (step < 6) {
const fillA = step >= 1 ? "#ea580c" : "#fb923c";
const strokeA = (step >= 1 && step <= 5) ? "#fbbf24" : "none";
const swA = (step >= 1 && step <= 5) ? 3 : 0;
const label = step === 0 ? "a" : "a*";
s += `<circle cx="${ancX}" cy="${ancY}" r="${aR}" fill="${fillA}" stroke="${strokeA}" stroke-width="${swA}"/>`;
s += `<text x="${ancX}" y="${ancY + 4}" text-anchor="middle" font-size="10" fill="white" font-weight="700">${label}</text>`;
if (step >= 1 && step <= 5) {
s += `<text x="${ancX}" y="${ancY - aR - 6}" text-anchor="middle" font-size="9" fill="#c2410c" font-weight="600">Rydberg</text>`;
}
} else {
// Measurement symbol
s += `<rect x="${ancX - 18}" y="${ancY - 14}" width="36" height="28" rx="5" fill="#f3f4f6" stroke="#6b7280" stroke-width="2"/>`;
s += `<path d="M${ancX - 8} ${ancY + 8} Q${ancX} ${ancY - 8} ${ancX + 8} ${ancY + 8}" stroke="#374151" stroke-width="2" fill="none"/>`;
s += `<line x1="${ancX}" y1="${ancY}" x2="${ancX + 6}" y2="${ancY - 8}" stroke="#374151" stroke-width="2"/>`;
s += `<text x="${ancX}" y="${ancY - 22}" text-anchor="middle" font-size="10" fill="#6b7280" font-weight="600">Measure</text>`;
if (step === 7) {
s += `<text x="${ancX}" y="${ancY + 36}" text-anchor="middle" font-size="13" fill="#16a34a" font-weight="700">+1</text>`;
}
}
// Motion arrow
if (step >= 2 && step <= 5) {
s += `<text x="${ancX - 28}" y="${ancY + 4}" font-size="16" fill="#ea580c">→</text>`;
}
// Step description
s += `<text x="${W/2}" y="${H - 24}" text-anchor="middle" font-size="13" fill="#334155">${stepDescriptions[step]}</text>`;
s += `</svg>`;
const div = html`<div>${s}</div>`;
div.innerHTML = s;
return div;
}{
return html`<div style="max-width:680px; margin:12px auto 0; background:#f8fafc; border:1px solid #e2e8f0; border-radius:8px; padding:16px; font-size:0.88em; color:#475569; line-height:1.65;">
<strong>How it works:</strong> The ancilla atom is physically transported through the data-qubit array.
At each data qubit, a controlled-Z (CZ) gate is performed via Rydberg interaction.
After interacting with all 4 data qubits, the ancilla is measured, yielding the Z⊗4 syndrome.
<br><br>
<strong>Key advantage:</strong> Because the ancilla <em>moves</em>, there is no need for long-range entangling gates
or a complex connectivity graph. This is the essence of the <em>velocity-enabled</em> architecture —
atomic motion provides all-to-all connectivity for free.
<br><br>
<strong>An analogous protocol</strong> with Hadamard gates on the ancilla before and after would measure the X⊗4 stabilizer instead.
</div>`;
}