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
  • Ideal (error-free) output state
  • Assume the physical qubits start in |0000⟩.
  • Apply H2 then CNOT21: this prepares a Bell state on qubits (2,1):
\[ \]
  • Apply H0 then CNOT03: this prepares a Bell state on qubits (0,3):
\[ \]
  • Hence the ideal final 4-qubit state factorizes:
\[ |\psi_{\mathrm{id}}\rangle = |\Phi^+\rangle_{21}\otimes|\Phi^+\rangle_{03}. \]
  • Noise model and factorization
  • Each CNOT is followed by a two-qubit depolarizing Pauli channel on its two qubits:
\[ \mathcal{E}(\rho)=(1-p)\rho+\frac{p}{15}\sum_{P\in\mathcal{P}_2\setminus\{I\}}P\rho P, \]
where the sum is over the 15 non-identity two-qubit Paulis on that pair.
  • The first noise channel acts on (2,1) after CNOT21; the second acts on (0,3) after CNOT03. Since subsequent gates act on disjoint qubits, the final state is
\[ \rho_{\mathrm{final}}=\mathcal{E}_{21}\big(|\Phi^+\rangle\langle\Phi^+|_{21}\big)\ \otimes\ \mathcal{E}_{03}\big(|\Phi^+\rangle\langle\Phi^+|_{03}\big). \]
  • Therefore, the physical state fidelity to the ideal pure state factorizes:
\[ \]
where
\[ F_{\Phi^+}(p)=\langle\Phi^+|\mathcal{E}(|\Phi^+\rangle\langle\Phi^+|)|\Phi^+\rangle. \]
  • Fidelity of a Bell state under the two-qubit Pauli depolarizing channel
  • For a Bell state, among the 15 non-identity two-qubit Paulis, exactly three map |Φ+⟩ to ±|Φ+⟩ (namely XX, YY, ZZ); the other 12 map it to a Bell state orthogonal to |Φ+⟩. Thus,
\[ F_{\Phi^+}(p)=(1-p)\cdot 1+\frac{p}{15}\big(3\cdot 1+12\cdot 0\big)=1-\frac{4p}{5}. \]
Equivalently, using the identity
\[ \]
we get
\[ F_{\Phi^+}(p)=\Big(1-\frac{16p}{15}\Big)+\frac{4p}{15}\cdot\frac{1}{4}=1-\frac{4p}{5}. \]
  • Combine the two independent pairs
\[ \]
  1. Mathematical Typesetting
  • All expressions above are given in LaTeX.
  1. Conventions and Units
  • Standard quantum information conventions; no physical units are involved.
  1. Final Answer: F_phys(p) = (1 - 4p/5)^2 = 1 - (8/5)p + (16/25)p^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
  1. Step-by-Step Derivation
  • Ideal output and factorization
  • The circuit prepares two independent Bell pairs on disjoint qubit pairs:
\[ \]
  • A two-qubit depolarizing channel follows each CNOT, one on pair (2,1) and one on pair (0,3), acting independently.

  • Action of the two-qubit depolarizing channel on a Bell state

  • For a single pair, the channel is
\[ \mathcal{E}(\rho)=(1-p)\rho+\frac{p}{15}\sum_{P\in\mathcal{P}_2\setminus\{I\}}P\rho P. \]
  • Among the 15 non-identity two-qubit Paulis, exactly 3 stabilize \(|\Phi^+\rangle\) (up to phase): \(XX,YY,ZZ\); the other 12 map it uniformly onto the other 3 Bell states. Therefore, for each pair independently,
\[ \]
  • Post-selection on the [[4,2,2]] code stabilizers
  • The stabilizers are \(S_X=XXXX\) and \(S_Z=ZZZZ\).
  • Writing \(S_X=(X\!\otimes\!X)_{03}(X\!\otimes\!X)_{21}\) and \(S_Z=(Z\!\otimes\!Z)_{03}(Z\!\otimes\!Z)_{21}\), the eigenvalue on the 4-qubit state is the product of the eigenvalues on each Bell pair.
  • Each Bell state is labeled by its \((XX,ZZ)\) eigenvalues:
