# Re-run computation succinctly
from itertools import product
n=5
char_to_xz = {'I':(0,0),'X':(1,0),'Z':(0,1),'Y':(1,1)}
xz_to_char = {v:k for k,v in char_to_xz.items()}
mult_table = {
('I','I'): ('I',1), ('I','X'): ('X',1), ('I','Y'): ('Y',1), ('I','Z'): ('Z',1),
('X','I'): ('X',1), ('X','X'): ('I',1), ('X','Y'): ('Y',1j), ('X','Z'): ('Z',-1j),
('Y','I'): ('Y',1), ('Y','X'): ('Y',-1j), ('Y','Y'): ('I',1), ('Y','Z'): ('Z',1j),
('Z','I'): ('Z',1), ('Z','X'): ('Z',1j), ('Z','Y'): ('Z',-1j), ('Z','Z'): ('I',1),
}
def pauli_mul(P,Q):
out=[]; ph=1+0j
for a,b in zip(P,Q):
c, ph2 = mult_table[(a,b)]
out.append(c); ph *= ph2
return ''.join(out), ph
def conj_by_cnot(P,c,t):
xs=[]; zs=[]
for ch in P:
x,z = char_to_xz[ch]
xs.append(x); zs.append(z)
xc, zc = xs[c], zs[c]
xt, zt = xs[t], zs[t]
xs[c] = xc
zs[c] = zc ^ zt
xs[t] = xc ^ xt
zs[t] = zt
return ''.join(xz_to_char[(xs[i],zs[i])] for i in range(n))
def twoq_nonid_on_pair(i,j):
res=[]
for a in 'IXYZ':
for b in 'IXYZ':
if a=='I' and b=='I':
continue
P=['I']*n
P[i]=a; P[j]=b
res.append(''.join(P))
return res
Sx='XXXX'; Sz='ZZZZ'
def sympl_commute(P4,Q4):
s=0
for a,b in zip(P4,Q4):
xa,za = char_to_xz[a]
xb,zb = char_to_xz[b]
s ^= (xa & zb) ^ (za & xb)
return s
def accept_code(P4):
return sympl_commute(P4,Sx)==0 and sympl_commute(P4,Sz)==0
def accept_anc(ch):
return ch in ('I','Z')
def good_logical(P4):
xs = [1 if ch in ('X','Y') else 0 for ch in P4]
return sum(xs) in (0,4)
# Gate sequence
gate_list=[(1,2),(1,0),(2,3),(3,4),(0,4)]
# Precompute conj errors
conj_errors=[]
for gi,(c,t) in enumerate(gate_list):
errs=twoq_nonid_on_pair(c,t)
cl=[]
for P in errs:
Q=P
for gj in range(gi+1,len(gate_list)):
cc,tt = gate_list[gj]
Q=conj_by_cnot(Q,cc,tt)
cl.append(Q)
conj_errors.append(cl)
# single stats
single_stats=[]
for gi in range(len(gate_list)):
acc=0; bad=0
for Q in conj_errors[gi]:
P4=Q[:4]; anc=Q[4]
if accept_anc(anc) and accept_code(P4):
acc += 1
if not good_logical(P4):
bad += 1
single_stats.append((acc,bad))
print('single per gate: (accepted, bad) out of 15')
for i,(a,b) in enumerate(single_stats):
print(i, gate_list[i], a, b, 'acc_frac', a/15)
# double stats
from itertools import product
double_stats={}
for i in range(len(gate_list)):
for j in range(i+1,len(gate_list)):
acc=0; bad=0; total=0
for Qi in conj_errors[i]:
for Qj in conj_errors[j]:
Pij,_=pauli_mul(Qi,Qj)
if accept_anc(Pij[4]) and accept_code(Pij[:4]):
acc += 1
if not good_logical(Pij[:4]):
bad += 1
total += 1
double_stats[(i,j)]=(acc,bad,total)
print('\nDouble stats: (i,j)->(acc,bad,total), acc_frac, bad_frac')
for k,(acc,bad,total) in double_stats.items():
af=acc/total; bf=bad/total
print(k, (gate_list[k[0]],gate_list[k[1]]), (acc,bad,total), af, bf)
# coefficients
a_i=[acc/15 for acc,bad in single_stats]
Sigma_a1 = sum(a_i)
a_ij = {k: acc/total for k,(acc,bad,total) in double_stats.items()}
b_ij = {k: bad/total for k,(acc,bad,total) in double_stats.items()}
Sigma_a2 = sum(a_ij.values())
Sigma_b2 = sum(b_ij.values())
beta = 5 - Sigma_a1
gamma = 10 - 4*Sigma_a1 + Sigma_a2
c = Sigma_b2
print('\nSums:')
print('Sum a_i =', Sigma_a1)
print('Sum a_ij =', Sigma_a2)
print('Sum b_ij =', Sigma_b2)
print('beta =', beta)
print('gamma =', gamma)
print('c =', c)