@@ -1,18 +1,17 @@ | |||
#!/usr/bin/python | |||
# -*- 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 | |||
import itertools as it | |||
import qi | |||
import numpy as np | |||
import tempfile | |||
from tqdm import tqdm | |||
import os, sys, json, string | |||
import argparse | |||
import qi | |||
decompositions = ("xxxx", "xx", "zzxx", "zz", "zxx", "z", "zzz", "xxz", | |||
"xzx", "xzxxx", "xzzzx", "xxxzx", "xzz", "zzx", "xxx", "x", | |||
@@ -32,7 +31,8 @@ def find_clifford(needle, haystack): | |||
return i | |||
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 """ | |||
# Figure out the target state | |||
target = qi.cz.dot(state_table[bond, c1, c2]) | |||
@@ -66,7 +66,7 @@ def get_unitaries(): | |||
def get_by_name(unitaries): | |||
""" Get a lookup table of cliffords by name """ | |||
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)} | |||
a.update(b) | |||
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 | |||
commuters = get_commuters(unitaries) | |||
state_table = get_state_table(unitaries) | |||
ab_cz_table = get_ab_cz_table() | |||
# And now build the CZ table | |||
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 | |||
for bond, (c1, c2) in tqdm(rows, desc="Building CZ table"): | |||
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, c2, c1] = [newbond, c2p, c1p] | |||
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 | |||
# scratch and store | |||
# scratch and store in /tmp/ | |||
os.chdir(tempfile.gettempdir()) | |||
try: | |||
if __name__ == "__main__": | |||
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") | |||
conjugation_table = np.load("conjugation_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: | |||
by_name = json.load(f) | |||
print "Loaded tables from cache" | |||
except IOError: | |||
# Spend time building the tables | |||
@@ -153,7 +154,6 @@ except IOError: | |||
conjugation_table = get_conjugation_table(unitaries) | |||
times_table = get_times_table(unitaries) | |||
cz_table = get_cz_table(unitaries) | |||
#cz_table = get_ab_cz_table() | |||
# Write it all to disk | |||
np.save("unitaries.npy", unitaries) | |||
@@ -1,5 +1,6 @@ | |||
from abp.graphstate import GraphState | |||
from anders_briegel import graphsim | |||
from abp import clifford | |||
import random | |||
import difflib | |||
import re | |||
@@ -44,8 +45,13 @@ def test_local_rotations(): | |||
compare(a, b) | |||
def test_cz_table(): | |||
def test_cz_table(N=10): | |||
""" Test the CZ table """ | |||
# Don't test if we are using Pete's CZ table - doesn't make sense | |||
if not clifford.legacy_cz: | |||
return | |||
for j in range(24): | |||
a = graphsim.GraphRegister(2) | |||
b = GraphState() | |||
@@ -65,9 +71,8 @@ def test_cz_table(): | |||
def test_with_cphase_gates_hadamard_only(): | |||
def test_with_cphase_gates_hadamard_only(N=10): | |||
""" Hadamrds and CPHASEs, deterministic """ | |||
N=10 | |||
a = graphsim.GraphRegister(N) | |||
b = GraphState() | |||
@@ -84,9 +89,12 @@ def test_with_cphase_gates_hadamard_only(): | |||
compare(a, b) | |||
def test_all(): | |||
def test_all(N=10): | |||
""" Test all gates at random """ | |||
N=10 | |||
# Don't test if we are using Pete's CZ table - doesn't make sense | |||
if not clifford.legacy_cz: | |||
return | |||
a = graphsim.GraphRegister(N) | |||
b = GraphState() | |||
@@ -9,7 +9,7 @@ REPEATS = 100 | |||
def test_single_qubit(n=1): | |||
""" A multi qubit test with Hadamards only""" | |||
for repeat in tqdm(range(REPEATS), desc="Testing against circuit model") : | |||
for repeat in tqdm(range(REPEATS), desc="Testing against circuit model"): | |||
g = GraphState([0]) | |||
c = CircuitModel(1) | |||
@@ -23,7 +23,7 @@ def test_single_qubit(n=1): | |||
def test_hadamard_only_multiqubit(n=6): | |||
""" A multi qubit test with Hadamards only""" | |||
for repeat in tqdm(range(REPEATS), desc="Testing against circuit model") : | |||
for repeat in tqdm(range(REPEATS), desc="Testing against circuit model"): | |||
g = GraphState(range(n)) | |||
c = CircuitModel(n) | |||
@@ -54,21 +54,15 @@ def test_all_multiqubit(n=4): | |||
assert g.to_state_vector() == c | |||
for repeat in tqdm(range(REPEATS), desc="Testing against circuit model") : | |||
a, b = np.random.randint(0, n-1, 2) | |||
for repeat in tqdm(range(REPEATS), desc="Testing against circuit model"): | |||
a, b = np.random.randint(0, n - 1, 2) | |||
if a != b: | |||
g.act_cz(a, b) | |||
c.act_cz(a, b) | |||
assert np.allclose(np.sum(np.abs(c.state)**2), 1) | |||
assert np.allclose(np.sum(np.abs(g.to_state_vector().state)**2), 1) | |||
if not g.to_state_vector() == c: | |||
print g | |||
print a, b | |||
print "Circuit:" | |||
print g.to_state_vector() | |||
print "Graph:" | |||
print c | |||
raise ValueError | |||
assert np.allclose(np.sum(np.abs(c.state) ** 2), 1) | |||
assert np.allclose( | |||
np.sum(np.abs(g.to_state_vector().state) ** 2), 1) | |||
assert g.to_state_vector() == c | |||
assert g.to_state_vector() == c |
@@ -1,26 +1,15 @@ | |||
import json | |||
import numpy as np | |||
from abp import clifford, qi | |||
import sys | |||
import os | |||
import itertools as it | |||
from string import maketrans | |||
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(maketrans("{}", "[]")) | |||
return np.array(json.loads(s)) | |||
from abp import clifford, qi, anders_cz | |||
def test_cz_table(): | |||
""" Does our clifford code work with anders & briegel's table? """ | |||
state_table = clifford.get_state_table(clifford.unitaries) | |||
ab_cz_table = get_ab_cz_table() | |||
ab_cz_table = anders_cz.cz_table | |||
rows = it.product([0, 1], it.combinations_with_replacement(range(24), 2)) | |||
for bond, (c1, c2) in rows: | |||