\[ \Phi^+:(+,+),\ \Phi^-:(-,+),\ \Psi^+:(+,-),\ \Psi^-:(-,-). \]
  • Hence a 4-qubit product \(|B_j\rangle_{21}\otimes|B_k\rangle_{03}\) has
\[ S_X\text{-eigenvalue}=a_j a_k,\qquad S_Z\text{-eigenvalue}=b_j b_k, \]
where $(a_j,b_j)$ are the $(XX,ZZ)$ eigenvalues of $|B_j\rangle$.
  • Post-selection (acceptance) requires both be \(+1\), i.e., \(a_j=a_k\) and \(b_j=b_k\), which is equivalent to \(j=k\). Therefore, the only accepted 4-qubit states are
\[ |B_j\rangle_{21}\otimes|B_j\rangle_{03},\qquad j\in\{\Phi^+,\Phi^-,\Psi^+,\Psi^-\}. \]
  • Accepted ensemble and logical fidelity
  • Because the two pairs are independent, the unnormalized weights of the accepted states are \(a^2\) for \(j=\Phi^+\) and \(b^2\) for each of the other three \(j\)’s. The acceptance probability is
\[ P_{\mathrm{acc}}=a^2+3b^2. \]
  • These four accepted code states are orthonormal and correspond to the four logical Bell states; only \(j=\Phi^+\) equals the target logical GHZ state. Therefore, the logical state fidelity conditioned on acceptance is
\[ \]
  • Closed form
\[ {\big(1-\tfrac{12}{15}p\big)^2+3\big(\tfrac{4}{15}p\big)^2} =\frac{(1-\tfrac{4}{5}p)^2}{(1-\tfrac{4}{5}p)^2+\tfrac{16}{75}p^2} \]
  • Small-\(p\) expansion (showing distance-2 behavior under post-selection):
\[ F_{\mathrm{logical}}(p)=1-\frac{16}{75}p^2+O(p^3). \]
  1. Mathematical Typesetting
  • All equations are presented in LaTeX as required.
  1. Conventions and Units
  • Quantum information setting; no physical units.
  1. Final Answer: F_logical(p) = [(1 - 12p/15)^2] / [(1 - 12p/15)^2 + 3(4p/15)^2] = (1 - 8p/5 + 16p^2/25) / (1 - 8p/5 + 64p^2/75).
User #5

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 #6
Tool Call (code to execute)
import numpy as np
from itertools import product, combinations

# Define single-qubit Pauli matrices
I = np.array([[1,0],[0,1]], dtype=complex)
X = np.array([[0,1],[1,0]], dtype=complex)
Y = np.array([[0,-1j],[1j,0]], dtype=complex)
Z = np.array([[1,0],[0,-1]], dtype=complex)
H = (1/np.sqrt(2))*np.array([[1,1],[1,-1]], dtype=complex)

paulis = {'I':I, 'X':X, 'Y':Y, 'Z':Z}
labels = ['I','X','Y','Z']

# Tensor product utility for applying single-qubit unitary on k-th qubit (0..4, 0 is left-most)
def apply_1q(U, k, num=5):
    ops = [I]*num
    ops[k] = U
    M = ops[0]
    for i in range(1,num):
        M = np.kron(M, ops[i])
    return M

# Build CNOT matrix on n-qubit system, control c, target t (0..n-1)
def CNOT(n, c, t):
    dim = 2**n
    U = np.zeros((dim,dim), dtype=complex)
    # basis |q0 q1 ... q_{n-1}>
    for idx in range(dim):
        # compute bit values
        bits = [(idx >> (n-1-k)) & 1 for k in range(n)]  # q0 is most significant
        new_bits = bits.copy()
        if bits[c] == 1:
            new_bits[t] ^= 1
        # map to new index
        new_idx = 0
        for k in range(n):
            new_idx = (new_idx << 1) | new_bits[k]
        U[new_idx, idx] = 1.0
    return U

# Apply 2-qubit Pauli P_a \otimes P_b on qubits (qa, qb) in n qubits
# qa and qb are distinct

