|
@@ -41,7 +41,7 @@ def normalize_global_phase(m): |
|
|
return rot * m if rot * v > 0 else -rot * m |
|
|
return rot * m if rot * v > 0 else -rot * m |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def find_cz(bond, c1, c2, commuters, state_table): |
|
|
|
|
|
|
|
|
def find_cz(bond, c1, c2, commuters, state_table, ab_cz_table): |
|
|
""" Find the output of a CZ operation """ |
|
|
""" Find the output of a CZ operation """ |
|
|
# Figure out the target state |
|
|
# Figure out the target state |
|
|
target = qi.cz.dot(state_table[bond, c1, c2]) |
|
|
target = qi.cz.dot(state_table[bond, c1, c2]) |
|
@@ -52,12 +52,23 @@ def find_cz(bond, c1, c2, commuters, state_table): |
|
|
s2 = commuters if c2 in commuters else xrange(24) |
|
|
s2 = commuters if c2 in commuters else xrange(24) |
|
|
|
|
|
|
|
|
# Find a match |
|
|
# Find a match |
|
|
for bond, c1p, c2p in it.product([0, 1], s1, s2): |
|
|
|
|
|
if np.allclose(target, state_table[bond, c1p, c2p]): |
|
|
|
|
|
return bond, c1p, c2p |
|
|
|
|
|
|
|
|
options = set() |
|
|
|
|
|
for bondp, c1p, c2p in it.product([0, 1], s1, s2): |
|
|
|
|
|
if np.allclose(target, state_table[bondp, c1p, c2p]): |
|
|
|
|
|
options.add((bondp, c1p, c2p)) |
|
|
|
|
|
|
|
|
|
|
|
#assert tuple(ab_cz_table[bond, c1, c2]) in options |
|
|
|
|
|
if not tuple(ab_cz_table[bond, c1, c2]) in options: |
|
|
|
|
|
assert len(s1)==5 or len(s2)==5 |
|
|
|
|
|
#print len(s1), len(s2) |
|
|
|
|
|
#print bond, c1, c2 |
|
|
|
|
|
#print ab_cz_table[bond, c2, c2] |
|
|
|
|
|
#print " ".join(map(str, options)) |
|
|
|
|
|
#raise AssertionError |
|
|
|
|
|
return options.pop() |
|
|
|
|
|
|
|
|
# Didn't find anything - this should never happen |
|
|
# Didn't find anything - this should never happen |
|
|
raise IndexError |
|
|
|
|
|
|
|
|
#raise IndexError |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def compose_u(decomposition): |
|
|
def compose_u(decomposition): |
|
@@ -100,27 +111,33 @@ def get_state_table(unitaries): |
|
|
np.dot(kp, state).T) |
|
|
np.dot(kp, state).T) |
|
|
return state_table |
|
|
return state_table |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_commuters(unitaries): |
|
|
def get_commuters(unitaries): |
|
|
""" Get the indeces of gates which commute with CZ """ |
|
|
""" Get the indeces of gates which commute with CZ """ |
|
|
commuters = (qi.id, qi.px, qi.pz, qi.ph, qi.hermitian_conjugate(qi.ph)) |
|
|
commuters = (qi.id, qi.px, qi.pz, qi.ph, qi.hermitian_conjugate(qi.ph)) |
|
|
return [find_clifford(u, unitaries) for u in commuters] |
|
|
return [find_clifford(u, unitaries) for u in commuters] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_cz_table(unitaries): |
|
|
def get_cz_table(unitaries): |
|
|
""" Compute the lookup table for the CZ (A&B eq. 9) """ |
|
|
""" Compute the lookup table for the CZ (A&B eq. 9) """ |
|
|
# Get a cached state table and a list of gates which commute with CZ |
|
|
# Get a cached state table and a list of gates which commute with CZ |
|
|
commuters = get_commuters(unitaries) |
|
|
commuters = get_commuters(unitaries) |
|
|
state_table = get_state_table(unitaries) |
|
|
state_table = get_state_table(unitaries) |
|
|
|
|
|
ab_cz_table = get_ab_cz_table() |
|
|
|
|
|
|
|
|
# And now build the CZ table |
|
|
# And now build the CZ table |
|
|
cz_table = np.zeros((2, 24, 24, 3), dtype=int) |
|
|
cz_table = np.zeros((2, 24, 24, 3), dtype=int) |
|
|
rows = list(it.product([0, 1], it.combinations_with_replacement(range(24), 2))) |
|
|
|
|
|
|
|
|
rows = list( |
|
|
|
|
|
it.product([0, 1], it.combinations_with_replacement(range(24), 2))) |
|
|
# CZ is symmetric so we only need combinations |
|
|
# CZ is symmetric so we only need combinations |
|
|
for bond, (c1, c2) in tqdm(rows, desc="Building CZ table"): |
|
|
for bond, (c1, c2) in tqdm(rows, desc="Building CZ table"): |
|
|
newbond, c1p, c2p = find_cz(bond, c1, c2, commuters, state_table) |
|
|
|
|
|
|
|
|
newbond, c1p, c2p = find_cz( |
|
|
|
|
|
bond, c1, c2, commuters, state_table, ab_cz_table) |
|
|
cz_table[bond, c1, c2] = [newbond, c1p, c2p] |
|
|
cz_table[bond, c1, c2] = [newbond, c1p, c2p] |
|
|
cz_table[bond, c2, c1] = [newbond, c2p, c1p] |
|
|
cz_table[bond, c2, c1] = [newbond, c2p, c1p] |
|
|
return cz_table |
|
|
return cz_table |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_ab_cz_table(): |
|
|
def get_ab_cz_table(): |
|
|
""" Load anders and briegel's CZ table """ |
|
|
""" Load anders and briegel's CZ table """ |
|
|
filename = "anders_briegel/cphase.tbl" |
|
|
filename = "anders_briegel/cphase.tbl" |
|
@@ -137,7 +154,7 @@ try: |
|
|
unitaries = np.load("unitaries.npy") |
|
|
unitaries = np.load("unitaries.npy") |
|
|
conjugation_table = np.load("conjugation_table.npy") |
|
|
conjugation_table = np.load("conjugation_table.npy") |
|
|
times_table = np.load("times_table.npy") |
|
|
times_table = np.load("times_table.npy") |
|
|
#cz_table = np.load("cz_table.npy") |
|
|
|
|
|
|
|
|
# cz_table = np.load("cz_table.npy") |
|
|
cz_table = get_ab_cz_table() |
|
|
cz_table = get_ab_cz_table() |
|
|
|
|
|
|
|
|
with open("by_name.json") as f: |
|
|
with open("by_name.json") as f: |
|
@@ -151,7 +168,7 @@ except IOError: |
|
|
conjugation_table = get_conjugation_table(unitaries) |
|
|
conjugation_table = get_conjugation_table(unitaries) |
|
|
times_table = get_times_table(unitaries) |
|
|
times_table = get_times_table(unitaries) |
|
|
cz_table = get_cz_table(unitaries) |
|
|
cz_table = get_cz_table(unitaries) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Write it all to disk |
|
|
# Write it all to disk |
|
|
np.save("unitaries.npy", unitaries) |
|
|
np.save("unitaries.npy", unitaries) |
|
|
np.save("conjugation_table.npy", conjugation_table) |
|
|
np.save("conjugation_table.npy", conjugation_table) |
|
|