Checkpoint-3

System #0

You are a physics research assistant specializing in solving complex, research-level problems using precise, step-by-step reasoning.

Input Problems will be provided in Markdown format.

Output (Markdown format)

  1. Step-by-Step Derivation - Show every non-trivial step in the solution. Justify steps using relevant physical laws, theorems, mathematical identities or numerical codes.
  2. Mathematical Typesetting - Use LaTeX for all mathematics: $...$ for inline expressions, $$...$$ for display equations.
  3. Conventions and Units - Follow the unit system and conventions specified in the problem.
  4. Final Answer - At the end of the solution, start a new line with “Final Answer:”, and present the final result.

    For final answers involving values, follow the precision requirements specified in the problem. If no precision is specified: - If an exact value is possible, provide it (e.g., \$\sqrt(2)\$, \$\pi/4\$). - If exact form is not feasible, retain at least 12 significant digits in the result.

  5. Formatting Compliance - If the user requests a specific output format (e.g., code, table), provide the final answer accordingly.

User #1

Problem setup:

In quantum error correction, you encode quantum states into logical states made of many qubits in order to improve their resilience to errors. In quantum error detection, you do the same but can only detect the presence of errors and not correct them. In this problem, we will consider a single [[4,2,2]] quantum error detection code, which encodes two logical qubits into four physical qubits, and investigate how robust logical quantum operations in this code are to quantum errors.

Our convention is that the four physical qubits in the [[4,2,2]] code are labelled 0,1,2,3. The two logical qubits are labelled A and B. The stabilizers are \(XXXX\) and \(ZZZZ\), where \(X\) and \(Z\) are Pauli matrices. The logical \(X\) and \(Z\) operators on the two qubits are \(X_A = XIXI\), \(X_B=XXII\), \(Z_A = ZZII\), \(Z_B = ZIZI\), up to multiplication by stabilizers.

We will consider different state preparation circuits consisting of controlled not \(CNOT_{ij}\) gates, where \(CNOT_{ij}\) has control qubit \(i\) and target qubit \(j\). As a simple model of quantum errors in hardware, we will suppose that each \(CNOT_{ij}\) gate in the circuit has a two qubit depolarizing error channel following it that produces one of the 15 non-identity two-qubit Paulis with equal probability \(p/15\). The probability \(p\) indicates the probability of an error in a single two-qubit gate. We will assess the logical infidelity of certain state preparation protocols as a function of the physical infidelity \(p\).

Checkpoints

Checkpoint 1

Suppose that we wish to prepare a logical two-qubit GHZ state \((|00\rangle_{AB}+|11\rangle_{AB})/\sqrt{2}\) in the [[4,2,2]] code. To do so, we use the following state preparation circuit:

\[ (CNOT_{03}) (H_0) (CNOT_{21}) (H_2). \]

Note that this equation is written in matrix multiplication order, while the quantum operations in the circuit occur in the reverse order (from right-to-left in the above equation). \(H\) is a single-qubit Hadamard gate.

What is the physical state fidelity of the final physical 4-qubit state at the end of the circuit as a function of the two-qubit gate error rate \(p\)?

Assistant #2
  1. Step-by-Step Derivation
  • Assumptions and noise model
  • Initial state is the computational basis state on four qubits: \(|0000\rangle\).
  • The state preparation circuit is applied right-to-left: 1) \(H_2\), 2) \(CNOT_{21}\), 3) \(H_0\), 4) \(CNOT_{03}\).
  • After each \(CNOT_{ij}\), a two-qubit depolarizing channel acts on \((i,j)\):
\[ \mathcal{D}_p(\rho)=(1-p)\rho+\frac{p}{15}\sum_{P\in\mathcal{P}_2\setminus\{II\}} P\rho P, \]
where $\mathcal{P}_2=\{I,X,Y,Z\}^{\otimes 2}$ on the two involved qubits.
  • Ideal final state and its stabilizer
  • Apply the circuit to \(|0000\rangle\):
    • \(H_2\) followed by \(CNOT_{21}\) prepares a Bell pair on qubits \((2,1)\):
\[ |{\Phi^+}\rangle_{21}=\frac{|00\rangle_{21}+|11\rangle_{21}}{\sqrt{2}}. \]
- $H_0$ followed by $CNOT_{03}$ prepares a Bell pair on qubits $(0,3)$:
\[ |{\Phi^+}\rangle_{03}=\frac{|00\rangle_{03}+|11\rangle_{03}}{\sqrt{2}}. \]
  • Hence the ideal four-qubit state is
\[ |\psi\rangle=|{\Phi^+}\rangle_{03}\otimes|{\Phi^+}\rangle_{21}. \]
  • The stabilizer generators (conjugating \(Z_i\) through the circuit) are
\[ X_0X_3,\quad Z_0Z_3,\quad Z_2Z_1,\quad X_2X_1, \]
confirming $|\psi\rangle$ is a product of two Bell states (each Bell state has stabilizer $\langle X\otimes X,\,Z\otimes Z\rangle$).
  • Location of errors and their propagation
  • Errors occur only after \(CNOT_{21}\) (on qubits \((2,1)\)) and after \(CNOT_{03}\) (on qubits \((0,3)\)).
  • The gates between these errors (\(H_0\) and \(CNOT_{03}\) after the first error, and no further gate after the second error) act on disjoint qubits from \((2,1)\); hence the first error does not propagate to \((0,3)\) and vice versa.
  • Therefore, the net error at the end is a tensor product
\[ E_{\text{tot}}=E_{21}\otimes E_{03}, \]
with $E_{21}$ a two-qubit Pauli on $(2,1)$ and $E_{03}$ a two-qubit Pauli on $(0,3)$, independently drawn from the depolarizing distributions.
  • Fidelity contribution from a single pair
  • For a single Bell pair \(|{\Phi^+}\rangle\), the two-qubit Paulis that leave the density matrix invariant (map the state to itself up to a global phase) are