def two_qubit_pauli(n, qa, qb, label_a, label_b):
    ops = [I]*n
    ops[qa] = paulis[label_a]
    ops[qb] = paulis[label_b]
    M = ops[0]
    for i in range(1,n):
        M = np.kron(M, ops[i])
    return M

# Projector onto ancilla |0> on qubit index 4
n = 5
anc = 4

# Build projectors for code stabilizers on 4 data qubits (0..3)
# S_X = X X X X; S_Z = Z Z Z Z
Sx = np.kron(np.kron(np.kron(X,X),X),X)
Sz = np.kron(np.kron(np.kron(Z,Z),Z),Z)
P_code = 0.25*(np.eye(16) + Sx) @ (np.eye(16) + Sz)

# Target codeword |00>_AB physical representative: take GHZ+ = (|0000>+|1111>)/sqrt2
v0000 = np.zeros(16, dtype=complex); v0000[0] = 1.0
v1111 = np.zeros(16, dtype=complex); v1111[-1] = 1.0
code00 = (v0000 + v1111)/np.sqrt(2)
# Normalize (should already be normalized)
code00 = code00 / np.linalg.norm(code00)

# Build unitaries for the ideal gates: H1, CNOTs in order
U_H1 = apply_1q(H, 1, num=5)
U_c12 = CNOT(5, 1, 2)
U_c10 = CNOT(5, 1, 0)
U_c23 = CNOT(5, 2, 3)
U_c34 = CNOT(5, 3, 4)
U_c04 = CNOT(5, 0, 4)

# The circuit unitary with error placeholders: We'll apply sequentially

# Initial state |00000>
psi0 = np.zeros(32, dtype=complex)
psi0[0] = 1.0

# Enumerate single- and double-error cases
# List gates and their qubit pairs for errors
# Order: after each CNOT: (12), (10), (23), (34), (04)
gate_pairs = [(1,2),(1,0),(2,3),(3,4),(0,4)]
U_gates = [U_H1, U_c12, U_c10, U_c23, U_c34, U_c04]  # include H as first then CNOTs

# Precompute sequence unitaries for speed? We'll just apply directly each time.

# Generate non-identity two-qubit Pauli labels
pauli2 = [(a,b) for a in labels for b in labels]
pauli2_nonid = [(a,b) for (a,b) in pauli2 if not (a=='I' and b=='I')]

# Function to run the circuit with a list of 5 errors (each either None or (label_a,label_b) for that CNOT)
def run_with_errors(err_list):
    psi = psi0.copy()
    # H1
    psi = U_H1 @ psi
    # CNOT12 then error 0
    psi = U_c12 @ psi
    if err_list[0] is not None:
        a,b = err_list[0]
        E = two_qubit_pauli(5, 1, 2, a, b)
        psi = E @ psi
    # CNOT10 then error 1
    psi = U_c10 @ psi
    if err_list[1] is not None:
        a,b = err_list[1]
        E = two_qubit_pauli(5, 1, 0, a, b)
        psi = E @ psi
    # CNOT23 then error 2
    psi = U_c23 @ psi
    if err_list[2] is not None:
        a,b = err_list[2]
        E = two_qubit_pauli(5, 2, 3, a, b)
        psi = E @ psi
    # CNOT34 then error 3
    psi = U_c34 @ psi
    if err_list[3] is not None:
        a,b = err_list[3]
        E = two_qubit_pauli(5, 3, 4, a, b)
        psi = E @ psi
    # CNOT04 then error 4
    psi = U_c04 @ psi
    if err_list[4] is not None:
        a,b = err_list[4]
        E = two_qubit_pauli(5, 0, 4, a, b)
        psi = E @ psi
    return psi

# Function to compute acceptance probabilities and fidelity to code00

def acceptance_and_fidelity(psi):
    # Project ancilla to |0>
    psi_tensor = psi.reshape(2,2,2,2,2)
    # Post-select ancilla = 0 component
    phi_data = psi_tensor[:,:,:,:,0].reshape(16)
    p_anc0 = np.vdot(phi_data, phi_data).real
    if p_anc0 == 0:
        return 0.0, 0.0
    # Normalize after ancilla measurement
    phi_data = phi_data / np.sqrt(p_anc0)
    # Project onto codespace
    chi = P_code @ phi_data
    p_code = np.vdot(chi, chi).real
    if p_code == 0:
        return 0.0, 0.0
    chi = chi / np.sqrt(p_code)
    # Fidelity to code00
    F = abs(np.vdot(code00, chi))**2
    return p_anc0 * p_code, p_anc0 * p_code * F

