|
@@ -1,18 +1,17 @@ |
|
|
#!/usr/bin/python |
|
|
|
|
|
# -*- coding: utf-8 -*- |
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
|
|
|
|
""" |
|
|
""" |
|
|
This program generates lookup tables |
|
|
|
|
|
|
|
|
This program generates lookup tables and handles the Clifford group |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
import os, json |
|
|
|
|
|
|
|
|
import os, json, tempfile, os, sys, json, string |
|
|
from functools import reduce |
|
|
from functools import reduce |
|
|
import itertools as it |
|
|
import itertools as it |
|
|
import qi |
|
|
|
|
|
import numpy as np |
|
|
import numpy as np |
|
|
import tempfile |
|
|
|
|
|
from tqdm import tqdm |
|
|
from tqdm import tqdm |
|
|
import os, sys, json, string |
|
|
|
|
|
|
|
|
import argparse |
|
|
|
|
|
|
|
|
|
|
|
import qi |
|
|
|
|
|
|
|
|
decompositions = ("xxxx", "xx", "zzxx", "zz", "zxx", "z", "zzz", "xxz", |
|
|
decompositions = ("xxxx", "xx", "zzxx", "zz", "zxx", "z", "zzz", "xxz", |
|
|
"xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x", |
|
|
"xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x", |
|
@@ -32,7 +31,8 @@ def find_clifford(needle, haystack): |
|
|
return i |
|
|
return i |
|
|
raise IndexError |
|
|
raise IndexError |
|
|
|
|
|
|
|
|
def find_cz(bond, c1, c2, commuters, state_table, ab_cz_table): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def find_cz(bond, c1, c2, commuters, state_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]) |
|
@@ -66,7 +66,7 @@ def get_unitaries(): |
|
|
def get_by_name(unitaries): |
|
|
def get_by_name(unitaries): |
|
|
""" Get a lookup table of cliffords by name """ |
|
|
""" Get a lookup table of cliffords by name """ |
|
|
a = {name: find_clifford(u, unitaries) |
|
|
a = {name: find_clifford(u, unitaries) |
|
|
for name, u in qi.by_name.items()} |
|
|
|
|
|
|
|
|
for name, u in qi.by_name.items()} |
|
|
b = {get_name(i): i for i in range(24)} |
|
|
b = {get_name(i): i for i in range(24)} |
|
|
a.update(b) |
|
|
a.update(b) |
|
|
return a |
|
|
return a |
|
@@ -106,7 +106,6 @@ def get_cz_table(unitaries): |
|
|
# 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) |
|
@@ -115,36 +114,38 @@ def get_cz_table(unitaries): |
|
|
# 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( |
|
|
newbond, c1p, c2p = find_cz( |
|
|
bond, c1, c2, commuters, state_table, ab_cz_table) |
|
|
|
|
|
|
|
|
bond, c1, c2, commuters, state_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(): |
|
|
|
|
|
""" Load anders and briegel's CZ table """ |
|
|
|
|
|
filename = "anders_briegel/cphase.tbl" |
|
|
|
|
|
filename = os.path.join(os.path.dirname(sys.path[0]), filename) |
|
|
|
|
|
with open(filename) as f: |
|
|
|
|
|
s = f.read().translate(string.maketrans("{}", "[]")) |
|
|
|
|
|
return np.array(json.loads(s)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# First try to load tables from cache. If that fails, build them from |
|
|
# First try to load tables from cache. If that fails, build them from |
|
|
# scratch and store |
|
|
|
|
|
|
|
|
# scratch and store in /tmp/ |
|
|
os.chdir(tempfile.gettempdir()) |
|
|
os.chdir(tempfile.gettempdir()) |
|
|
try: |
|
|
try: |
|
|
if __name__ == "__main__": |
|
|
if __name__ == "__main__": |
|
|
raise IOError |
|
|
raise IOError |
|
|
|
|
|
|
|
|
|
|
|
# Parse command line args |
|
|
|
|
|
parser = argparse.ArgumentParser() |
|
|
|
|
|
parser.add_argument("-l", "--legacy", help="Use legacy CZ table", action="store_true", default=False) |
|
|
|
|
|
args = parser.parse_args() |
|
|
|
|
|
legacy_cz = args.legacy |
|
|
|
|
|
|
|
|
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 = get_ab_cz_table() |
|
|
|
|
|
|
|
|
if legacy_cz: |
|
|
|
|
|
import anders_cz |
|
|
|
|
|
cz_table = anders_cz.cz_table |
|
|
|
|
|
else: |
|
|
|
|
|
cz_table = np.load("cz_table.npy") |
|
|
|
|
|
|
|
|
with open("by_name.json") as f: |
|
|
with open("by_name.json") as f: |
|
|
by_name = json.load(f) |
|
|
by_name = json.load(f) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print "Loaded tables from cache" |
|
|
print "Loaded tables from cache" |
|
|
except IOError: |
|
|
except IOError: |
|
|
# Spend time building the tables |
|
|
# Spend time building the tables |
|
@@ -153,7 +154,6 @@ 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) |
|
|
#cz_table = get_ab_cz_table() |
|
|
|
|
|
|
|
|
|
|
|
# Write it all to disk |
|
|
# Write it all to disk |
|
|
np.save("unitaries.npy", unitaries) |
|
|
np.save("unitaries.npy", unitaries) |
|
|