\[ \{II,\ XX,\ YY,\ ZZ\}. \]
Indeed, $XX$ and $ZZ$ stabilize $|{\Phi^+}\rangle$ with eigenvalue $+1$, while $YY=-(XX)(ZZ)$ acts with eigenvalue $-1$, which still leaves the projector $|\Phi^+\rangle\langle\Phi^+|$ unchanged.
  • Under the depolarizing channel on that pair:
    • With probability \((1-p)\), \(II\) occurs (good).
    • With probability \(p\), a uniformly random non-identity Pauli from the 15 occurs; among these, exactly 3 are good: \(XX,YY,ZZ\).
  • Thus, the probability that the pair remains in \(|{\Phi^+}\rangle\) is
\[ f_{\text{pair}}=(1-p)+\frac{3}{15}p=1-\frac{12}{15}p=1-\frac{4}{5}p. \]
  • Overall four-qubit fidelity
  • Because the two error channels act on disjoint pairs and independently, the total state is preserved if and only if both pairs are preserved. Hence the total physical-state fidelity is
\[ F(p)=\big(f_{\text{pair}}\big)^2=\left(1-\frac{4}{5}p\right)^2. \]
  1. Mathematical Typesetting

All key steps have been expressed in LaTeX above.

  1. Conventions and Units
  • Qubits labeled as specified: physical qubits 0,1,2,3; pairs affected by the two CNOTs are (2,1) and (0,3).
  • Noise model is the stated two-qubit depolarizing channel with parameter \(p\).
  1. Final Answer: F(p) = (1 - 4p/5)^2.
User #3

The correct answer is: $ F_{\rm{physical}}=(1-\frac{12}{15}p)^2 $

Now let’s solve the next Checkpoint.

Checkpoint 2

Suppose that we wish to prepare a logical two-qubit GHZ state \((|00\rangle_{AB}+|11\rangle_{AB})/\sqrt{2}\) in the [[4,2,2]] code. To do so, we use the following state preparation circuit:

\[ (CNOT_{03}) (H_0) (CNOT_{21}) (H_2). \]

Note that this equation is written in matrix multiplication order, while the quantum operations in the circuit occur in the reverse order (from right-to-left in the above equation). \(H\) is a single-qubit Hadamard gate.

What is the logical state fidelity of the final 2-qubit logical state at the end of the circuit as a function of the two-qubit gate error rate \(p\), assuming the state is post-selected on all detectable errors in the code?

Assistant #4
Tool Call (code to execute)
from itertools import product

# Pauli matrices ignoring phase
paulis = ['I','X','Y','Z']

# Single-qubit commutation: two Paulis commute if (both I) or same or one is I or are not from (X,Z) anti commute etc.
# We can define a commutation function for strings of length 4.

anti_pairs = {('X','Z'),('Z','X'),('X','Y'),('Y','X'),('Y','Z'),('Z','Y')}

def commute(p, q):
    # p and q are strings over I,X,Y,Z of same length
    anti = 0
    for a,b in zip(p,q):
        if a=='I' or b=='I':
            continue
        if a==b:
            continue
        if (a,b) in anti_pairs:
            anti ^= 1
    return anti==0

# group generation ignoring phase

def generate_group(generators):
    # generators: list of strings
    G = set(['I'*4])
    changed = True
    while changed:
        changed = False
        for g in generators:
            for h in list(G):
                # multiply g*h ignoring phase
                prod = []
                for a,b in zip(g,h):
                    if a=='I': prod.append(b)
                    elif b=='I': prod.append(a)
                    elif a==b: prod.append('I')
                    else:
                        # multiplication table ignoring phase
                        # X*Y = Z; Y*X = Z; but differing by phase; ignore phase -> symmetric
                        # We'll define mapping as: X*Y->Z, Y*Z->X, Z*X->Y, and symmetric
                        m = {
                            ('X','Y'):'Z',('Y','X'):'Z',
                            ('Y','Z'):'X',('Z','Y'):'X',
                            ('Z','X'):'Y',('X','Z'):'Y'
                        }
                        prod.append(m[(a,b)])
                s = ''.join(prod)
                if s not in G:
                    G.add(s)
                    changed = True
    return G

# Define code 
S1 = 'XXXX'
S2 = 'ZZZZ'
X_A = 'XIXI'
X_B = 'XXII'
Z_A = 'ZZII'
Z_B = 'ZIZI'

# Logical Bell state stabilizer group generators: S plus X_A X_B and Z_A Z_B
# Need to compute products X_A X_B etc.

def multiply(p,q):
    prod = []
    for a,b in zip(p,q):
        if a=='I': prod.append(b)
        elif b=='I': prod.append(a)
        elif a==b: prod.append('I')
        else:
            m = {
                ('X','Y'):'Z',('Y','X'):'Z',
                ('Y','Z'):'X',('Z','Y'):'X',
                ('Z','X'):'Y',('X','Z'):'Y'
            }
            prod.append(m[(a,b)])
    return ''.join(prod)

L1 = multiply(X_A, X_B)  # X_A X_B
L2 = multiply(Z_A, Z_B)  # Z_A Z_B

G_state = generate_group([S1,S2,L1,L2])

# Centralizer N(S): set of Paulis commuting with both S1 and S2
# We'll enumerate all 4-qubit Paulis ignoring phase
P4 = [''.join(p) for p in product(paulis, repeat=4)]
centralizer = set([p for p in P4 if commute(p,S1) and commute(p,S2)])

len_G_state = len(G_state)
len_centralizer = len(centralizer)
len_G_state, len_centralizer, len(G_state - centralizer)
Tool #5
''
Assistant #6
Tool Call (code to execute)
from itertools import product

paulis = ['I','X','Y','Z']
anti_pairs = {('X','Z'),('Z','X'),('X','Y'),('Y','X'),('Y','Z'),('Z','Y')}

def commute(p, q):
    anti = 0
    for a,b in zip(p,q):
        if a=='I' or b=='I':
            continue
        if a==b:
            continue
        if (a,b) in anti_pairs:
            anti ^= 1
    return anti==0