# Baseline (no error)
psi_clean = run_with_errors([None]*5)
p_acc0, p_good0 = acceptance_and_fidelity(psi_clean)
# Sanity checks
print('Clean acceptance prob:', p_acc0, 'Clean fidelity contribution:', p_good0)

# Single-error enumeration
acc1_sum = 0.0
num1_sum = 0.0
for loc in range(5):
    for (a,b) in pauli2_nonid:
        errs = [None]*5
        errs[loc] = (a,b)
        psi = run_with_errors(errs)
        p_acc, p_good = acceptance_and_fidelity(psi)
        acc1_sum += p_acc
        num1_sum += p_good
print('Single-error accepted total (sum over all 5*15 cases):', acc1_sum)
print('Single-error good total:', num1_sum)

# Double-error enumeration
acc2_sum = 0.0
num2_sum = 0.0
for loc1, loc2 in combinations(range(5), 2):
    for (a1,b1) in pauli2_nonid:
        for (a2,b2) in pauli2_nonid:
            errs = [None]*5
            errs[loc1] = (a1,b1)
            errs[loc2] = (a2,b2)
            psi = run_with_errors(errs)
            p_acc, p_good = acceptance_and_fidelity(psi)
            acc2_sum += p_acc
            num2_sum += p_good
print('Double-error accepted sum (over 10*225 cases):', acc2_sum)
print('Double-error good sum:', num2_sum)

# Now compute series coefficients up to O(p^2)
# D = (1-p)^5 + (p/15)(1-p)^4 * acc1_sum + (p/15)^2 (1-p)^3 * acc2_sum + O(p^3)
# N = (1-p)^5 + (p/15)(1-p)^4 * num1_sum + (p/15)^2 (1-p)^3 * num2_sum + O(p^3)

# Expand to O(p^2):
# (1-p)^5 = 1 - 5p + 10 p^2
# (p/15)(1-p)^4 = (p/15)(1 - 4p)
# (p/15)^2 (1-p)^3 = (p^2/225)

# Coefficients d1, d2, n1, n2 such that D = 1 - d1 p + d2 p^2, N = 1 - n1 p + n2 p^2

acc1 = acc1_sum
acc2 = acc2_sum
num1 = num1_sum
num2 = num2_sum

# Compute d1, d2, n1, n2
# D = 1 + [ -5 + acc1/15 ] p + [ 10 - 4*acc1/15 + acc2/225 ] p^2
# N = 1 + [ -5 + num1/15 ] p + [ 10 - 4*num1/15 + num2/225 ] p^2

d1 = 5 - acc1/15.0
n1 = 5 - num1/15.0
d2 = 10 - (4*acc1)/15.0 + acc2/225.0
n2 = 10 - (4*num1)/15.0 + num2/225.0

print('d1, d2 =', d1, d2)
print('n1, n2 =', n1, n2)

# Provide rational approximations maybe
Tool #7
Clean acceptance prob: 1.0 Clean fidelity contribution: 1.0000000000000004
Single-error accepted total (sum over all 5*15 cases): 7.0
Single-error good total: 7.000000000000002
Double-error accepted sum (over 10*225 cases): 282.0
Double-error good sum: 138.00000000000003
d1, d2 = 4.533333333333333 9.386666666666667
n1, n2 = 4.533333333333333 8.746666666666666
Assistant #8
Tool Call (code to execute)
# Identify which single-error cases are accepted
accepted_singles = []
for loc in range(5):
    for (a,b) in pauli2_nonid:
        errs = [None]*5
        errs[loc] = (a,b)
        psi = run_with_errors(errs)
        p_acc, p_good = acceptance_and_fidelity(psi)
        if p_acc > 1e-9:
            accepted_singles.append((loc,(a,b),p_acc,p_good))

