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