def generate_group(generators):
    G = set(['I'*4])
    changed = True
    while changed:
        changed = False
        for g in generators:
            for h in list(G):
                prod = []
                for a,b in zip(g,h):
                    if a=='I': prod.append(b)
                    elif b=='I': prod.append(a)
                    elif a==b: prod.append('I')
                    else:
                        m = {
                            ('X','Y'):'Z',('Y','X'):'Z',
                            ('Y','Z'):'X',('Z','Y'):'X',
                            ('Z','X'):'Y',('X','Z'):'Y'
                        }
                        prod.append(m[(a,b)])
                s = ''.join(prod)
                if s not in G:
                    G.add(s)
                    changed = True
    return G


def multiply(p,q):
    prod = []
    for a,b in zip(p,q):
        if a=='I': prod.append(b)
        elif b=='I': prod.append(a)
        elif a==b: prod.append('I')
        else:
            m = {
                ('X','Y'):'Z',('Y','X'):'Z',
                ('Y','Z'):'X',('Z','Y'):'X',
                ('Z','X'):'Y',('X','Z'):'Y'
            }
            prod.append(m[(a,b)])
    return ''.join(prod)

S1 = 'XXXX'; S2 = 'ZZZZ'
X_A = 'XIXI'; X_B = 'XXII'; Z_A = 'ZZII'; Z_B = 'ZIZI'
L1 = multiply(X_A, X_B)
L2 = multiply(Z_A, Z_B)

G_state = generate_group([S1,S2,L1,L2])
P4 = [''.join(p) for p in product(['I','X','Y','Z'], repeat=4)]
centralizer = set([p for p in P4 if commute(p,S1) and commute(p,S2)])

print('Sizes:', len(G_state), len(centralizer))
print('L1:', L1, 'L2:', L2)
print('G_state subset centralizer?', G_state.issubset(centralizer))
Tool #7
Sizes: 16 64
L1: IXXI L2: IZZI
G_state subset centralizer? True
Assistant #8
Tool Call (code to execute)
from itertools import product

paulis = ['I','X','Y','Z']
anti_pairs = {('X','Z'),('Z','X'),('X','Y'),('Y','X'),('Y','Z'),('Z','Y')}

def commute(p, q):
    anti = 0
    for a,b in zip(p,q):
        if a=='I' or b=='I':
            continue
        if a==b:
            continue
        if (a,b) in anti_pairs:
            anti ^= 1
    return anti==0


def multiply(p,q):
    prod = []
    for a,b in zip(p,q):
        if a=='I': prod.append(b)
        elif b=='I': prod.append(a)
        elif a==b: prod.append('I')
        else:
            m = {
                ('X','Y'):'Z',('Y','X'):'Z',
                ('Y','Z'):'X',('Z','Y'):'X',
                ('Z','X'):'Y',('X','Z'):'Y'
            }
            prod.append(m[(a,b)])
    return ''.join(prod)

# Define code elements
S1 = 'XXXX'; S2 = 'ZZZZ'
X_A = 'XIXI'; X_B = 'XXII'; Z_A = 'ZZII'; Z_B = 'ZIZI'

def gen_group(gens):
    G = set(['I'*4])
    frontier = ['I'*4]
    while frontier:
        h = frontier.pop()
        for g in gens:
            new = multiply(g,h)
            if new not in G:
                G.add(new)
                frontier.append(new)
    return G

L1 = multiply(X_A, X_B)
L2 = multiply(Z_A, Z_B)
G_state = gen_group([S1,S2,L1,L2])

# Construct 2-qubit Paulis for a given ordered pair tuple (u,v) -> indices order in 4-qubit string
P2 = [(a,b) for a in paulis for b in paulis]

# Map pair Paul's to 4-qubit string for (2,1) and (0,3)

def embed_21(p):
    a,b = p  # a on qubit2, b on qubit1
    return ''.join(['I', b, a, 'I'])

def embed_03(p):
    a,b = p  # a on qubit0, b on qubit3
    return ''.join([a, 'I', 'I', b])

# Prepare sets
accepted = set()
for p21 in P2:
    for p03 in P2:
        E = multiply(embed_03(p03), embed_21(p21))
        if commute(E,S1) and commute(E,S2):
            accepted.add((p21,p03,E))

# Compute counts per category
import collections

# For counting weights: categories n_err = #(pair non-identity)
counts_accept = {0:0, 1:0, 2:0}
counts_good = {0:0, 1:0, 2:0}

for p21 in P2:
    for p03 in P2:
        E = multiply(embed_03(p03), embed_21(p21))
        n_err = (p21 != ('I','I')) + (p03 != ('I','I'))
        if commute(E,S1) and commute(E,S2):
            counts_accept[n_err] += 1
            if E in G_state:
                counts_good[n_err] += 1

print('Counts accept by n_err:', counts_accept)
print('Counts good by n_err:', counts_good)

# Also total counts, to sanity-check
total = {0:1*1, 1: (1*15 + 15*1), 2: 15*15}
print('Total combos per n_err:', total)

# Now compute polynomial coefficients for acceptance and good probabilities
# acceptance probability =
#   (1-p)^2 * counts_accept[0] 
# +  (1-p)*(p/15) * counts_accept[1]   [since there are counts_accept[1] distinct pairs overall]
# +  (p/15)^2 * counts_accept[2]

from fractions import Fraction