len(accepted_singles), accepted_singles
Tool #9
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
NameError: name 'pauli2_nonid' is not defined
Assistant #10
# Recreate pauli2_nonid (was defined earlier but lost due to separate run)
labels = ['I','X','Y','Z']
pauli2_nonid = [(a,b) for a in labels for b in labels if not (a=='I' and b=='I')]

accepted_singles = []
for loc in range(5):
    for (a,b) in pauli2_nonid:
        # Need to reconstruct earlier functions and variables, re-define minimal required ones
        import numpy as np
        I = np.array([[1,0],[0,1]], dtype=complex)
        X = np.array([[0,1],[1,0]], dtype=complex)
        Y = np.array([[0,-1j],[1j,0]], dtype=complex)
        Z = np.array([[1,0],[0,-1]], dtype=complex)
        H = (1/np.sqrt(2))*np.array([[1,1],[1,-1]], dtype=complex)
        paulis = {'I':I, 'X':X, 'Y':Y, 'Z':Z}
        def apply_1q(U, k, num=5):
            ops = [I]*num
            ops[k] = U
            M = ops[0]
            for i in range(1,num):
                M = np.kron(M, ops[i])
            return M
        def CNOT(n, c, t):
            dim = 2**n
            U = np.zeros((dim,dim), dtype=complex)
            for idx in range(dim):
                bits = [(idx >> (n-1-k)) & 1 for k in range(n)]
                new_bits = bits.copy()
                if bits[c] == 1:
                    new_bits[t] ^= 1
                new_idx = 0
                for k in range(n):
                    new_idx = (new_idx << 1) | new_bits[k]
                U[new_idx, idx] = 1.0
            return U
        def two_qubit_pauli(n, qa, qb, la, lb):
            ops = [I]*n
            ops[qa] = paulis[la]
            ops[qb] = paulis[lb]
            M = ops[0]
            for i in range(1,n):
                M = np.kron(M, ops[i])
            return M
        # Rebuild global items
        n=5
        anc=4
        X = paulis['X']; Z = paulis['Z']
        Sx = np.kron(np.kron(np.kron(X,X),X),X)
        Sz = np.kron(np.kron(np.kron(Z,Z),Z),Z)
        P_code = 0.25*(np.eye(16) + Sx) @ (np.eye(16) + Sz)
        v0000 = np.zeros(16, dtype=complex); v0000[0]=1.0
        v1111 = np.zeros(16, dtype=complex); v1111[-1]=1.0
        code00 = (v0000 + v1111)/np.sqrt(2); code00/=np.linalg.norm(code00)
        U_H1 = apply_1q(H,1,5)
        U_c12 = CNOT(5,1,2)
        U_c10 = CNOT(5,1,0)
        U_c23 = CNOT(5,2,3)
        U_c34 = CNOT(5,3,4)
        U_c04 = CNOT(5,0,4)
        psi0 = np.zeros(32, dtype=complex); psi0[0]=1.0
        def run_with_errors(err_list):
            psi = psi0.copy()
            psi = U_H1 @ psi
            psi = U_c12 @ psi
            if err_list[0] is not None:
                la,lb = err_list[0]
                E = two_qubit_pauli(5,1,2,la,lb)
                psi = E @ psi
            psi = U_c10 @ psi
            if err_list[1] is not None:
                la,lb = err_list[1]
                E = two_qubit_pauli(5,1,0,la,lb)
                psi = E @ psi
            psi = U_c23 @ psi
            if err_list[2] is not None:
                la,lb = err_list[2]
                E = two_qubit_pauli(5,2,3,la,lb)
                psi = E @ psi
            psi = U_c34 @ psi
            if err_list[3] is not None:
                la,lb = err_list[3]
                E = two_qubit_pauli(5,3,4,la,lb)
                psi = E @ psi
            psi = U_c04 @ psi
            if err_list[4] is not None:
                la,lb = err_list[4]
                E = two_qubit_pauli(5,0,4,la,lb)
                psi = E @ psi
            return psi
        def acceptance_and_fidelity(psi):
            psi_tensor = psi.reshape(2,2,2,2,2)
            phi_data = psi_tensor[:,:,:,:,0].reshape(16)
            p_anc0 = np.vdot(phi_data, phi_data).real
            if p_anc0 == 0:
                return 0.0, 0.0
            phi_data = phi_data/np.sqrt(p_anc0)
            chi = P_code @ phi_data
            p_code = np.vdot(chi, chi).real
            if p_code == 0:
                return 0.0, 0.0
            chi /= np.sqrt(p_code)
            F = abs(np.vdot(code00, chi))**2
            return p_anc0*p_code, p_anc0*p_code*F
        errs = [None]*5
        errs[loc] = (a,b)
        psi = run_with_errors(errs)
        p_acc, p_good = acceptance_and_fidelity(psi)
        if p_acc > 1e-9:
            accepted_singles.append((loc,(a,b),p_acc,p_good))

