Browse Source

Loadsa stuff. CZ table bodging

master
Pete Shadbolt 8 years ago
parent
commit
ec403d4c30
10 changed files with 90 additions and 101 deletions
  1. +15
    -11
      abp/clifford.py
  2. +45
    -39
      abp/graphstate.py
  3. +12
    -0
      demograph.py
  4. +1
    -1
      tests/test_against_anders_and_briegel.py
  5. +7
    -0
      tests/test_against_circuit_model.py
  6. +5
    -15
      tests/test_graph.py
  7. +3
    -14
      tests/test_json.py
  8. +1
    -12
      tests/test_layout.py
  9. +0
    -8
      tests/test_quantum.py
  10. +1
    -1
      tests/test_viz.py

+ 15
- 11
abp/clifford.py View File

@@ -52,18 +52,22 @@ def find_cz(bond, c1, c2, commuters, state_table, ab_cz_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
#options = set() # TODO: remove and put in a test
options = set() # TODO: remove and put in a test
for bondp, c1p, c2p in it.product([0, 1], s1, s2): for bondp, c1p, c2p in it.product([0, 1], s1, s2):
if np.allclose(target, state_table[bondp, c1p, c2p]): if np.allclose(target, state_table[bondp, c1p, c2p]):
return bondp, c1p, c2p
#options.add((bondp, c1p, c2p))
# return bondp, c1p, c2p
options.add((bondp, c1p, c2p))


#TODO fix this bull shit
#assert tuple(ab_cz_table[bond, c1, c2]) in options
#return ab_cz_table[bond, c1, c2]
# TODO fix this bull shit
# assert tuple(ab_cz_table[bond, c1, c2]) in options
options = sorted(options, key=lambda (a, b, c): a*10000 + b*100 + c*1)
if not np.all(ab_cz_table[bond, c1, c2] == options[0]):
print ab_cz_table[bond, c1, c2], options[0]

return ab_cz_table[bond, c1, c2]


# 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):
@@ -125,7 +129,7 @@ def get_cz_table(unitaries):
rows = list( rows = list(
it.product([0, 1], it.combinations_with_replacement(range(24), 2))) 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", disable=True):
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, ab_cz_table)
cz_table[bond, c1, c2] = [newbond, c1p, c2p] cz_table[bond, c1, c2] = [newbond, c1p, c2p]
@@ -146,13 +150,13 @@ def get_ab_cz_table():
# scratch and store # scratch and store
os.chdir(tempfile.gettempdir()) os.chdir(tempfile.gettempdir())
try: try:
if __name__=="__main__":
if __name__ == "__main__":
raise IOError raise IOError
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()
cz_table = np.load("cz_table.npy")
# cz_table = get_ab_cz_table()


with open("by_name.json") as f: with open("by_name.json") as f:
by_name = json.load(f) by_name = json.load(f)


+ 45
- 39
abp/graphstate.py View File

@@ -2,7 +2,6 @@
Provides an extremely basic graph structure, based on neighbour lists Provides an extremely basic graph structure, based on neighbour lists
""" """


from collections import defaultdict
import itertools as it import itertools as it
import clifford import clifford
import json import json
@@ -15,26 +14,34 @@ except ImportError:


class GraphState(object): class GraphState(object):


def __init__(self):
self.ngbh = defaultdict(set)
self.vops = defaultdict(int)
self.meta = defaultdict(dict)
def __init__(self, nodes = []):
self.ngbh = {}
self.vops = {}
self.meta = {}
self.add_nodes(nodes)


def add_node(self, v): def add_node(self, v):
""" Add a node if it doesn't already exist """ """ Add a node if it doesn't already exist """
if not v in self.ngbh: if not v in self.ngbh:
self.ngbh[v] = set() self.ngbh[v] = set()
self.vops[v] = clifford.by_name["hadamard"] self.vops[v] = clifford.by_name["hadamard"]
self.meta[v] = dict()

def add_nodes(self, nodes):
""" Add a buncha nodes """
for n in nodes:
self.add_node(n)


def add_edge(self, v1, v2): def add_edge(self, v1, v2):
""" Add an edge between two vertices in the self """ """ Add an edge between two vertices in the self """
if not v1 in self.ngbh:
self.vops[v1] = clifford.by_name["hadamard"]
if not v2 in self.ngbh:
self.vops[v2] = clifford.by_name["hadamard"]
self.ngbh[v1].add(v2) self.ngbh[v1].add(v2)
self.ngbh[v2].add(v1) self.ngbh[v2].add(v1)


def add_edges(self, edges):
""" Add a buncha edges """
for (v1, v2) in edges:
self.add_edge(v1, v2)

def del_edge(self, v1, v2): def del_edge(self, v1, v2):
""" Delete an edge between two vertices in the self """ """ Delete an edge between two vertices in the self """
self.ngbh[v1].remove(v2) self.ngbh[v1].remove(v2)
@@ -70,7 +77,8 @@ class GraphState(object):
for i, j in it.combinations(self.ngbh[v], 2): for i, j in it.combinations(self.ngbh[v], 2):
self.toggle_edge(i, j) self.toggle_edge(i, j)


# Update VOPs: TODO check ordering and replace by self.act_local_rotation
# Update VOPs: TODO check ordering and replace by
# self.act_local_rotation
self.vops[v] = clifford.times_table[ self.vops[v] = clifford.times_table[
self.vops[v]][clifford.by_name["sqx"]] self.vops[v]][clifford.by_name["sqx"]]
for i in self.ngbh[v]: for i in self.ngbh[v]:
@@ -79,7 +87,7 @@ class GraphState(object):


def act_local_rotation(self, a, op): def act_local_rotation(self, a, op):
""" Act a local rotation """ """ Act a local rotation """
self.vops[a] = clifford.times_table[op,self.vops[a]]
self.vops[a] = clifford.times_table[op, self.vops[a]]


def act_local_rotation_by_name(self, qubit, name): def act_local_rotation_by_name(self, qubit, name):
""" Shorthand """ """ Shorthand """
@@ -99,14 +107,14 @@ class GraphState(object):
if self.ngbh[a] - {b}: if self.ngbh[a] - {b}:
self.remove_vop(a, b) self.remove_vop(a, b)
edge = self.has_edge(a, b) edge = self.has_edge(a, b)
new_edge, self.vops[a], self.vops[b] = clifford.cz_table[edge, self.vops[a], self.vops[b]]
new_edge, self.vops[a], self.vops[
b] = clifford.cz_table[edge, self.vops[a], self.vops[b]]
if new_edge != edge: if new_edge != edge:
self.toggle_edge(a, b) self.toggle_edge(a, b)



def measure_z(self, node, force = None):
def measure_z(self, node, force=None):
""" Measure the graph in the Z-basis """ """ Measure the graph in the Z-basis """
res = force if force else np.random.choice([0,1])
res = force if force else np.random.choice([0, 1])


# Disconnect # Disconnect
for neighbour in self.ngbh[node]: for neighbour in self.ngbh[node]:
@@ -123,15 +131,14 @@ class GraphState(object):


return res return res



def measure_x(self, i): def measure_x(self, i):
""" Measure the graph in the X-basis """ """ Measure the graph in the X-basis """
#TODO
# TODO
pass pass


def measure_y(self, i): def measure_y(self, i):
""" Measure the graph in the Y-basis """ """ Measure the graph in the Y-basis """
#TODO
# TODO
pass pass


def order(self): def order(self):
@@ -140,22 +147,22 @@ class GraphState(object):


def __str__(self): def __str__(self):
""" Represent as a string for quick debugging """ """ Represent as a string for quick debugging """
vopstr = {key: clifford.get_name(value) for key,value in self.vops.items()}
nbstr = str(dict(self.ngbh))
vopstr = {key: clifford.get_name(value)
for key, value in self.vops.items()}
nbstr = str(self.ngbh)
return "graph:\n vops: {}\n ngbh: {}\n".format(vopstr, nbstr) return "graph:\n vops: {}\n ngbh: {}\n".format(vopstr, nbstr)


def to_json(self): def to_json(self):
""" Convert the graph to JSON form """ """ Convert the graph to JSON form """
#ngbh = {key: tuple(value) for key, value in self.ngbh.items()}
meta = {key: value for key, value in self.meta.items()} meta = {key: value for key, value in self.meta.items()}
edge = self.edgelist() edge = self.edgelist()
return json.dumps({"vops": self.vops, "edge": edge, "meta": meta})
return json.dumps({"nodes": self.vops, "edges": edge, "meta": meta})


def to_networkx(self): def to_networkx(self):
""" Convert the graph to a networkx graph """ """ Convert the graph to a networkx graph """
g = nx.Graph() g = nx.Graph()
g.edge = {node: {neighbour: {} for neighbour in neighbours}
for node, neighbours in self.ngbh.items()}
g.edge = {node: {neighbour: {} for neighbour in neighbours}
for node, neighbours in self.ngbh.items()}
g.node = {node: {"vop": vop} for node, vop in self.vops.items()} g.node = {node: {"vop": vop} for node, vop in self.vops.items()}
for node, metadata in self.meta.items(): for node, metadata in self.meta.items():
g.node[node].update(metadata) g.node[node].update(metadata)
@@ -163,28 +170,29 @@ class GraphState(object):


def to_state_vector(self): def to_state_vector(self):
""" Get the full state vector """ """ Get the full state vector """
if not len(self.vops)<10:
if len(self.vops) > 15:
raise ValueError("Cannot build state vector: too many qubits") raise ValueError("Cannot build state vector: too many qubits")
output = qi.CircuitModel(len(self.vops))
#print output
state = qi.CircuitModel(len(self.vops))
for i in range(len(self.vops)): for i in range(len(self.vops)):
output.act_hadamard(i)
#print output
state.act_hadamard(i)
for i, j in self.edgelist(): for i, j in self.edgelist():
output.act_cz(i, j)
#print output
state.act_cz(i, j)
for i, u in self.vops.items(): for i, u in self.vops.items():
output.act_local_rotation(i, clifford.unitaries[u])
return output
state.act_local_rotation(i, clifford.unitaries[u])
return state


def layout(self): def layout(self):
""" Automatically lay out the graph """ """ Automatically lay out the graph """
g = self.to_networkx() g = self.to_networkx()
pos = nx.spring_layout(g, dim=3, scale=10) pos = nx.spring_layout(g, dim=3, scale=10)
average = lambda axis: sum(p[axis] for p in pos.values())/float(len(pos))
average = lambda axis: sum(p[axis]
for p in pos.values()) / float(len(pos))
ax, ay, az = average(0), average(1), average(2) ax, ay, az = average(0), average(1), average(2)
for key, (x, y, z) in pos.items(): for key, (x, y, z) in pos.items():
self.meta[key]["pos"] = {"x": round(x-ax, 0), "y": round(y-ay, 0), "z": round(z-az, 0)}
self.meta[key]["pos"] = {
"x": round(x - ax, 0),
"y": round(y - ay, 0),
"z": round(z - az, 0)}


def to_stabilizer(self): def to_stabilizer(self):
""" Get the stabilizer of this graph """ """ Get the stabilizer of this graph """
@@ -200,7 +208,7 @@ class GraphState(object):
output += " I " output += " I "
output += "\n" output += "\n"
return output return output
def adj_list(self): def adj_list(self):
""" For comparison with Anders and Briegel's C++ implementation """ """ For comparison with Anders and Briegel's C++ implementation """
rows = [] rows = []
@@ -209,7 +217,5 @@ class GraphState(object):
vop = clifford.get_name(vop) vop = clifford.get_name(vop)
s = "Vertex {}: VOp {}, neighbors {}".format(key, vop, ngbh) s = "Vertex {}: VOp {}, neighbors {}".format(key, vop, ngbh)
rows.append(s) rows.append(s)
return " \n".join(rows)+ " \n"

return " \n".join(rows) + " \n"



+ 12
- 0
demograph.py View File

@@ -0,0 +1,12 @@
from abp.graphstate import GraphState

def demograph():
""" A graph for testing with """
g = GraphState([0,1,2,3,100,200])
g.add_edge(0, 1)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(0, 3)
g.add_edge(100, 200)
return g


+ 1
- 1
tests/test_against_anders_and_briegel.py View File

@@ -5,7 +5,7 @@ import difflib
import re import re


def compare(a, b): def compare(a, b):
""" Sketchy as you like. Remove this abomination """
""" TODO: Sketchy as you like. Remove this abomination """
aa = a.get_adj_list() aa = a.get_adj_list()
bb = b.adj_list() bb = b.adj_list()
try: try:


+ 7
- 0
tests/test_against_circuit_model.py View File

@@ -0,0 +1,7 @@
from abp.graphstate import GraphState
from anders_briegel import graphsim
import random
from abp import qi

def single_qubit_test():
""" A single qubit test """

+ 5
- 15
tests/test_graph.py View File

@@ -1,19 +1,9 @@
from abp.graphstate import GraphState from abp.graphstate import GraphState
from abp import clifford from abp import clifford
from demograph import demograph
import time import time




def demograph():
""" A graph for testing with """
g = GraphState()
g.add_edge(0, 1)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(0, 3)
g.add_edge(100, 200)
return g


def test_graph_basic(): def test_graph_basic():
""" Test that we can construct graphs, delete edges, whatever """ """ Test that we can construct graphs, delete edges, whatever """
g = demograph() g = demograph()
@@ -59,18 +49,18 @@ def test_edgelist():
assert (100, 200) in el assert (100, 200) in el




def test_stress():
def test_stress(n = int(1e5)):
""" Testing that making a graph of ten thousand qubits takes less than half a second""" """ Testing that making a graph of ten thousand qubits takes less than half a second"""
g = GraphState()
g = GraphState(range(n+1))
t = time.clock() t = time.clock()
for i in xrange(100000):
for i in xrange(n):
g.add_edge(i, i + 1) g.add_edge(i, i + 1)
assert time.clock() - t < .5 assert time.clock() - t < .5




def test_cz(): def test_cz():
""" Test CZ gate """ """ Test CZ gate """
g = GraphState()
g = GraphState([0, 1])
g.add_node(0) g.add_node(0)
g.add_node(1) g.add_node(1)
g.act_local_rotation(0, clifford.by_name["hadamard"]) g.act_local_rotation(0, clifford.by_name["hadamard"])


+ 3
- 14
tests/test_json.py View File

@@ -1,26 +1,15 @@
from abp.graphstate import GraphState from abp.graphstate import GraphState
from abp import clifford from abp import clifford
from demograph import demograph
import time import time
import json import json



def demograph():
""" A graph for testing with """
g = GraphState()
g.add_edge(0, 1)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(0, 3)
g.add_edge(100, 200)
return g


def test_json_basic(): def test_json_basic():
""" Test that we can export to JSON """ """ Test that we can export to JSON """
g = demograph() g = demograph()
js = g.to_json() js = g.to_json()
assert "edge" in js
assert "vops" in js
assert "edges" in js
assert "nodes" in js
json.loads(js) json.loads(js)





+ 1
- 12
tests/test_layout.py View File

@@ -1,15 +1,4 @@
from abp.graphstate import GraphState

def demograph():
""" A graph for testing with """
g = GraphState()
g.add_edge(0, 1)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(0, 3)
g.add_edge(100, 200)
return g

from demograph import demograph


def test_nx_convert(): def test_nx_convert():
g = demograph() g = demograph()


+ 0
- 8
tests/test_quantum.py View File

@@ -1,8 +0,0 @@
from abp.graphstate import GraphState

def test_logic_101():
""" Some really simple tests """
g = GraphState()
g.act_local_rotation_by_name(0, "hadamard")
#print g.


+ 1
- 1
tests/test_viz.py View File

@@ -3,7 +3,7 @@ from abp import viz




def test_viz(): def test_viz():
g = GraphState()
g = GraphState(range(4)+[100, 200])
g.add_edge(0, 1) g.add_edge(0, 1)
g.add_edge(1, 2) g.add_edge(1, 2)
g.add_edge(2, 0) g.add_edge(2, 0)


Loading…
Cancel
Save