counts_accept, counts_good
Tool #9
Counts accept by n_err: {0: 1, 1: 6, 2: 57}
Counts good by n_err: {0: 1, 1: 6, 2: 9}
Total combos per n_err: {0: 1, 1: 30, 2: 225}
Assistant #10
Tool Call (code to execute)
import sympy as sp
p = sp.symbols('p', real=True)
Acc = (1-p)**2 + 6*(1-p)*(p/15) + 57*(p/15)**2
Good = (1-p)**2 + 6*(1-p)*(p/15) + 9*(p/15)**2
F = sp.simplify(Good/Acc)
Acc_simplified = sp.simplify(sp.factor(Acc))
Good_simplified = sp.simplify(sp.factor(Good))
print('Acc(p) =', sp.together(Acc_simplified))
print('Good(p)=', sp.together(Good_simplified))
print('F(p)   =', sp.together(sp.simplify(F)))
# Also expand to get polynomial forms
print('Acc expanded:', sp.expand(Acc))
print('Good expanded:', sp.expand(Good))
Tool #11
Acc(p) = (64*p**2 - 120*p + 75)/75
Good(p)= (4*p - 5)**2/25
F(p)   = 3*(16*p**2 - 40*p + 25)/(64*p**2 - 120*p + 75)
Acc expanded: 64*p**2/75 - 8*p/5 + 1
Good expanded: 16*p**2/25 - 8*p/5 + 1
Assistant #12
Tool Call (code to execute)
import sympy as sp
p=sp.symbols('p')
F = 3*(16*p**2 - 40*p + 25)/(64*p**2 - 120*p + 75)
print(sp.series(F, p, 0, 3))
Tool #13
1 - 16*p**2/75 + O(p**3)
Assistant #14
Tool Call (code to execute)
from itertools import product
paulis = ['I','X','Y','Z']

def parity_class(p):
    a,b = p
    def is_x_or_y(c): return c in ('X','Y')
    def is_z_or_y(c): return c in ('Z','Y')
    xpar = (1 if is_x_or_y(a) else 0) + (1 if is_x_or_y(b) else 0)
    zpar = (1 if is_z_or_y(a) else 0) + (1 if is_z_or_y(b) else 0)
    return (xpar%2, zpar%2)

P2 = [(a,b) for a in paulis for b in paulis]
from collections import Counter
cnt = Counter(parity_class(p) for p in P2)
print('Parity counts including II:', dict(cnt))
# Remove identity
cnt_nonid = Counter(parity_class(p) for p in P2 if p != ('I','I'))
print('Parity counts non-id:', dict(cnt_nonid))
Tool #15
Parity counts including II: {(0, 0): 4, (1, 0): 4, (1, 1): 4, (0, 1): 4}
Parity counts non-id: {(1, 0): 4, (1, 1): 4, (0, 1): 4, (0, 0): 3}
Assistant #16
  1. Step-by-Step Derivation
  • Setup and target
  • Stabilizers: S = ⟨S1, S2⟩ with S1 = XXXX, S2 = ZZZZ.
  • Logical operators (one valid choice): X_A = XIXI, X_B = XXII, Z_A = ZZII, Z_B = ZIZI.
  • Target logical state: the logical Bell state (|00⟩{AB} + |11⟩{AB})/√2, stabilized (at the logical level) by X_A X_B and Z_A Z_B.
  • Circuit: H_2 → CNOT_{21} → H_0 → CNOT_{03}. Noise: after each CNOT, a 2-qubit depolarizing channel acts on that pair:

    • On pair (2,1) after CNOT_{21}.
    • On pair (0,3) after CNOT_{03}.
    • Each error is a 2-qubit Pauli chosen uniformly from the 15 non-identity elements with probability p/15; identity with probability 1−p.
  • Ideal state after the noiseless circuit

  • The circuit prepares |Φ^+⟩{03} ⊗ |Φ^+⟩{21}, where |Φ^+⟩ = (|00⟩+|11⟩)/√2.
  • This state lies in the [[4,2,2]] codespace (it is stabilized by S1 = XXXX and S2 = ZZZZ) and implements the logical Bell state (|00⟩{AB}+|11⟩{AB})/√2.

  • Post-selection criterion (error detection)

  • Post-select on trivial syndrome, i.e., accept only errors E that commute with both S1 and S2. Equivalently, E must lie in the normalizer N(S) of the stabilizer S.

  • Logical fidelity conditional on acceptance

  • Let P_acc be the total acceptance probability (sum over all error events that commute with S).
  • Let P_good be the probability that the final state equals the target logical state (i.e., error lies in the stabilizer group of the target physical state). Then the logical state fidelity conditioned on acceptance is
\[ F_{\text{logical}}(p) = \frac{P_{\text{good}}(p)}{P_{\text{acc}}(p)}. \]
  • Classifying two-qubit Paulis on a pair by X/Z parities
  • For a 2-qubit Pauli Q on a pair, define parities:
    • x-parity = number of X or Y on the two qubits mod 2,
    • z-parity = number of Z or Y on the two qubits mod 2.
  • Among the 16 elements on a pair (including II), the counts by (x,z)-parity classes are:
    • (0,0): 4 elements (one is II, the other three are XX, YY, ZZ),
    • (1,0): 4 elements,
    • (0,1): 4 elements,
    • (1,1): 4 elements.
  • Acceptance condition for the 4-qubit error E = E_{21} ⊗ E_{03}: E commutes with S1=XXXX iff the total z-parity across all four qubits is even; commutes with S2=ZZZZ iff the total x-parity is even. Hence E is accepted iff the pair parities match componentwise:
\[ x_{21}\equiv x_{03}\ (\text{mod }2),\quad z_{21}\equiv z_{03}\ (\text{mod }2). \]
  • Counting accepted and “good” events by number of faults
  • There are at most two faulty locations (after each CNOT).
  • n_err = 0 (no error): 1 combination (II on each pair); accepted and good.
  • n_err = 1 (exactly one non-identity on one pair):
    • Accepted iff the single non-identity lies in the (0,0) class, i.e., it is one of {XX, YY, ZZ} on that pair.
    • There are 3 such on pair (2,1) and 3 on pair (0,3): total 6 accepted.
    • All 6 are also “good,” since XX, YY, ZZ on a Bell pair stabilize |Φ^+⟩ (up to phase), and the overall physical state remains the ideal one.
  • n_err = 2 (non-identity on both pairs):
    • Acceptance requires the parity classes to match: number of accepted combinations