# Output the accepted singles
len(accepted_singles), accepted_singles[:20]
Tool #11
''
Assistant #12
Tool Call (code to execute)
# Let's reconstruct global environment properly and compute accepted singles and doubles again, with classification
import numpy as np
from itertools import product, combinations

I = np.array([[1,0],[0,1]], dtype=complex)
X = np.array([[0,1],[1,0]], dtype=complex)
Y = np.array([[0,-1j],[1j,0]], dtype=complex)
Z = np.array([[1,0],[0,-1]], dtype=complex)
H = (1/np.sqrt(2))*np.array([[1,1],[1,-1]], dtype=complex)
paulis = {'I':I, 'X':X, 'Y':Y, 'Z':Z}
labels = ['I','X','Y','Z']

# Utility functions

def apply_1q(U, k, num=5):
    ops = [I]*num
    ops[k] = U
    M = ops[0]
    for i in range(1,num):
        M = np.kron(M, ops[i])
    return M

def CNOT(n, c, t):
    dim = 2**n
    U = np.zeros((dim,dim), dtype=complex)
    for idx in range(dim):
        bits = [(idx >> (n-1-k)) & 1 for k in range(n)]
        new_bits = bits.copy()
        if bits[c] == 1:
            new_bits[t] ^= 1
        new_idx = 0
        for k in range(n):
            new_idx = (new_idx << 1) | new_bits[k]
        U[new_idx, idx] = 1.0
    return U

def two_qubit_pauli(n, qa, qb, la, lb):
    ops = [I]*n
    ops[qa] = paulis[la]
    ops[qb] = paulis[lb]
    M = ops[0]
    for i in range(1,n):
        M = np.kron(M, ops[i])
    return M

Sx4 = np.kron(np.kron(np.kron(X,X),X),X)
Sz4 = np.kron(np.kron(np.kron(Z,Z),Z),Z)
P_code = 0.25*(np.eye(16) + Sx4) @ (np.eye(16) + Sz4)

v0000 = np.zeros(16, dtype=complex); v0000[0]=1.0
v1111 = np.zeros(16, dtype=complex); v1111[-1]=1.0
code00 = (v0000 + v1111)/np.sqrt(2); code00/=np.linalg.norm(code00)

U_H1 = apply_1q(H,1,5)
U_c12 = CNOT(5,1,2)
U_c10 = CNOT(5,1,0)
U_c23 = CNOT(5,2,3)
U_c34 = CNOT(5,3,4)
U_c04 = CNOT(5,0,4)

psi0 = np.zeros(32, dtype=complex); psi0[0]=1.0

def run_with_errors(err_list):
    psi = psi0.copy()
    psi = U_H1 @ psi
    psi = U_c12 @ psi
    if err_list[0] is not None:
        la,lb = err_list[0]
        psi = two_qubit_pauli(5,1,2,la,lb) @ psi
    psi = U_c10 @ psi
    if err_list[1] is not None:
        la,lb = err_list[1]
        psi = two_qubit_pauli(5,1,0,la,lb) @ psi
    psi = U_c23 @ psi
    if err_list[2] is not None:
        la,lb = err_list[2]
        psi = two_qubit_pauli(5,2,3,la,lb) @ psi
    psi = U_c34 @ psi
    if err_list[3] is not None:
        la,lb = err_list[3]
        psi = two_qubit_pauli(5,3,4,la,lb) @ psi
    psi = U_c04 @ psi
    if err_list[4] is not None:
        la,lb = err_list[4]
        psi = two_qubit_pauli(5,0,4,la,lb) @ psi
    return psi

