diff --git a/.gitignore b/.gitignore index f39bd6d..6c7da33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -tables.pkl +*.pkl *.pdf papers/ # Project-specific diff --git a/clifford.py b/clifford.py index e1a612f..ef3ed8a 100644 --- a/clifford.py +++ b/clifford.py @@ -32,7 +32,7 @@ def name_of(vop): return "%s" % get_name[vop] if vop in get_name else "VOP%d" % vop -@cache_to_disk("tables.pkl") +@cache_to_disk("clifford_tables.pkl") def construct_tables(): """ Constructs / caches multiplication and conjugation tables """ by_name = {name: find_up_to_phase(u)[0] for name, u in qi.by_name.items()} @@ -51,8 +51,3 @@ elements = {"x": qi.sqx, "z": qi.msqz} unitaries = [compose_u(d) for d in decompositions] by_name, get_name, conjugation_table, times_table = construct_tables() - -if __name__ == '__main__': - print by_name - print get_name - diff --git a/cz.py b/cz.py deleted file mode 100644 index cfc60ea..0000000 --- a/cz.py +++ /dev/null @@ -1,48 +0,0 @@ -from graph import * -import viz -import itertools as it -import clifford - -def cphase(g, vops, a, b): - """ Act a controlled-phase gate on two qubits """ - if g[a]-{b}: remove_vop(g, vops, a, b) - if g[b]-{a}: remove_vop(g, vops, b, a) - if g[a]-{b}: remove_vop(g, vops, a, b) - edge = has_edge(g, a, b) - new_edge, vops[a], vops[b] = cphase_table[edge, vops[a], vops[b]] - if new_edge != edge: - toggle_edge(g, a, b) - - -def remove_vop(g, vops, a, avoid): - """ Reduces VOP[a] to the identity, avoiding (if possible) the use of vertex b as a swapping partner """ - others = g[a] - {avoid} - swap_qubit = others.pop() if others else avoid - for v in reversed(clifford.decompositions[vops[a]]): - local_complementation(g, vops, a if v == "x" else swap_qubit) - - -def local_complementation(g, vops, v): - """ As defined in LISTING 1 of Anders & Briegel """ - for i, j in it.combinations(g[v], 2): - toggle_edge(g, i, j) - - # Update VOPs - vops[v] = clifford.times_table[vops[v]][clifford.by_name["sqx"]] - for i in g[v]: - vops[i] = clifford.times_table[vops[i]][clifford.by_name["msqz"]] - - -if __name__ == '__main__': - g, vops = graph() - add_edge(g, 0, 1) - add_edge(g, 1, 2) - add_edge(g, 0, 2) - add_edge(g, 0, 3) - add_edge(g, 6, 7) - - pos = viz.draw(g, vops, "out.pdf") - remove_vop(g, vops, 0, 1) - remove_vop(g, vops, 1, 2) - cphase(g, vops, 0, 1) - viz.draw(g, vops, "out2.pdf", pos) diff --git a/cz_table.py b/cz_table.py new file mode 100644 index 0000000..882c8c9 --- /dev/null +++ b/cz_table.py @@ -0,0 +1,14 @@ +""" This part computes the CZ table """ + +from util import cache_to_disk +import qi +import numpy as np +from tqdm import tqdm +import clifford + +#@cache_to_disk("cz_table.pkl") +def construct_table(): + print "awd" + return "awd" + +cz_table = construct_table() diff --git a/graph.py b/graph.py index 0c1b28e..f0800dd 100644 --- a/graph.py +++ b/graph.py @@ -3,6 +3,7 @@ Provides an extremely basic graph structure, based on neighbour lists """ from collections import defaultdict +import itertools as it import clifford def graph(): @@ -39,3 +40,32 @@ def edgelist(g): for n in v) return [tuple(e) for e in edges] +def cphase(g, vops, a, b): + """ Act a controlled-phase gate on two qubits """ + if g[a]-{b}: remove_vop(g, vops, a, b) + if g[b]-{a}: remove_vop(g, vops, b, a) + if g[a]-{b}: remove_vop(g, vops, a, b) + edge = has_edge(g, a, b) + new_edge, vops[a], vops[b] = cphase_table[edge, vops[a], vops[b]] + if new_edge != edge: + toggle_edge(g, a, b) + + +def remove_vop(g, vops, a, avoid): + """ Reduces VOP[a] to the identity, avoiding (if possible) the use of vertex b as a swapping partner """ + others = g[a] - {avoid} + swap_qubit = others.pop() if others else avoid + for v in reversed(clifford.decompositions[vops[a]]): + local_complementation(g, vops, a if v == "x" else swap_qubit) + + +def local_complementation(g, vops, v): + """ As defined in LISTING 1 of Anders & Briegel """ + for i, j in it.combinations(g[v], 2): + toggle_edge(g, i, j) + + # Update VOPs + vops[v] = clifford.times_table[vops[v]][clifford.by_name["sqx"]] + for i in g[v]: + vops[i] = clifford.times_table[vops[i]][clifford.by_name["msqz"]] + diff --git a/pseudocode.txt b/pseudocode.txt deleted file mode 100644 index b83296b..0000000 --- a/pseudocode.txt +++ /dev/null @@ -1,55 +0,0 @@ -cphase (vertex a, vertex b): - if ngbh a\{b} =/= {}: - remove VOP (a, b) - end if - if ngbh b\{a} =/= {}: - remove VOP (b, a) - end if - [It may happen that the condition in line 2 has not been fulfilled then, but is now due to the effect of line 5. So we check again:] - if ngbh a\{b} =/= {}: - remove VOP (a, b) - end if - [Now we can be sure that the the condition (ngbh c\{a, b} = {} or VOP[c] ∈ Z) is fulfilled for c = a, b and we may use the lookup table (cf. Eq. (9)).] - if {a, b} ∈ E : - edge ← true - else: - edge ← false - end if - (edge, VOP[a], VOP[b]) ← cphase_table[edge, VOP[a], VOP[b]] - - -remove_VOP (vertex a, vertex b): - [This reduces VOP[a] to I, avoiding (if possible) to use b as swapping partner.] - [First, we choose a swapping partner c.] - if ngbh a\{b} = {}: - c ← any element of ngbh a\{b} - else: - c←b - end if - d ← decomposition lookup table [a] - [c contains now a decomposition such as Eq. (7)] - for v from last factor of d to first factor of d - if v = −iX: - local complementation (a) - else: ( this means that v = iZ) - local complementation (b) - end if - [Now, VOP[a] = I.] - - -local complementation (vertex a) - [performs the operation specified in Definition 4] - nv ← ngbh v - for i ∈ nv : - for j ∈ nv : - if i < j: - if (i, j) ∈ E: - remove edge (i, j) - else: - add edge (i, j) - end if - end if - end for - VOP[i] ← VOP[i]sqrt(−iZ) - VOP[v] ← VOP[v]sqrt(iX) - end for diff --git a/tests/test_cz.py b/tests/test_cz.py index 06126a2..f7caafc 100644 --- a/tests/test_cz.py +++ b/tests/test_cz.py @@ -1,6 +1,4 @@ -import cz from graph import * -import viz def test_local_complementation(): """ Test that local complementation works as expected """ @@ -9,7 +7,7 @@ def test_local_complementation(): add_edge(g, 0, 2) add_edge(g, 1, 2) add_edge(g, 0, 3) - cz.local_complementation(g, vops, 0) + local_complementation(g, vops, 0) assert has_edge(g, 0, 1) assert has_edge(g, 0, 2) assert not has_edge(g, 1, 2) diff --git a/util.py b/util.py index 3886083..810fb53 100644 --- a/util.py +++ b/util.py @@ -1,9 +1,17 @@ """ -Provides a decorator to cache function output to disk +Useful but messy crap """ import cPickle +import networkx as nx +from matplotlib import pyplot as plt +from graph import * +import clifford +import numpy as np + +VOP_COLORS = ["red", "green", "blue", "orange", "yellow", "purple", "black", "white"] def cache_to_disk(file_name): + """ A decorator to cache the output of a function to disk """ def wrap(func): def modified(*args, **kwargs): try: @@ -15,3 +23,23 @@ def cache_to_disk(file_name): return output return modified return wrap + + +def draw(graph, vops, filename="out.pdf", pos=None, ns=500): + """ Draw a graph with networkx layout """ + plt.clf() + g = nx.from_edgelist(edgelist(graph)) + pos = nx.spring_layout(g) if pos==None else pos + colors = [VOP_COLORS[vop % len(VOP_COLORS)] for vop in vops] + nx.draw_networkx_nodes(g, pos, node_color="white", node_size=ns) + nx.draw_networkx_nodes(g, pos, node_color=colors, node_size=ns, alpha=.4) + nx.draw_networkx_edges(g, pos, edge_color="gray") + nx.draw_networkx_labels(g, pos, font_family="FreeSans") + + labels = {i: clifford.name_of(vops[i]) for i in g.nodes()} + pos = {k: v + np.array([0, -.1]) for k, v in pos.items()} + nx.draw_networkx_labels(g, pos, labels, font_family="FreeSans") + plt.axis('off') + plt.savefig(filename) + return pos + diff --git a/viz.py b/viz.py deleted file mode 100644 index ab9f643..0000000 --- a/viz.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Utility function for plotting graphs nicely -""" - -import networkx as nx -from matplotlib import pyplot as plt -from graph import * -import clifford -import numpy as np - -VOP_COLORS = ["red", "green", "blue", "orange", "yellow", "purple", "black", "white"] - -def draw(graph, vops, filename="out.pdf", pos=None, ns=500): - """ Draw a graph with networkx layout """ - plt.clf() - g = nx.from_edgelist(edgelist(graph)) - pos = nx.spring_layout(g) if pos==None else pos - colors = [VOP_COLORS[vop % len(VOP_COLORS)] for vop in vops] - nx.draw_networkx_nodes(g, pos, node_color="white", node_size=ns) - nx.draw_networkx_nodes(g, pos, node_color=colors, node_size=ns, alpha=.4) - nx.draw_networkx_edges(g, pos, edge_color="gray") - nx.draw_networkx_labels(g, pos, font_family="FreeSans") - - labels = {i: clifford.name_of(vops[i]) for i in g.nodes()} - pos = {k: v + np.array([0, -.1]) for k, v in pos.items()} - nx.draw_networkx_labels(g, pos, labels, font_family="FreeSans") - plt.axis('off') - plt.savefig(filename) - return pos -