\[ 4\cdot 4 + 4\cdot 4 + 4\cdot 4 + 3\cdot 3 = 57. \]
  Explanation: for classes (1,0), (0,1), (1,1) there are 4 choices per pair; for (0,0) there are 3 non-identity choices per pair.
- Good requires each pairs error be in {XX, YY, ZZ}, i.e., 3×3 = 9 combinations. These map the target Bell×Bell state to itself (up to phase).
  • Probabilities and weights under the noise model
  • For each pair: P(II) = 1−p; P(Q≠II) = p/15 for each of 15 non-identity elements.
  • Therefore:
    • Acceptance probability:
\[ P_{\text{acc}}(p) &= (1-p)^2\cdot 1 \\ &\quad + 2\,(1-p)\,(p/15)\cdot 3 \\ &\quad + (p/15)^2 \cdot 57 \\ &= 1 - \frac{8}{5}p + \frac{64}{75}p^2. \]
- “Good” probability:
\[ P_{\text{good}}(p) &= (1-p)^2\cdot 1 \\ &\quad + 2\,(1-p)\,(p/15)\cdot 3 \\ &\quad + (p/15)^2 \cdot 9 \\ &= \left(1 - \frac{4}{5}p\right)^2. \]
  Note P_good equals the physical-state fidelity from Subproblem 1, because the state is a tensor product of two Bell pairs and “good” requires each pair to remain in |Φ^+⟩ (up to phase).
  • Logical fidelity conditioned on acceptance
\[ F_{\text{logical}}(p) \;=\; \frac{P_{\text{good}}(p)}{P_{\text{acc}}(p)} \;=\; \frac{1 - \frac{8}{5}p + \frac{16}{25}p^2}{1 - \frac{8}{5}p + \frac{64}{75}p^2}. \]

A compact equivalent form:

\[ F_{\text{logical}}(p) \;=\; \frac{48p^2 - 120p + 75}{64p^2 - 120p + 75} \;=\; 1 - \frac{16p^2}{64p^2 - 120p + 75}. \]

Small-p expansion: \(F_{\text{logical}}(p) = 1 - \frac{16}{75}p^2 + O(p^3)\) (no linear term, as all accepted single-fault events are harmless).

  1. Mathematical Typesetting
  • All expressions above are written in LaTeX.
  1. Conventions and Units
  • Qubit ordering: (0,1,2,3).
  • Noise: two-qubit depolarizing after each CNOT, independent across the two pairs (2,1) and (0,3), with parameter p.
  1. Final Answer: F_logical(p) = (1 - 8p/5 + 16p^2/25)/(1 - 8p/5 + 64p^2/75) = (48p^2 - 120p + 75)/(64p^2 - 120p + 75).
User #17

The correct answer is: $ F_{\rm{logical}}=1 - \frac{\frac{16}{75}p^2}{1-\frac{8}{5}p + \frac{64}{75}p^2} $

Now let’s solve the next Checkpoint.

Checkpoint 3

Suppose that we prepare a logical two-qubit \(|00\rangle_{AB}\) state in the [[4,2,2]] code. To do so, we introduce an ancilla qubit, qubit 4, and use the following state preparation circuit:

\[ M_4 (CNOT_{04}) (CNOT_{34}) (CNOT_{23}) (CNOT_{10}) (CNOT_{12}) (H_1) \]

Note that this equation is written in matrix multiplication order, while the quantum operations in the circuit occur in the reverse order (from right-to-left in the above equation). \(H\) is a single-qubit Hadamard gate and \(M\) is a single-qubit measurement. The ancilla is used to detect errors in the state preparation circuit and makes the circuit fault-tolerant. If the ancilla measurement is \(|0\rangle\) (\(|1\rangle\)), the state preparation succeeds (fails).

What is the logical state fidelity of the final 2-qubit logical state at the end of the circuit as a function of two-qubit gate error rate \(p\), assuming the state is post-selected on all detectable errors in the code and on the ancilla qubit measuring \(|0\rangle\)?

Assistant #18
Tool Call (code to execute)
from itertools import product

# Define Pauli group operations ignoring phase
paulis = ['I','X','Y','Z']
mult_map = {
    ('I','I'):'I', ('I','X'):'X', ('I','Y'):'Y', ('I','Z'):'Z',
    ('X','I'):'X', ('X','X'):'I', ('X','Y'):'Z', ('X','Z'):'Y',
    ('Y','I'):'Y', ('Y','X'):'Z', ('Y','Y'):'I', ('Y','Z'):'X',
    ('Z','I'):'Z', ('Z','X'):'Y', ('Z','Y'):'X', ('Z','Z'):'I',
}

# Multiplication ignoring phase on strings

def pmul(a,b):
    return ''.join(mult_map[(x,y)] for x,y in zip(a,b))

# Conjugation by CNOT(c,t) on a 5-qubit Pauli string s

def cnot_conj(s, c, t):
    s = list(s)
    # Rules: X_c -> X_c X_t; Z_t -> Z_c Z_t; Y_c -> Y_c X_t; Y_t -> Z_c Y_t
    # We implement by updating characters appropriately; need to combine if both changes apply
    def combine(qubit, p):
        s[qubit] = mult_map[(s[qubit], p)]
    # Apply effect for control
    if s[c] == 'X':
        combine(t, 'X')
    elif s[c] == 'Y':
        combine(t, 'X')  # Y_c carries X on c and Z on c; effect on target same as X on control
    # Apply effect for target
    if s[t] == 'Z':
        combine(c, 'Z')
    elif s[t] == 'Y':
        combine(c, 'Z')
    return ''.join(s)

# Conjugation by H on qubit q: X<->Z, Y -> -Y (ignore phase so Y stays Y)

def h_conj(s, q):
    s = list(s)
    if s[q] == 'X':
        s[q] = 'Z'
    elif s[q] == 'Z':
        s[q] = 'X'
    # Y remains Y ignoring phase
    return ''.join(s)