# Acceptance and fidelity

def acc_and_good(psi):
    psi_t = psi.reshape(2,2,2,2,2)
    data = psi_t[:,:,:,:,0].reshape(16)
    p_anc0 = float(np.vdot(data,data).real)
    if p_anc0 == 0:
        return 0.0, 0.0
    data /= np.sqrt(p_anc0)
    proj = P_code @ data
    p_code = float(np.vdot(proj,proj).real)
    if p_code == 0:
        return 0.0, 0.0
    proj /= np.sqrt(p_code)
    F = float(abs(np.vdot(code00, proj))**2)
    return p_anc0*p_code, p_anc0*p_code*F

# Enumerate singles and list accepted ones
labels = ['I','X','Y','Z']
nonid = [(a,b) for a in labels for b in labels if not (a=='I' and b=='I')]
accepted = []
for loc in range(5):
    for (a,b) in nonid:
        err = [None]*5
        err[loc] = (a,b)
        psi = run_with_errors(err)
        pa, pg = acc_and_good(psi)
        if pa > 1e-12:
            accepted.append((loc, a+b, pa, pg))

print('count accepted singles:', len(accepted))
for item in accepted:
    print(item)
Tool #13
count accepted singles: 7
(0, 'XX', 1.0, 1.0000000000000004)
(0, 'YY', 1.0, 1.0000000000000004)
(0, 'ZZ', 1.0, 1.0000000000000004)
(1, 'ZZ', 1.0, 1.0000000000000004)
(2, 'ZZ', 1.0, 1.0000000000000004)
(3, 'ZZ', 1.0, 1.0000000000000004)
(4, 'IZ', 1.0, 1.0000000000000004)
Assistant #14
  1. Step-by-Step Derivation
  • Circuit and ideal output
  • Start from the 5-qubit initial state \(|0000\rangle_{0123}\otimes|0\rangle_4\).
  • Apply the circuit (right-to-left): 1) \(H_1\) 2) \(CNOT_{12}\) 3) \(CNOT_{10}\) 4) \(CNOT_{23}\) 5) \(CNOT_{34}\) 6) \(CNOT_{04}\) 7) Measure \(M_4\) in the \(Z\) basis.
  • The first three entangling steps prepare a 4-qubit GHZ state on data qubits:
    • \(H_1\) prepares \(|+\rangle_1\).
    • \(CNOT_{12}\) creates a Bell pair \((|00\rangle_{12}+|11\rangle_{12})/\sqrt2\).
    • \(CNOT_{10}\) extends this to a 3-qubit GHZ on \((1,2,0)\).
    • \(CNOT_{23}\) extends to a 4-qubit GHZ on \((1,2,0,3)\):
\[ |\mathrm{GHZ}^+\rangle_{0123}=\frac{|0000\rangle+|1111\rangle}{\sqrt2}. \]
  • This state satisfies \(ZZZZ=+1\) and \(XXXX=+1\), so it lies in the [[4,2,2]] codespace. Moreover
\[ Z_A=ZZII=+1,\qquad Z_B=ZIZI=+1, \]
so the encoded state is $|00\rangle_{AB}$.
  • The ancilla parity check \(CNOT_{34}\) and \(CNOT_{04}\) flips the ancilla by the parity of \((q_3\oplus q_0)\). In \(|\mathrm{GHZ}^+\rangle\), qubits 0 and 3 are equal, so the ideal ancilla outcome is \(|0\rangle\).

  • Noise model

  • After each CNOT there is a two-qubit depolarizing channel on its two qubits:
\[ \mathcal{E}(\rho)=(1-p)\rho+\frac{p}{15}\sum_{P\in\mathcal{P}_2\setminus\{I\}}P\rho P. \]
  • There are 5 such CNOTs, hence 5 fault locations. Post-selection discards runs with ancilla outcome \(|1\rangle\) and any run that has a nontrivial syndrome under the code stabilizers \(XXXX\) and \(ZZZZ\).

  • Single-fault analysis (order p)

  • Insert one non-identity two-qubit Pauli after one CNOT and analyze propagation through the remaining Clifford circuit and the post-selections.
  • A complete Pauli-stabilizer enumeration shows that, among the \(5\times 15=75\) possible single faults, exactly 7 pass all post-selections (ancilla \(=0\) and codespace). These 7 are:
    • After \(CNOT_{12}\): \(XX\), \(YY\), \(ZZ\) on \((1,2)\).
    • After \(CNOT_{10}\), \(CNOT_{23}\), \(CNOT_{34}\): only \(ZZ\) on the respective pairs.
    • After \(CNOT_{04}\): only \(I Z\) on \((0,4)\) (a \(Z\) on the ancilla).
  • All 7 accepted single faults act trivially on the logical state \(|00\rangle_{AB}\) (they are either stabilizers or logical \(Z\)’s, which have eigenvalue \(+1\) on \(|0\rangle\)). Therefore:

    • The accepted-probability and the accepted-correct-probability have the same linear term in \(p\).
    • Hence the conditional logical fidelity has no \(O(p)\) term (fault-tolerant, distance-2 behavior).
  • Double-fault analysis (order p^2)

  • Consider all pairs of fault locations \(\binom{5}{2}=10\) and all non-identity Pauli pairs at each, giving \(10\times 15\times 15=2250\) double-fault cases.
  • Exact enumeration (Clifford-Pauli propagation with projective post-selection) yields:

    • Accepted double faults: 282.
    • Among these, 138 post-select to the correct logical state \(|00\rangle_{AB}\) (they act as stabilizers or logical \(Z\)’s on \(|00\rangle\)).
    • The remaining 144 accepted cases implement a nontrivial \(X\) or \(Y\) on at least one logical qubit, mapping to an orthogonal logical basis state and thus reducing fidelity.
  • Assemble series to second order in p

  • Let \(D(p)\) be the total acceptance probability and \(N(p)\) be the probability of accepting and being in the correct logical state. Expanding to \(O(p^2)\):
    • Zero faults: \((1-p)^5 = 1 - 5p + 10p^2 + O(p^3)\).
    • Single faults (accepted): \(7 \times \frac{p}{15}(1-p)^4 = \frac{7}{15}p - \frac{28}{15}p^2 + O(p^3)\).
    • Double faults (accepted): \(282 \times \left(\frac{p}{15}\right)^2 + O(p^3) = \frac{282}{225}p^2 + O(p^3)\).
    • Correct double faults: \(138 \times \left(\frac{p}{15}\right)^2 + O(p^3) = \frac{138}{225}p^2 + O(p^3)\).
  • Collecting terms:
\[ \]
  • Hence the conditional logical fidelity is
\[ =\frac{1-\frac{68}{15}p+\frac{656}{75}p^2}{1-\frac{68}{15}p+\frac{704}{75}p^2} \]
  • Using \(\frac{704-656}{75}=\frac{48}{75}=\frac{16}{25}\), we get
\[ F_{\mathrm{logical}}(p)=1-\frac{\frac{16}{25}p^2}{1-\frac{68}{15}p+\frac{704}{75}p^2}+O(p^3). \]
  • Small-\(p\) expansion
\[ F_{\mathrm{logical}}(p)=1-\frac{16}{25}p^2+O(p^3), \]

showing distance-2 (fault-tolerant) suppression of logical infidelity.

  1. Mathematical Typesetting
  • All expressions are provided in LaTeX as required.
  1. Conventions and Units
  • Quantum information conventions; no physical units.
  1. Final Answer: F_logical(p) = 1 - [ (16/25) p^2 ] / [ 1 - (68/15) p + (704/75) p^2 ] + O(p^3).
User #15

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 #16
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 = 1 - (sp.Rational(16, 25) * p**2) / (1 - sp.Rational(68, 15) * p + sp.Rational(704, 75) * p**2)
    # ---------------------------------------------------------------

    return F_logical