# Build mapping: final error from each inserted error after a given CNOT
# Circuit order (right-to-left):
# 1) H_1
# 2) CNOT_12
# 3) CNOT_10
# 4) CNOT_23
# 5) CNOT_34
# 6) CNOT_04
# 7) M_4

# We will define a function that, given a list of 5 two-qubit Pauli errors e2,e3,e4,e5,e6 (strings like 'IX' on the pair),
# computes the final 5-qubit Pauli string.

# Helper to embed a two-qubit Pauli on qubits (i,j) into 5-qubit string

def embed_ij(pair, i, j):
    s = ['I']*5
    s[i] = pair[0]
    s[j] = pair[1]
    return ''.join(s)

# Apply conjugation function for the remainder of the circuit

def propagate_to_end(err_after_gate_index, P):
    # err_after_gate_index in {2,3,4,5,6}
    # P is a 5-qubit Pauli string representing an error that occurs just after that gate
    s = P
    # Conjugate by the subsequent gates in chronological order: next indices > err_after_gate_index
    if err_after_gate_index < 3:
        s = cnot_conj(s, 1, 0)  # gate 3: CNOT_10
    if err_after_gate_index < 4:
        s = cnot_conj(s, 2, 3)  # gate 4: CNOT_23
    if err_after_gate_index < 5:
        s = cnot_conj(s, 3, 4)  # gate 5: CNOT_34
    if err_after_gate_index < 6:
        s = cnot_conj(s, 0, 4)  # gate 6: CNOT_04
    # No conjugation by measurement
    return s

# Let's verify conj functions by random tests (omitted for brevity)

# Stabilizers for data qubits 0..3
S1 = 'XXXX'
S2 = 'ZZZZ'

# Centralizer predicate for data 0..3
anti_pairs = {('X','Z'),('Z','X'),('X','Y'),('Y','X'),('Y','Z'),('Z','Y')}

def commute(p, q):
    # p, q are 4-qubit strings
    anti = 0
    for a,b in zip(p,q):
        if a=='I' or b=='I' or a==b:
            continue
        if (a,b) in anti_pairs:
            anti ^= 1
    return anti==0

# Generate group of target codeword stabilizer: <S1,S2, Z_A, Z_B>
X_A = 'XIXI'; X_B = 'XXII'; Z_A = 'ZZII'; Z_B = 'ZIZI'

# Multiply 4-qubit ignoring phase
mult4 = mult_map

def pmul4(a,b):
    return ''.join(mult4[(x,y)] for x,y in zip(a,b))

def generate_group(gens):
    G = set(['I'*4])
    frontier = ['I'*4]
    while frontier:
        h = frontier.pop()
        for g in gens:
            nh = pmul4(g, h)
            if nh not in G:
                G.add(nh)
                frontier.append(nh)
    return G

state_stab = generate_group([S1, S2, Z_A, Z_B])  # size should be 16
centralizer = set()
for a in product(paulis, repeat=4):
    p = ''.join(a)
    if commute(p,S1) and commute(p,S2):
        centralizer.add(p)

# Now enumerate all 16^5 combinations
pairs = [''.join(p) for p in product(paulis, repeat=2)]  # two-qubit Paulis on a pair

# Precompute mapping for each location and pair Pauli to final 5-qubit Pauli
locations = {
    2: (1,2),  # CNOT_12
    3: (1,0),  # CNOT_10
    4: (2,3),  # CNOT_23
    5: (3,4),  # CNOT_34
    6: (0,4),  # CNOT_04
}

maps = {k:{} for k in locations}
for k,(i,j) in locations.items():
    for pair in pairs:
        emb = embed_ij(pair, i, j)
        maps[k][pair] = propagate_to_end(k, emb)

# Now enumerate tuples (e2,e3,e4,e5,e6)
from collections import defaultdict
counts_accept = defaultdict(int)
counts_good = defaultdict(int)
counts_tot = defaultdict(int)

for e2 in pairs:
    for e3 in pairs:
        for e4 in pairs:
            for e5 in pairs:
                for e6 in pairs:
                    # Compute final Pauli as product (order doesn't matter up to phase)
                    s = 'I'*5
                    for k,e in [(2,e2),(3,e3),(4,e4),(5,e5),(6,e6)]:
                        s = pmul(s, maps[k][e])
                    # Split data and ancilla
                    data = s[:4]
                    anc = s[4]
                    # Accept if anc in {I,Z} and data in centralizer
                    accept = (anc in ('I','Z')) and (data in centralizer)
                    # Good if accept and data in state_stab
                    good = accept and (data in state_stab)
                    # Count by m = number of non-identity errors
                    m = (e2!='II') + (e3!='II') + (e4!='II') + (e5!='II') + (e6!='II')
                    counts_tot[m] += 1
                    if accept:
                        counts_accept[m] += 1
                    if good:
                        counts_good[m] += 1

# Print summaries
print('Total combinations per m (should be C(5,m)*15^m):')
for m in range(6):
    print(m, counts_tot[m])
print('Accepted counts per m:', dict(counts_accept))
print('Good counts per m:', dict(counts_good))
Tool #19
Total combinations per m (should be C(5,m)*15^m):
0 1
1 75
2 2250
3 33750
4 253125
5 759375
Accepted counts per m: {0: 1, 1: 7, 2: 282, 3: 4222, 4: 31637, 5: 94923}
Good counts per m: {0: 1, 1: 7, 2: 138, 3: 1198, 4: 7397, 5: 24027}
Assistant #20
Tool Call (code to execute)
import sympy as sp
p = sp.symbols('p', real=True)
# Counts from enumeration
counts_accept = {0:1, 1:7, 2:282, 3:4222, 4:31637, 5:94923}
counts_good   = {0:1, 1:7, 2:138, 3:1198, 4:7397, 5:24027}

Acc = 0
Good = 0
for m in range(6):
    cA = counts_accept.get(m,0)
    cG = counts_good.get(m,0)
    term = (1-p)**(5-m) * (p/15)**m
    Acc += cA * term
    Good += cG * term

F = sp.simplify(sp.together(Good/Acc))
print('Acc(p) =', sp.together(sp.simplify(Acc)))
print('Good(p)=', sp.together(sp.simplify(Good)))
print('F_logical(p)=', F)
print('Series small p:', sp.series(F, p, 0, 4))
Tool #21
Acc(p) = (-262144*p**5 + 1269760*p**4 - 2457600*p**3 + 2376000*p**2 - 1147500*p + 253125)/253125
Good(p)= (-229376*p**5 + 1116160*p**4 - 2198400*p**3 + 2214000*p**2 - 1147500*p + 253125)/253125
F_logical(p)= (229376*p**5 - 1116160*p**4 + 2198400*p**3 - 2214000*p**2 + 1147500*p - 253125)/(262144*p**5 - 1269760*p**4 + 2457600*p**3 - 2376000*p**2 + 1147500*p - 253125)
Series small p: 1 - 16*p**2/25 - 704*p**3/375 + O(p**4)
Assistant #22
Tool Call (code to execute)
import sympy as sp
p=sp.symbols('p')
num = 229376*p**5 - 1116160*p**4 + 2198400*p**3 - 2214000*p**2 + 1147500*p - 253125
den = 262144*p**5 - 1269760*p**4 + 2457600*p**3 - 2376000*p**2 + 1147500*p - 253125
print('Factor numerator:')
print(sp.factor(num))
print('Factor denominator:')
print(sp.factor(den))

# Try to factor out (1 - 4p/5)^2 maybe? Let's divide Good and Acc by (1 - a p)^k etc
cand = (1 - sp.Rational(4,5)*p)**2
print('Divide polynomials by (1 - 4p/5)^2:')
print(sp.together(sp.simplify(num/cand)))
print(sp.together(sp.simplify(den/cand)))
Tool #23
Factor numerator:
229376*p**5 - 1116160*p**4 + 2198400*p**3 - 2214000*p**2 + 1147500*p - 253125
Factor denominator:
(128*p**2 - 300*p + 225)*(2048*p**3 - 5120*p**2 + 3600*p - 1125)
Divide polynomials by (1 - 4p/5)^2:
25*(229376*p**5 - 1116160*p**4 + 2198400*p**3 - 2214000*p**2 + 1147500*p - 253125)/(4*p - 5)**2
25*(262144*p**5 - 1269760*p**4 + 2457600*p**3 - 2376000*p**2 + 1147500*p - 253125)/(4*p - 5)**2
Assistant #24
Tool Call (code to execute)
import sympy as sp
p = sp.symbols('p', real=True)
counts_accept = {0:1, 1:7, 2:282, 3:4222, 4:31637, 5:94923}
counts_good   = {0:1, 1:7, 2:138, 3:1198, 4:7397, 5:24027}

Acc = 0
Good = 0
for m in range(6):
    Acc += counts_accept.get(m,0) * (1-p)**(5-m) * (p/15)**m
    Good += counts_good.get(m,0) * (1-p)**(5-m) * (p/15)**m
Delta = sp.simplify(sp.together(Acc - Good))
print('Delta(p) =', Delta)
print('Factor Delta:', sp.factor(sp.together(sp.expand(Delta))))
print('Series small p:', sp.series(Delta, p, 0, 4))
Tool #25
Delta(p) = 16*p**2*(-2048*p**3 + 9600*p**2 - 16200*p + 10125)/253125
Factor Delta: -16*p**2*(8*p - 15)*(256*p**2 - 720*p + 675)/253125
Series small p: 16*p**2/25 - 128*p**3/125 + O(p**4)
Assistant #26
Tool Call (code to execute)
import sympy as sp
p=sp.symbols('p')
Good = (-229376*p**5 + 1116160*p**4 - 2198400*p**3 + 2214000*p**2 - 1147500*p + 253125)/253125
Acc  = (-262144*p**5 + 1269760*p**4 - 2457600*p**3 + 2376000*p**2 - 1147500*p + 253125)/253125
print('Factor Good numerator positive:', sp.factor(-sp.together(Good*253125)))
print('Factor Acc numerator positive:', sp.factor(-sp.together(Acc*253125)))
Tool #27
Factor Good numerator positive: 229376*p**5 - 1116160*p**4 + 2198400*p**3 - 2214000*p**2 + 1147500*p - 253125
Factor Acc numerator positive: (128*p**2 - 300*p + 225)*(2048*p**3 - 5120*p**2 + 3600*p - 1125)
Assistant #28
  1. Step-by-Step Derivation
  • Code, circuit, and noise
  • [[4,2,2]] code with stabilizers S = ⟨S1, S2⟩, S1 = XXXX, S2 = ZZZZ.
  • Logical operators (one valid choice): X_A = XIXI, X_B = XXII, Z_A = ZZII, Z_B = ZIZI.
  • Target logical state: |00⟩_{AB}, stabilized (within the codespace) by S together with Z_A and Z_B.
  • Circuit (right-to-left execution): H_1 → CNOT_{12} → CNOT_{10} → CNOT_{23} → CNOT_{34} → CNOT_{04} → measure Z on ancilla 4.
  • Noise: after each CNOT, a two-qubit depolarizing channel on that pair:

    • Pairs in order: (1,2), (1,0), (2,3), (3,4), (0,4).
    • Each such channel applies II with probability (1−p), and one of the 15 non-identity two-qubit Paulis with probability p/15, independently.
  • Post-selection (acceptance) criteria

  • Code post-selection: final data-qubit error E_data must commute with both S1 and S2 (i.e., E_data ∈ N(S), the normalizer of S).
  • Ancilla post-selection: the measured ancilla outcome must be |0⟩. In the Pauli picture, this is equivalent to requiring that the final Pauli on qubit 4 is in {I, Z} (X or Y on the ancilla flips the Z-measurement bit).

  • “Good” events (logical fidelity)

  • Among accepted events, the final 4-qubit data error must stabilize the target logical state |00⟩{AB}. The stabilizer of |00⟩{AB} is G_target = ⟨S1, S2, Z_A, Z_B⟩ (size 16 ignoring phases). Any accepted error in G_target leaves the logical state unchanged; accepted errors in N(S)\G_target implement logical flips (e.g., X_A, X_B, …) and are “bad.”

  • Clifford/Pauli propagation and exhaustive counting

  • Because the circuit is Clifford and the errors are Paulis, each error can be propagated to the end via the conjugation rules for CNOT and H (we only need CNOT here since all errors are inserted after H_1).
  • For five error locations, enumerate all 16^5 Pauli choices (identity + 15 non-identity per location), and group by m ≡ number of non-identity insertions. For each configuration: 1) Propagate each Pauli forward to the end and multiply them (ignoring global phases) to get a single 5-qubit Pauli E_final. 2) Extract E_data = E_final on qubits 0..3 and E_anc = E_final on qubit 4. 3) Accept iff E_data ∈ N(S) and E_anc ∈ {I, Z}. 4) Good iff, in addition, E_data ∈ G_target.
  • The exact accepted/good counts obtained are:

    • m = 0: accepted = 1, good = 1
    • m = 1: accepted = 7, good = 7
    • m = 2: accepted = 282, good = 138
    • m = 3: accepted = 4222, good = 1198
    • m = 4: accepted = 31637, good = 7397
    • m = 5: accepted = 94923, good = 24027 (Total configurations for each m are C(5,m)·15^m, matching 1, 75, 2250, 33750, 253125, 759375.)
  • Probabilities

  • Acceptance probability:
\[ P_{\text{acc}}(p)=\sum_{m=0}^{5}\text{acc}_m\,(1-p)^{5-m}\left(\frac{p}{15}\right)^m, \]
where acc_m are the acceptance counts above. Simplifying,
\[ P_{\text{acc}}(p)=\frac{(128p^2-300p+225)(2048p^3-5120p^2+3600p-1125)}{253125}. \]
  • “Good” probability:
\[ P_{\text{good}}(p)=\sum_{m=0}^{5}\text{good}_m\,(1-p)^{5-m}\left(\frac{p}{15}\right)^m, \]
with good_m as above. In expanded form,
\[ P_{\text{good}}(p)=\frac{-229376p^5+1116160p^4-2198400p^3+2214000p^2-1147500p+253125}{253125}. \]
  • Logical fidelity conditioned on acceptance:
\[ F_{\text{logical}}(p)=\frac{P_{\text{good}}(p)}{P_{\text{acc}}(p)}. \]
  • Closed forms and structure
  • It is convenient to write the infidelity as a ratio:
\[ 1-F_{\text{logical}}(p)=\frac{P_{\text{acc}}(p)-P_{\text{good}}(p)}{P_{\text{acc}}(p)}. \]
The numerator factors neatly:
\[ P_{\text{acc}}(p)-P_{\text{good}}(p)=\frac{16\,p^2\,(15-8p)\,(675-720p+256p^2)}{253125}. \]
Therefore,
\[ F_{\text{logical}}(p)=1-\frac{16\,p^2\,(15-8p)\,(675-720p+256p^2)}{(128p^2-300p+225)\,(2048p^3-5120p^2+3600p-1125)}. \]
  • Small-p expansion (useful sanity check): since all accepted single-fault events are “good,” the linear term vanishes:
\[ F_{\text{logical}}(p)=1-\frac{16}{25}p^2-\frac{704}{375}p^3+O(p^4). \]
  1. Mathematical Typesetting
  • All equations above are presented in LaTeX.
  1. Conventions and Units
  • Qubits are labeled 0,1,2,3 (data) and 4 (ancilla).
  • CNOT_{ij} has control i and target j.
  • Depolarizing parameter p per two-qubit gate as specified.
  1. Final Answer: F_logical(p) = 1 - [16 p^2 (15 - 8 p)(675 - 720 p + 256 p^2)] / [(128 p^2 - 300 p + 225)(2048 p^3 - 5120 p^2 + 3600 p - 1125)].

Equivalently, F_logical(p) = (229376 p^5 - 1116160 p^4 + 2198400 p^3 - 2214000 p^2 + 1147500 p - 253125) / (262144 p^5 - 1269760 p^4 + 2457600 p^3 - 2376000 p^2 + 1147500 p - 253125).

User #29

Populate your final answer into the code template provided below. This step is purely for formatting/display purposes. No additional reasoning or derivation should be performed. Do not import any modules or packages beyond what is provided in the template.

import sympy as sp

p = sp.symbols('p')

def answer(p):
    r"""
    Return the expression of the logical state fidelity of the final 2-qubit logical state
    at the end of the circuit as a function of two-qubit gate error rate $p$.

    Inputs
    ----------
    p: sympy.Symbol, two-qubit gate error rate, $p$

    Outputs
    ----------
    F_logical: sympy.Expr, logical state fidelity of the final 2-qubit logical state
    """

    # ------------------ FILL IN YOUR RESULTS BELOW ------------------
    F_logical = ...  # a SymPy expression of inputs
    # ---------------------------------------------------------------

    return F_logical
Assistant #30
import sympy as sp

p = sp.symbols('p')

def answer(p):
    r"""
    Return the expression of the logical state fidelity of the final 2-qubit logical state
    at the end of the circuit as a function of two-qubit gate error rate $p$.

    Inputs
    ----------
    p: sympy.Symbol, two-qubit gate error rate, $p$

    Outputs
    ----------
    F_logical: sympy.Expr, logical state fidelity of the final 2-qubit logical state
    """

    # ------------------ FILL IN YOUR RESULTS BELOW ------------------
    F_logical = (229376*p**5 - 1116160*p**4 + 2198400*p**3 - 2214000*p**2 + 1147500*p - 253125) / (262144*p**5 - 1269760*p**4 + 2457600*p**3 - 2376000*p**2 + 1147500*p - 253125)
    # ---------------------------------------------------------------

    return F_logical